A Disaster Recovery Checklist You Can Finish Today
28 Apr 2026Your VPS provider deletes the wrong account, a datacenter has a fire, or someone fat-fingers rm -rf on production. The question that matters isn’t “do we have backups” — it’s “how long until we’re back online, and does anyone besides me know the steps.” Here’s the minimum plan, doable in an afternoon.
1. Write down what “recovery” means, concretely
Two numbers, not a paragraph:
- RTO (Recovery Time Objective): how long you can be down. Be honest — for most solo projects this is “a few hours is annoying, a few days is a real problem.”
- RPO (Recovery Point Objective): how much data you can afford to lose. If backups run nightly, your RPO is 24 hours by default. If that’s not acceptable, back up more often.
Write these two numbers at the top of the doc. Everything else exists to hit them.
2. Inventory what actually needs to come back
Make a list, not from memory — from what’s actually running:
docker ps --format '{{.Names}}\t{{.Image}}'
For each service: what data does it hold, where’s the backup, what secrets does it need to start (API keys, DB passwords, TLS certs). If the answer to “where’s the backup” is “I think it’s fine,” it’s not on the list yet — go set that up first.
3. Store the recovery doc somewhere that survives the disaster
The classic mistake: the runbook lives in a private repo, on the server that’s now gone, or in a password manager whose 2FA device was in the office that burned down. Put a copy somewhere independent of the infrastructure it describes — a second cloud account, a printed copy, or at minimum a password manager entry your co-founder or a trusted friend can also reach.
4. Write the actual restore steps, and make them runnable
Not prose — commands. If you already have restic backups (covered elsewhere), the doc is short:
# 1. Provision a new VPS, install docker
curl -fsSL https://get.docker.com | sh
# 2. Restore secrets from password manager into .env
# 3. Pull latest backup
export RESTIC_REPOSITORY=s3:https://s3.us-west-002.backblazeb2.com/my-backups
export RESTIC_PASSWORD=...
restic restore latest --target /srv/restore
# 4. Restore the database
psql mydb < /srv/restore/backups/db.sql
# 5. docker compose up -d
If any step requires knowledge that only lives in your head — a specific flag, a manual DNS change, an undocumented config tweak — write it down now. You will not remember it during an actual outage at 2am.
5. Test it once, on a throwaway box
Spin up a $5 VPS, follow the doc exactly as written, time it. This finds the two problems every untested plan has: a missing credential, and a step that assumes context you didn’t write down. Fix the doc, not just the box.
6. Set a review date
Infrastructure drifts. A doc written in January is wrong by June if you’ve added a service since. Put a recurring reminder — quarterly is enough — to re-read it and check it still matches what’s running.
The concrete next action
If you don’t have a documented restore path today, that’s the actual disaster risk, not the failure scenario itself. Servers fail all the time and it’s fine — what turns a server failure into a multi-day outage is finding out your recovery plan lives only in your memory.