Reported symptoms
A fire in the plant room takes the primary suite and both production racks. The recovery team convenes at 07:41. The offsite repository at the second facility is the only surviving copy of the estate data, and it is reachable.
The first command of the recovery is a snapshot listing, because you cannot choose a recovery point before you can see one. It returns a single line and exits 12. No snapshot is named. No pack is named. No partial tree is offered.
The disaster recovery plan names an escrow location for the repository passphrase. The share is there. It is empty, and its directory timestamp is the date the plan was signed off.
The monthly restore test has passed fourteen times running, most recently nine
days ago. By 09:20 the theory on the bridge is that the copy must have been
damaged in transit, and somebody proposes running restic repair against it.
Evidence provided
$ du -sh /work/repo--- the repository is completely intact ---
11M /work/repo
files in repository: 6Eleven megabytes, six objects, matching the replication manifest from the night before the fire. Nothing short, nothing truncated, nothing missing.
$ restic snapshotsFatal: wrong password or no key found
>>> exit code: 12$ ls /work/repo/keys/d5f39ef5517fab2e4d1e6dc1d9d5b4b1f1ca4eeacecde523af8b5a0c3c3d120e$ ls -la /srv/rbdr-escrow/total 8
drwxr-x--- 2 root root 4096 Nov 4 2025 .
drwxr-xr-x 6 root root 4096 Aug 28 07:41 ..Illustrative output
The backup unit on the destroyed hosts passed
--password-file /opt/rbdr/prod/.restic-pass, a path inside the tree it was
backing up. The same passphrase was on a wiki page served by a virtual machine
in the destroyed suite. All fourteen restore-test records show the restore
running on a production host.
Work the evidence before reading on
- Six objects, eleven megabytes, one key file present. What has actually been lost, and where was it?
- The bridge thinks the repository is corrupt. What did Part IV measure a damaged repository doing, and does this match it?
- Fourteen restore tests passed. What did each of them prove, and what did none of them touch?
- Somebody wants to run
restic repair. Against what, exactly, and what is the cost if the theory is wrong?
Root cause
The passphrase never left the failure domain
The repository’s keys/ file holds the master key that every pack was encrypted
with, sealed under a second key derived from the passphrase at the moment it is
typed. The passphrase itself never enters the repository. Replicating the
repository therefore copies the lock and not the key.
Both copies of that passphrase were inside the suite that burned: one file in the tree the job was protecting, one wiki page on a virtual machine three racks away. The offsite copy survived a failure that took the only two things that could open it.
No drill ever opened the repository with escrowed material
The escrow location was created, entered in the plan, and never filled. Nothing detected that in fourteen months, because nothing ever tried to use it.
The restore tests looked like the control that would have caught it, and they were not. Each ran on a production host, which read the same passphrase file the backup job read. Each proved that a machine already holding the key could open a repository — true, cleanly exited, and irrelevant to a site loss. The property that mattered was whether anyone outside the estate could open it, and that was never once tested.
Why this is not corruption
Corruption fails differently, and this course measured how. In the Part IV capture, ten overwritten bytes in one pack produced a named blob error, restored 6 of 7 files and 59.401 MiB of 60.000 MiB, and exited 1: damage localised to the blobs actually harmed, with a partial answer returned.
Here the storage-layer listing is complete and consistent, the expected key file is present, and the refusal is total, uniform and arrives at exit 12 before any pack is opened. Damage takes away some of the data. This has taken away all of it from a repository in which none of the data is missing.
Resolution
Freeze the repository and work on a copy of it:
REPO=/srv/rbdr-repo-offsite
cp -a "$REPO" "$REPO.evidence"
Then search for the passphrase outside the blast radius, methodically: engineer password managers, configuration-management history, any pipeline secret store that deployed the unit, change-request attachments, offsite backups of the wiki virtual machine, printed runbooks. Search for the path and the flag, since the secret is the thing you do not have.
If a passphrase is found, add an independent unlock path before attempting anything else, so a second way in exists before the first can be lost again:
REPO=/srv/rbdr-repo-offsite
restic -r "$REPO" key add --new-password-file /run/rbdr/escrow-pass
restic -r "$REPO" key list
If it is not found, the repository cannot be opened. There is no vendor path and no support escalation; the encryption is doing exactly what it was configured to do. Declare the loss, record it against the recovery objectives, and move the incident to rebuilding from whatever primary sources remain.
The replacement repository gets escrow on day one. The reference capture shows both halves of that:
$ restic key add --new-password-file /work/recovery-passsaved new key with ID 66c34166d8443d16e8c5899fe3f792e749cb24fa3a90ac90bbe8348979b57d90
>>> exit code: 0$ restic key list ID User Host Created
--------------------------------------------------
66c34166 root 17dffded9807 2026-08-28 14:04:55
*4bc6f61a root 17dffded9807 2026-08-28 14:04:52
--------------------------------------------------Verification
restic key list returns two keys, not one.
A restore is then performed with the escrowed passphrase alone, by someone without production credentials, on a host that never held the production passphrase. The capture sets the standard to meet:
$ restic --password-file /work/recovery-pass restore latest --target /work/recrestoring snapshot b96ba7cf of [/work/prod2] at 2026-08-28 14:04:52.481565631 +0000 UTC by root@17dffded9807 to /work/rec
Summary: Restored 3 files/dirs (38 B) in 0:00
>>> exit code: 0The recovered checksum matched the source exactly —
9eb4e2ad8e08e1dcaaf87ababab964b0 in and out. Prove the same for your own
drill:
DRILL=/srv/rbdr-drill
find "$DRILL" -type f -exec md5sum {} + | sort -k 2 > /srv/rbdr-drill.md5
The escrow location is opened under witness and is not empty. The register entry matches what is inside it: custodian, repository, deposit date, last-opened date.
Prevention
Two unlock paths, always. restic key add gives the repository a second key
opening the same master key. Borg’s mechanism is an export of the key material
itself, and borg key export --paper produces a printable block that outlives
every system holding the repository.
Split the custody. Exported key material is still useless without its passphrase, so escrow the two to different custodians in different buildings. Neither can act alone, and neither is lost with the estate.
Run a decryption drill quarterly — outside the production credential set, outside the estate, escrowed material only. That exercise is the control that was missing here, and it fails loudly the first time the escrow is empty.
Inventory the key material. The passphrase file was never listed as an asset, so no impact assessment for the loss of those hosts ever considered it.
Record where each restore test ran. A test that reads the passphrase file sitting next to the data proves the host is alive. That is not the question a site loss asks.