Recover after complete primary-site loss
1 · Prerequisites
Confirm every item is in place before any state change.
- An accepted declaration that the primary site is lost rather than degraded, made by the named authority, with the time recorded. This runbook is the one that follows that declaration; it does not make it.
- A backup catalogue held somewhere the primary cannot take with it — which repository holds which system, at which endpoint, under which credential. It is a small file, it is irreplaceable, and estates routinely discover it existed only on a server inside the site that is gone.
- Key material for every repository in the recovery path, escrowed to a custodian outside both sites, with the passphrase and any exported key block held by different custodians so that one safe is not one point of failure.
- A written dependency graph for the estate, produced while it was healthy, expressed as ordered pairs a machine can sort rather than as an architecture diagram nobody can execute.
- A bootstrap path for identity, certificates and time that does not route through either site: the directory or its seed data, the root certificate authority material or its offline copy, and a time source the recovery hardware can reach on its own.
- Capacity at the recovery location — compute, storage, addressing and licences — measured rather than assumed, because the scope decisions in this runbook are arithmetic against that number.
- A named business owner per service, reachable today, who can state what the loss of a given interval costs and confirm afterwards that a real transaction is correct.
- A place to record decisions, recovery points and timings that survives the loss of the primary, plus the failback procedure on hand for the day the estate goes home.
2 · Pre-checks
Read-only diagnostic commands. If any of these don't match expected output, stop and investigate further.
- · Answer the first question: where are the copies. List every repository, object store and offline medium in the recovery path with its endpoint, and mark which of them you have just proven reachable from the recovery location rather than from memory. A copy nobody can name the location of is not in the recovery path.
- · Answer the second question: what opens them. Retrieve the escrowed key material and open one repository with it, now. Not confirm the escrow exists — open a repository. The measured failure below is an intact repository that could not be read, and it is indistinguishable from data loss at the moment it matters.
- · Answer the third question: what lists them. Confirm the catalogue is readable at the recovery location and that it maps systems to repositories. Without it the team is searching repositories one at a time to discover what is inside them, and that search is measured in days.
- · Confirm the identity, certificate and time bootstrap can start without either site. Establish which of directory, secrets platform, certificate authority and time source can be started from escrowed material and which silently expected the primary to answer. An estate that starts everything except the thing that authenticates everything has not recovered.
- · Measure the capacity actually available at the recovery location, and write the number down. Cores, memory, usable storage, addresses and any licence that is counted. Every scope decision in this runbook is that number against the dependency graph, and doing the arithmetic later means doing it after something has already been started that should not have been.
- · Sort the dependency graph and read the first tier out loud. If the first tier contains anything nobody can start from escrowed material, that is the blocker, and it is cheaper to find it here than four tiers up.
- · Confirm the restore bandwidth and any retrieval delay on the offsite tier. Retrieval from a cold tier is a serial stage that nothing else overlaps; if it is hours, the sequencing below changes and the business needs to hear that in the first hour rather than the fifth.
- · Record the current recovery point available for each system before restoring anything. These are the numbers the RPO statement is made from, and they are easiest to read now, while nothing has been overwritten.
3 · Procedure
Execute each step in order. Verify the expected output of a step before moving to the next.
- 1Open the log with the declaration, the capacity number and the three answers. Where the copies are, what opens them, what lists them. A recovery that cannot answer all three is not started, it is stalled, and saying so in the first hour is worth more than any command in this runbook.
- 2Prove the key material opens a repository before planning anything around it. The plan is worthless if the repositories cannot be read, and every hour spent sequencing work that depends on unreadable bytes is an hour subtracted from the recovery window.
- 3Bootstrap time first, from a source that does not depend on either site. Clock disagreement breaks certificate validation, token lifetimes, consensus and log correlation, and it does so with error messages that point somewhere else entirely.
- 4Bootstrap identity and the certificate authority from escrowed material, and validate both before anything depends on them. Issue one certificate and authenticate one account. This tier is where most site-loss recoveries stall, and it stalls in a way that looks like an application fault three tiers later.
- 5Sort the dependency graph down to the infrastructure primitives and follow the sort. The graph does not stop at applications: it continues into addressing, name resolution, routing, storage provisioning and the container registry or package mirror the rebuild pulls from. A tier that appears to be a given at the primary is a thing somebody has to start here.
- 6Select the recovery point for each system explicitly, by identifier and timestamp, and never take "the latest". Name the gap each selection leaves. The set must be mutually consistent: a database recovered past the point at which the queue or the object store was captured produces an estate that disagrees with itself about what happened.
- 7Get each recovery point selection accepted by its business owner before restoring. They are the only people who can price the gap, and the conversation is far cheaper before the restore than after it.
- 8Decision point — choose which systems are recovered today, against the measured capacity. The criteria are in the body. This is arithmetic and business priority together, and it is made once, explicitly, rather than drifting as people start whatever they know how to start.
- 9Decision point — declare what is out of scope for the first day, and communicate it. An estate that tries to recover everything at half speed recovers nothing by the end of the day. Naming the deferred systems is what makes the rest of the plan honest.
- 10Restore the infrastructure primitives before the services that assume them. Addressing, resolution, routing, storage classes or volume groups, and the registry or mirror. These are the tier nobody lists because at the primary they were furniture.
- 11Restore storage and databases to the selected recovery points, and validate each before starting anything above it. A database that starts is not a database that is consistent; check which recovery target it actually reached and read a row somebody can vouch for.
- 12Start each service tier only after the tier below it has passed a check that belongs to that tier. Under time pressure the temptation is to start everything and see what breaks. That produces a cascade whose first cause is four tiers down and invisible from the top.
- 13Re-issue the credentials and certificates the primary held, rather than restoring copies of them. Material that was present at a site now assumed lost should be treated as material an incident may have touched, and the recovery is the natural moment to replace it.
- 14Publish the recovery location through the mechanism the estate owns, and account for what caches the old answer. Changing an authoritative record starts a timer rather than moving traffic; pools and long-lived connections may not re-resolve at all until restarted.
- 15Validate each recovered service against the business, and state the RPO actually paid for each. Not "the process started": a real transaction, exercised by a real role, confirmed by the owner, with the interval of lost work named in hours and minutes.
- 16Establish protection at the recovery location before standing anybody down. It is production now, and it is running on whatever backup schedule it inherited, which is frequently none. Take a recovery point and list it.
- 17Record the deferred scope as work, with an owner and a date. Systems declared out of scope for the first day become permanently unrecovered exactly when nobody writes them down, and the discovery is usually made by an auditor.
4 · Verification
Confirm the procedure actually fixed the problem.
- ✓The three questions are answered in the log with evidence: the repository list with endpoints proven reachable from the recovery location, the catalogue read, and
restic -r "$RBDR_REPO" --password-file "$RBDR_PASS" snapshotsexiting 0 with its snapshot table pasted into the log. The opposite signature isFatal: wrong password or no key foundat exit code 12, and it means the escrow answer is wrong rather than the data being gone. - ✓Time, identity and the certificate authority were started from material held outside both sites, and each was validated by an action rather than by a running process: a clock the responder recorded as synchronised, one authenticated account, and
openssl x509 -noout -subject -enddateexiting 0 against the recovered root with anotAfter=date still in the future. - ✓The executed startup order matches the sorted dependency graph, including the infrastructure primitives, and every deviation is recorded with its reason and the person who authorised it.
- ✓Every recovery point is named by identifier and timestamp, the set is stated to be mutually consistent, and each business owner's acceptance of the gap is recorded against their name.
- ✓Both scope decisions are recorded: what was recovered today against the measured capacity, and what was explicitly deferred, with an owner and a date for each deferred system.
- ✓Each tier passed its own validation before the tier above it started, with the evidence in the log rather than summarised as "tier up".
- ✓Every restore that ran is recorded with its command, its closing summary line and its exit code — a restic restore ends on a
Summary: Restoredline at exit code 0 — and no restore counts as passed until a digest or a row count taken from the recovered data matches one recorded before the loss. - ✓A real business transaction has completed end to end for every in-scope service, confirmed by name by the person who owns it.
- ✓The RPO paid is stated per service in hours and minutes, derived from the selected recovery point rather than from the schedule that was supposed to run.
- ✓Backups at the recovery location have produced at least one recovery point that has been listed, so the new production estate is protected before the incident is closed.
5 · Rollback
If verification fails, undo the procedure in reverse order.
- ↶There is no rollback to the primary site: it is gone, and that is the premise of this runbook. What can be rolled back is everything this procedure changed outside it, and every item below is a mutation responders make by reflex.
- ↶Stop and remove partially recovered services in reverse dependency order rather than leaving them half-started. A service that is up but unvalidated will be assumed working by the next person who looks at it.
- ↶Withdraw any published record or route that points at a recovery location which is not serving, and restore the original time-to-live on every name whose TTL was lowered for the cutover.
- ↶Remove the monitoring silences taken to quiet the primary's alarms. This is the commonest artefact left behind by a site-loss recovery, and it hides the next failure of the same component at the new location.
- ↶Revert speculative changes made while working the incident: firewall rules opened to reach the recovery location, resolver overrides, hosts-file entries, relaxed certificate checks and connection-pool settings changed to force a re-resolve.
- ↶Revoke every temporary identity created during the recovery — break-glass accounts, recovery-team credentials, service identities issued to get a tier started — and record the revocation time for each.
- ↶Destroy or take custody of every copy of key material created during the incident, including anything written to a terminal scrollback or a shared document, and record where each copy ended up.
- ↶Return escrowed originals to their custodians and record the return, so the next recovery starts from a control that is intact rather than from a safe somebody emptied a year ago.
6 · Escalation
When the runbook isn't enough, contact:
- · The escrowed key material does not open the repositories: escalate to the key custodian and the incident owner in parallel, within minutes. No amount of sequencing addresses this, and the business needs to know that the copies exist but cannot be read.
- · The catalogue cannot be found or read: escalate to the backup platform owner and the incident owner. Recovery can continue by searching repositories directly, but the estimate changes by an order of magnitude and that estimate belongs to the business.
- · Identity, certificates or time cannot be bootstrapped without the primary: escalate to the identity owner immediately. Everything above that tier will fail in ways that look like application faults, and responders will spend the window debugging the wrong layer.
- · The measured capacity cannot hold the systems the business considers essential: escalate to the incident owner and the service owners together. Choosing what is not recovered today is a business decision, and a responder should never make it alone at three in the morning.
- · The primary's loss has characteristics of a deliberate act: escalate to security before restoring anything, because a recovery point taken after a compromise reproduces the compromise at the new location, and choosing the pre-incident point is a decision security owns.
- · The estate will miss the agreed recovery time with work still outstanding: escalate with the measured remaining work, so that continuing, reducing scope further or accepting a longer outage becomes an explicit decision rather than a default.
Assume nothing from the primary survives. Not the hypervisors, not the control plane, not the wiki page that recorded where things were kept, not the console of the one host that always knew. Everything this procedure uses has to be reachable from somewhere the disaster did not reach.
The first three questions
Where are the copies. What opens them. What lists them. The bytes are usually the easy part; the two small items that stop this recovery are the key material and the catalogue, and both are small enough that estates forget they are irreplaceable.
RBDR_INCIDENT=rbdr-site-loss-2026-08-28
RBDR_LOG=/srv/rbdr-dr/"$RBDR_INCIDENT".log
RBDR_REPO=sftp:rbdr-recovery@vault.dr.example.net:/srv/rbdr-repo
RBDR_PASS=/mnt/rbdr-escrow/rbdr-recovery.pass
mkdir -p /srv/rbdr-dr
restic -r "$RBDR_REPO" --password-file "$RBDR_PASS" snapshots | tee -a "$RBDR_LOG"
That command answers the first two questions at once, and it is the first thing this runbook does. Here is what the second answer looks like when the passphrase lived on a host inside the site rather than with a custodian outside it.
$ restic snapshots Fatal: wrong password or no key found
>>> exit code: 12The transcript’s own summary is the sentence to carry into the incident: This is not a corruption failure or a media failure. The data survived the disaster; the ability to read it did not. Escrow is what makes that a solved problem, and escrow means a passphrase and any exported key block held by different custodians, neither of them the site.
The third question is the catalogue: which repository holds which system, at which endpoint, under which credential. It is a text file. It is also the difference between a directed recovery and opening repositories one at a time to find out what is in them.
RBDR_CATALOGUE=/mnt/rbdr-escrow/rbdr-catalogue-2026-08-28.txt
grep -c . "$RBDR_CATALOGUE"
awk -F'\t' '{print $1, $2}' "$RBDR_CATALOGUE" | sort -u
Bootstrapping identity, certificates and time
Every tier above this one authenticates, validates a certificate chain, or compares a timestamp. All three of those capabilities were services at the primary, and all three have to start here from material held outside both sites.
RBDR_BOOTSTRAP=/mnt/rbdr-escrow/rbdr-bootstrap
timedatectl show --property=NTPSynchronized --value
openssl x509 -noout -subject -enddate -in "$RBDR_BOOTSTRAP"/rbdr-root-ca.crt
getent hosts idp.dr.example.net
Time first, because clock disagreement breaks certificate validation, token lifetimes and consensus while producing error messages that point somewhere else. Then the certificate authority, proven by issuing one certificate. Then the directory, proven by authenticating one account.
Recovery point selection, one system at a time
$ restic --password-file /work/recovery-pass restore latest --target /work/rec restoring 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 capture used latest because it was demonstrating a key path rather than
choosing a recovery point; this runbook names the identifier. What it does
establish is the standard of proof — the recovered digest matched the source
digest recorded before the loss, rather than the tool’s own summary line.
Order comes from the graph, and the graph goes down to the primitives
RBDR_GRAPH=/mnt/rbdr-escrow/rbdr-dependency-graph.txt
tsort "$RBDR_GRAPH" > /srv/rbdr-dr/rbdr-recovery-order.txt
nl -ba /srv/rbdr-dr/rbdr-recovery-order.txt
Most graphs stop at applications. This one continues downwards into addressing, name resolution, routing, storage provisioning, and the registry or package mirror the rebuild pulls from — the tier that was furniture at the primary and is somebody’s task here.
Decision point 1 — what is recovered today
| Condition | Recover today | Defer |
|---|---|---|
| Named in the graph as a dependency of an in-scope service | Required | Never |
| Business owner prices an outage in hours, not days | Chosen | — |
| Capacity remains after the tiers below it are placed | Chosen | — |
| Needs hardware or a licence not present at the location | — | Chosen, escalate |
| Recovery point exists only on a cold tier still retrieving | — | Chosen, revisit |
Decision point 2 — what is out of scope for the first day
| Condition | Defer to day two | Keep in today’s scope |
|---|---|---|
| Anything in the first tier of the sorted graph depends on it | Never | Required |
| The named owner accepts a further day of outage, and says so | Chosen | — |
| Capacity measured in the pre-checks is already committed above it | Chosen | — |
| Its recovery point is still retrieving from a cold tier | Chosen, with a revisit time | — |
| No owner can be reached to accept the deferral | Refused | Held, and escalated |
Declaring scope is the decision that makes the rest of the plan honest. An estate that attempts everything at once at half speed finishes the day with nothing validated. Say which systems are not being recovered today, tell their owners in the same hour, and record each one as work with an owner and a date — deferred systems become permanently unrecovered precisely when nobody writes them down.
Everything must be reachable without the primary
RBDR_DEPS=/mnt/rbdr-escrow/rbdr-external-dependencies.txt
while read -r RBDR_HOST; do
getent hosts "$RBDR_HOST" || printf 'UNRESOLVED %s\n' "$RBDR_HOST"
done < "$RBDR_DEPS"
Licence servers, update mirrors, identity providers, payment gateways and the monitoring endpoint all belong on that list. The only exercise that proves the list is complete is one run with the primary genuinely unavailable — powered off or firewalled off, not politely ignored. A rehearsal that leaves the primary reachable tests a recovery that quietly borrows from it, and the borrowing is invisible until the day it is not there.
Abort criteria
Stop and escalate rather than continuing when any of these is true:
- The escrowed key material does not open the repositories. The copies exist and cannot be read, and that fact belongs to the business within minutes.
- The catalogue cannot be produced, so nothing maps systems to repositories.
- Identity, certificates or time cannot be made authoritative without the primary. Everything above fails in ways that look like application faults.
- Measured capacity cannot hold the systems the business calls essential, and no owner is available to choose.
- The loss shows evidence of a deliberate act and no pre-incident recovery point has been chosen with security.
Business validation, with the RPO paid stated per service
The record has four columns and no fifth. The rows below are the shape to fill in — a worked example of the format, not a capture from any estate:
| Service | Recovery point restored | RPO paid | Confirmed by |
|---|---|---|---|
| Directory | rbdr-idm 2026-08-28T02:10Z | 6 h 05 m | identity owner |
| Orders database | rbdr-pg 2026-08-28T07:45Z | 0 h 30 m | finance owner |
| Object store | rbdr-obj 2026-08-28T04:00Z | 4 h 15 m | platform owner |
| Reporting | deferred — day two | not yet paid | reporting owner |
Every in-scope row needs a real transaction completed by a real business role and confirmed by name, not a green health endpoint. The RPO column is the interval between the selected recovery point and the loss, and it is a property of this recovery, not of any product involved in it.
What to record
The three answers and how long each took to establish. Every recovery point by identifier and timestamp, with the accepted gap and who accepted it. Both scope decisions, the capacity number they were made against, and the deferred list with owners and dates. The bootstrap path actually used for time, certificates and identity, including anything that turned out to depend on the primary. The RPO paid per service. And the first backup taken at the recovery location, because it is production now.
Cross-course references
- Linux for Production Sysadmins — Part L (Disaster Recovery) is the parent discipline for this procedure, and Part LXIII (Cluster Time, DNS and Identity Dependencies) is the tier that has to start first and the failures it produces three tiers later when it does not.
- Secrets, PKI & Certificate Management — Part XV (KMS, HSM and Key Protection) covers the custodianship that makes key material available when neither site is, and Part XVIII (Incidents and Recovery) covers re-issuing the credentials a lost site held.
- Terraform for Production Sysadmins — Part XXVIII (Disaster Recovery and Resilience) and Part XII (State Recovery and Backup) cover rebuilding the infrastructure primitives when the state that described them is at the site that is gone.
- Kubernetes for Production Sysadmins — Part XCIX (Complete Cluster Loss) is the same problem scoped to one cluster, and its ordering argument is the one generalised here.
References
- NIST SP 800-34 Rev. 1, Contingency Planning Guide for Federal Information Systems
- NIST SP 800-184, Guide for Cybersecurity Event Recovery
- restic documentation
- BorgBackup documentation
- GNU coreutils manual
- timedatectl(1) manual page
- RFC 2181, Clarifications to the DNS Specification
- openssl-x509(1) manual page