Skip to content

fix: recover per-app config after database loss instead of deleting it - #126

Merged
vazra merged 5 commits into
mainfrom
fix/dr-sidecar-recovery
Oct 11, 2026
Merged

vazra merged 5 commits into
mainfrom
fix/dr-sidecar-recovery

Conversation

@vazra

@vazra vazra commented Oct 11, 2026

Copy link
Copy Markdown
Owner

Found by un-skipping the disaster-recovery E2E spec (26a), which had been skipped with a TODO.

Bug: after the database was lost and SimpleDeploy restarted, boot ran PruneOrphanSidecars before the reconciler re-created app rows. With an empty apps table every <app>/simpledeploy.yml looked orphaned and was deleted, so alert rules, backup configs and access grants were lost, contrary to docs/operations/config-sidecars.md. Server log on restart:

[configsync] imported global sidecar into empty DB
[configsync] pruned orphan sidecars for: [dr-nginx]

Fix

  • A sidecar is an orphan only when its folder has no docker-compose.yml, no app row (active or archived) and no archive tombstone. Nothing is pruned while the DB has no apps, or when a check fails; a stale file is safer than lost config.
  • ReconcileDBFromFS skips apps without a row (the reconciler creates the row and imports the sidecar).
  • A DR import of config.yml marks the first-boot seed done, so a failed or partial import can no longer overwrite config.yml/secrets.yml from the partial DB.

Tests: configsync recovery tests, reconciler recovery after DB wipe with boot-time prune, a CLI boot-sequence test (DB wipe, restart, config restored), malformed config.yml guard. Full go test ./... passes.

Docs: config-sidecars.md corrected (file layout incl. secrets.yml and simpledeploy.secrets.yml, file modes, prune rule).

vazra added 5 commits October 11, 2026 02:35
PruneOrphanSidecars ran on boot before the reconciler re-created app rows,
so on an empty DB every app's simpledeploy.yml was deleted. A sidecar is now
an orphan only when its folder has no docker-compose.yml, no app row and no
tombstone, and nothing is pruned while the DB has no apps.

ReconcileDBFromFS skips apps without a row (the reconciler imports them).
A DR import of config.yml marks the first-boot seed done so a failed import
can no longer overwrite config.yml/secrets.yml from the partial DB.
Move serve's boot-time configsync steps into initConfigSync and
reloadConfigFromFS (same order) so a test can run them.
…ne rule)

config-sidecars.md claimed config.yml holds bcrypt hashes at 0600 and that
master_secret lives in data_dir/.secret; hashes are in secrets.yml (0600),
config.yml/simpledeploy.yml are 0644, master_secret is in config.yaml.
Document secrets sidecars, the orphan prune rule, the reconciler-driven
per-app import, and that files win over the DB.
@vazra
vazra merged commit 816d632 into main Oct 11, 2026
8 checks passed
@vazra
vazra deleted the fix/dr-sidecar-recovery branch October 11, 2026 17:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant