docs: first-run restore generates new secrets over a backup holding the old ones
Restoring a real 13-app repository onto a fresh install: 11 came back working. matrix failed because its install hook writes homeserver.yaml with the new DB secret and the restore then lays the old one back over it; stoat failed because rabbit's mnesia dir restores raw and the broker only honours RABBITMQ_DEFAULT_PASS on an empty data dir. Apps with a dump descriptor are unaffected — those clear the data dir so the engine initialises with the current secret, then replay the dump. That is the tell for what the general fix has to look like. Not implemented: applying the restored system config on first run changes what a restore does with credentials (including the WebUI login), which is a decision, not a defect. Written up as §3.6 with a recommendation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
95edf64558
commit
d0735ea9ba
@ -264,6 +264,54 @@ Anything unexpected — no subuid range, no `newuidmap`, a namespace that will n
|
||||
start — falls back to running the command plainly, which is what happened before
|
||||
any of this existed.
|
||||
|
||||
### 3.6 — Open: a fresh install generates new secrets, the backup carries the old ones
|
||||
|
||||
Found by restoring a real 13-app repository onto a purpose-built install
|
||||
(storage-locations §12.5, case 4). 11 of 13 apps came back working. The two that
|
||||
did not failed the same way for two different reasons, and the reason is
|
||||
structural rather than a bug in either app.
|
||||
|
||||
**A first-run restore generates fresh credentials, then restores state that
|
||||
encodes the old ones.** Install randomises every `CFG_*_PASSWORD`; the backup
|
||||
contains a machine that used different ones. Wherever a secret is written into
|
||||
something the restore then lays down, the two disagree:
|
||||
|
||||
| app | what disagreed | result |
|
||||
|---|---|---|
|
||||
| `matrix` | the install hook writes `homeserver.yaml` from `CFG_MATRIX_DB_PASSWORD_1` at step 3, and step 6 restores the snapshot *over* it | `password authentication failed for user "synapse"` — postgres was initialised with the new secret, the restored config file holds the old one |
|
||||
| `stoat` | `data/rabbit/mnesia` restores raw, and rabbit only honours `RABBITMQ_DEFAULT_PASS` on an **empty** data dir | `ACCESS_REFUSED` — four dependent services exit 101 |
|
||||
|
||||
Apps with a **dump descriptor** are unaffected, and that is the tell: for those,
|
||||
`restoreDbRehydratePreStart` clears the data dir so the engine initialises with
|
||||
the current secret, then replays the dump into it. Everything else — a config
|
||||
file inside the app dir, a broker's own user database — keeps the old value.
|
||||
|
||||
Three ways out:
|
||||
|
||||
1. **Apply the restored system config on first run** instead of only staging it.
|
||||
The backup's `configs/` holds the original secrets, so adopting them makes
|
||||
every restored app consistent by construction. `backupRestoreSystemConfig`
|
||||
deliberately stages rather than applies — *"recovering creds/settings is a
|
||||
review-then-copy step, never an automatic blast over a running control
|
||||
plane"* — and that is right for a **running** box and wrong for a **fresh**
|
||||
one. The code currently cannot tell those two situations apart. This is §9.1
|
||||
restated with a concrete failure behind it, and it carries a real
|
||||
consequence: it also restores the WebUI login, so the user signs in to the
|
||||
new machine with the old password. Probably expected; must be said out loud.
|
||||
2. **Re-run app config generation after the data restore.** Fixes matrix. Does
|
||||
nothing for stoat, where the secret lives inside restored *service state*
|
||||
rather than a generated file — so it is not sufficient on its own.
|
||||
3. **Reset the credential in the restored service** (`ALTER ROLE`,
|
||||
`rabbitmqctl change_password`). Per-engine, fragile, and needs a hook per
|
||||
backing service.
|
||||
|
||||
Recommendation: **(1)**, gated on first run specifically — the flag already
|
||||
exists as `init_mode=restore`. (2) is a reasonable belt-and-braces addition; (3)
|
||||
is a last resort for services whose state cannot be re-initialised.
|
||||
|
||||
Not implemented here: it changes what a restore does with credentials, which is
|
||||
a decision rather than a defect.
|
||||
|
||||
## 4. The password problem, stated plainly
|
||||
|
||||
**An encrypted repository cannot be opened with anything inside itself.** `CFG_BACKUP_LOC_<idx>_PASSWORD` lives in the system config — which is *inside the backup*. So on a fresh machine the user must supply the repository password by hand. There is no way around this and it is not a bug; it is what encryption means.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user