feat(samba): lifecycle — ensureSamba/ReconcileSamba/password/disable (R-7 slice 1, Part 2)

ensureSamba joins EnsureBaseStack after filebrowser, gated on SMB.Enabled
(cloudflared conditional precedent); reconcile is idempotent (unchanged config +
running container = ZERO compose calls, asserted via seam). Atomic tmp+fsync+
rename config writes. Password applied via smbpasswd on STDIN (never argv/log/
settings). Disable = compose down, volumes + folders KEPT. samba added to
IsProtectedStack in code (controller.yaml is golden-generated and predates it),
which also makes the app-backup loops correctly skip it.
This commit is contained in:
2026-07-18 11:30:04 +02:00
parent b0c5ef4823
commit 0dcbea90b2
5 changed files with 600 additions and 1 deletions
+9
View File
@@ -71,6 +71,15 @@ func (m *Manager) EnsureBaseStack() error {
errs = append(errs, fmt.Sprintf("filebrowser: %v", err))
}
// samba (LAN network-sharing, R-7) — conditional deploy, same shape as cloudflared: only when the
// customer turned the feature on. reconcileSambaAt additionally holds off until a household SMB
// password exists. Deployed LAST (it joins no docker network — host networking by spike mandate).
if m.settings != nil && m.settings.GetSMBSettings().Enabled {
if err := m.ensureSamba(filepath.Join(base, SambaStackName)); err != nil {
errs = append(errs, fmt.Sprintf("samba: %v", err))
}
}
if len(errs) > 0 {
return fmt.Errorf("base-infra bring-up: %s", strings.Join(errs, "; "))
}