Night 2026-10-17: restore keeps the DB password (R-1106, 07 §7.4), restic 0.19.1, hardening; 8 rows closed, 7 filed; evidence
gates / gates (push) Successful in 6m57s
gates / gates (push) Successful in 6m57s
This commit is contained in:
@@ -952,7 +952,7 @@ rather than being folded into a neighbour. Where the warning is SHOWN on the das
|
||||
**[DESIGN] restic is a pinned decision, never „whatever the OS ships".** Until v0.322.0 it came from the runtime's apt
|
||||
list, so a base-image move (Debian 12 → 13) would have swapped restic 0.14.0 for 0.18.0 under the off-site code with
|
||||
nobody choosing it. Since v0.323.0 the controller image carries the **official restic release binary** of one version
|
||||
(`ARG RESTIC_VERSION`, today **0.18.1**), checked at build time against restic's signed `SHA256SUMS` (vendored release
|
||||
(`ARG RESTIC_VERSION`, **0.19.1** since controller v0.324.0 — 0.18.1 in v0.323.0; operator decision 2A, R-1107), checked at build time against restic's signed `SHA256SUMS` (vendored release
|
||||
key, no keyserver) and against a per-architecture sum pinned in the Dockerfile; any mismatch fails the build. The
|
||||
Proxmox hosts run no restic at all (measured on all three test hosts): the agent's escrow path only stores and returns
|
||||
the repository password, and every restic call happens in the guest.
|
||||
@@ -964,7 +964,7 @@ holds REAL outputs of each version the code was checked against (captured on one
|
||||
|
||||
| What the code relies on | 0.18.1 |
|
||||
|---|---|
|
||||
| a missing source path is skipped with a warning, exit 0 (§6.3, SP-3.4); an unreadable file exits 3 | same |
|
||||
| a missing source path is skipped with a warning, exit 0 (§6.3, SP-3.4); an unreadable file exits 3 | 0.18.1 same; **0.19.1 exits 3 for a missing top-level path** (restic #4467) — the capture's stat-filter keeps such paths out of argv, so only a path vanishing in between reaches it, and that race now reads as the app's failure instead of a silent partial copy |
|
||||
| `backup --json` status lines (`percent_done`, totals, `current_files`) | same field names |
|
||||
| `snapshots --json`, `snapshots latest --tag … --json`, `stats <id>` / `--mode raw-data` | same shapes (new fields only) |
|
||||
| the §6.7 classes: wrong password, no repository, refused port / key, unreachable host, dead rclone ssh | same class each |
|
||||
@@ -975,8 +975,10 @@ holds REAL outputs of each version the code was checked against (captured on one
|
||||
| a store written by both: 0.14.0 reads and restores a 0.18.1 snapshot after a 0.18.1 `forget --prune`; 0.18.1 restores a 0.14.0 snapshot | proven on a scratch store; on demo-hp's real store both directions are proven (byte-identical trees); 0.14.0 reading after a 0.18.1 prune there waits for the store's next weekly clean-up window |
|
||||
|
||||
Exit codes changed (10 no repository, 11 locked, 12 wrong password); nothing in the controller reads a restic exit code.
|
||||
**Open:** the 0.18.1 binary is built with Go 1.25.1 and carries 50 fixable scanner findings (R-1107 — the operator's
|
||||
choice of 0.19.x).
|
||||
The 0.19.1 re-proof (2026-10-16 night): its notes read for every row above; fixtures for 0.14.0, 0.18.1 and 0.19.1
|
||||
recaptured from one shared store; `TestR1105_*` runs each version against 0.14.0 — same classes, same JSON, the same
|
||||
forget plan as 0.18.1. The 0.18.1 binary (Go 1.25.1) carried 50 fixable scanner findings; 0.19.1 (Go 1.26.4) is the
|
||||
reason for the move (`audits/night-restore-2026-10-17/P2/`).
|
||||
|
||||
## 7. The recovery chain (D3) — the reason this document exists
|
||||
|
||||
@@ -1153,6 +1155,28 @@ password would have failed. Separately, Grafana's `type: password` admin login w
|
||||
the sentinel value was live in the container and encrypted in the guest, and appeared in **0 files**
|
||||
anywhere under the backup namespace. Full record: `audits/D5-drive-alone-restore-2026-07-30.md`.
|
||||
|
||||
**[DESIGN — operator decision 1A, 2026-10-16 21:57; built in controller v0.324.0 — R-1106, R-127 (b)] A restored
|
||||
database comes back with the password it was saved with.** A database engine reads `POSTGRES_PASSWORD`,
|
||||
`MARIADB_ROOT_PASSWORD` and the like only when it initialises an EMPTY data directory; a restored data directory opens
|
||||
with its own password only. So when a restore puts back an app's database, the database credentials the data was
|
||||
saved with are written into the app's settings before the app starts, and they REPLACE whatever the current install
|
||||
holds. The credentials are the app.yaml variables that feed a database service's `*_PASSWORD` keys in the compose
|
||||
that will run (`appbackup.DBCredentialVars`; 17 catalog apps, 20 fields, every one `type: secret` — the catalog gate
|
||||
`db-credentials` refuses a template where that stops being true). Per route:
|
||||
|
||||
| Route | Where the database password comes from |
|
||||
|---|---|
|
||||
| On-box restore („Visszaállítás", `POST /backup/restore`), the update's rollback, „use my kept data", an off-site restore at the snapshot's version | the unit (unit-wins, `unitRestoreEnv`) |
|
||||
| Off-site full restore that keeps the app's definition (same version — the reinstall case) | the snapshot's unit, written by `stacks.SetStackSecretValues` before the database starts — **only when the snapshot replays the database's data volume**; a dump-only snapshot replays into the current data directory and keeps the current password |
|
||||
| `.fab` import | the bundle's own app.yaml (it carries the whole env) — unchanged |
|
||||
|
||||
**A restore whose unit does not carry the password is REFUSED before anything changes** — unless the current install
|
||||
is OLDER than the data (then the current value is the one the data was written with). The household reads „Ezt a
|
||||
mentést nem lehet visszaállítani: nem tartalmazza az adatbázis jelszavát, és nélküle az alkalmazás nem tudna elindulni.
|
||||
A mostani telepítés érintetlen maradt." **A database password is never generated for restored data** — O4 no longer
|
||||
reaches these names. On the reinstall path the reinstall's `type: password` admin logins are recorded as restored-login
|
||||
fields (R-694's rule — the page says to use the old password; R-926).
|
||||
|
||||
### 7.2 A tier whose prerequisites cannot be met in the failure it exists for
|
||||
|
||||
**[FACT]** Two instances, both current:
|
||||
|
||||
Reference in New Issue
Block a user