v0.332.0: one sign-in for the file manager — a dashboard pass, a host-only files cookie, a per-box secret header (R-1100, operator D16)
gates / gates (push) Successful in 47s

This commit is contained in:
2026-10-19 04:56:56 +02:00
parent ba4a6f060b
commit 9bdd8f8fe8
21 changed files with 1078 additions and 54 deletions
+15 -3
View File
@@ -274,7 +274,7 @@ func (m *Manager) ensureFileBrowser(dir string) error {
// import source here without its bind would produce a source with no path behind it — a broken
// sidebar entry — so both halves are deliberately deferred to the same place.
compose := infra.RenderFileBrowserCompose(m.cfg.Customer.Domain, nil)
config := infra.RenderFileBrowserConfig(nil, false)
config := infra.RenderFileBrowserConfigKept(nil, false, "", m.fileBrowserSSO())
if err := os.WriteFile(composePath, []byte(compose), 0o644); err != nil {
return fmt.Errorf("write docker-compose.yml: %w", err)
}
@@ -296,16 +296,28 @@ func (m *Manager) ensureFileBrowserRoute(traefikDir string) error {
return fmt.Errorf("mkdir dynamic: %w", err)
}
path := filepath.Join(dynDir, "filebrowser.yml")
want := infra.RenderFileBrowserRoute(domain)
sso := m.fileBrowserSSO()
want := infra.RenderFileBrowserRoute(domain, sso.Header)
if cur, err := os.ReadFile(path); err != nil || string(cur) != want {
if err := os.WriteFile(path, []byte(want), 0o644); err != nil {
return fmt.Errorf("write filebrowser route: %w", err)
}
m.logger.Printf("[INFO] [infra] wrote filebrowser route → %s (Host files.%s → filebrowser:80 by name, R-1126)", path, domain)
m.logger.Printf("[INFO] [infra] wrote filebrowser route → %s (Host files.%s → filebrowser:80 by name, R-1126; one sign-in %v, R-1100)", path, domain, sso.Header != "")
}
return nil
}
// fileBrowserSSO is this box's header sign-in for FileBrowser (R-1100): the same secret name for its config and for
// traefik's route. An error = none (the pre-R-1100 files) and a WARN; the name itself is never logged.
func (m *Manager) fileBrowserSSO() infra.FileBrowserSSO {
sso, err := infra.FileBrowserSSOFor(m.cfg.Paths.DataDir, m.cfg.Customer.Domain)
if err != nil {
m.logger.Printf("[WARN] [infra] filebrowser: no one sign-in (R-1100): %v — FileBrowser asks for its own password", err)
return infra.FileBrowserSSO{}
}
return sso
}
// ensureServersTransports writes the traefik file-provider dynamic config defining named backend
// transports (the insecure-skip-verify transport for self-signed HTTPS backends like Crafty). Like
// wireController, it writes only when the content changes so the traefik file watcher doesn't reload