resticprofile schedule copies env-file values into the generated units, which
are 0644, so RESTIC_REPOSITORY (the rest-server basic-auth password included)
was readable by every local user on every restic host.
New playbooks/restic-repository-file.yaml:
- derives /etc/restic/repository (root 0400) from restic.env;
- uploads the profile switched to repository-file, but only when the live
profile's sha matches the repo copy it was edited from (drift guard);
- checks the repository is reachable through the new profile (cat config);
- regenerates the units and verifies they exist and contain no rest:http.
Applied to ana-docker, fv-ml1 (configs/restic/ana-ml2), esh-docker-vm,
esh-vm-db, irv-ml1, nh3-dev and nh3-docker. An independent check across all
eight restic hosts (these seven plus esh-ml1) found 0 leaking units. nh3-docker's
scheduled unit ran a real backup afterwards (snapshot a29b889d). Each host's
URL and passphrase are vaulted as <host>/etc/restic/{repository,password}.
restic.env is kept (root 0600) because the per-host READMEs and the freshness
probe source it. A rotation must update the vault, restic.env and repository.
vm-esh-nas has no infra-ops account. Its in-place migration script is staged
for Prime to run with sudo, and its repo profile is pre-edited to match.
Also mirrors augaman-dev's 401df2d (compose header only). The config hash on
esh-ml1 is unchanged.
Work by a parallel session on 2026-09-12; committed here with the rest of the
day's changes. Rationale in persistent-memory.d/2026-09-12-esh-vm-db-restic-repair.md.
The only visible symptom was a systemd-failed unit from a Sep 6 repository
network timeout after boot. The real fault was quieter and much worse: the
pre-backup hook logged failures as WARN and returned zero, so pg_dumpall could
fail every single night -- it used TCP localhost and wanted a password nobody
supplied -- while restic dutifully backed up the stale April 23 dump still
sitting in the staging directory and reported success. Mongo was fine, which
is part of why it went unnoticed.
Postgres now dumps over the /var/run/postgresql socket with peer auth and -w,
and both database failures now fail the backup rather than masking it, while
still preserving any prior per-DB dump rather than truncating to nothing. An
ERRORS counter replaces the warn-and-continue path, and the staging directory
is overridable via RESTIC_STAGE_DIR so the new test can exercise it.
Adds backup.contract.md, retry.conf and test_pre_backup.py -- three red-green
regression tests covering the failure modes above. systemd drop-ins on both
jobs add network-online ordering plus Restart=on-failure with a 5m delay and a
3-per-hour limit, which addresses the original boot-timeout symptom.
Verified against a real run: snapshot bc5eeaff at 07:01 PDT with a fresh 3.46MB
PG dump, retrieved from the repository with decompression and completion marker
checked (not a full restore). Repository check passed, 99 snapshots. The old
hook and stale dump are preserved root-only at /var/lib/restic/repair-20260912.
Bundles the post-2026-04-21 work that built out the two-layer backup
architecture (PBS for VM images + restic for file/DB), plus the cross-
site mirror and the disaster-recovery runbook.
- configs/restic/esh-docker-vm/profiles.yaml: drop the obsolete
*_offen_backup_data exclude (offen sidecars retired fleet-wide
2026-04-23; restic now covers the equivalent scope directly).
- configs/restic/esh-vm-db/: new profile for the dedicated DB VM
(10.0.50.60), with pre-backup pg_dumpall + mongodump hooks.
- configs/rsync/: ana-nas → nh3-nas (04:00 daily, runs as lkraven)
and nh3-nas → ana-nas (05:00 daily, runs as root because DSM
rest-server-nh3 writes mode-400 files only root can read).
- docs/runbooks/pbs-deployment.md: 9-phase PBS rollout runbook,
refined during the 2026-04-22 deployment with per-hypervisor
namespaces, NFSv3 + ZFS-case-insensitivity workaround, and the
Synology syno_acl flatten step.
- docs/runbooks/disaster-recovery.md: blast-radius runbook ordered
Tier 0 → 5 (ana-nas → hypervisors → Docker hosts → VMs → specialty);
references incident memory + recovery-step playbooks per consumer.