SKYHOUSE.dev Journal

Maintaining the Cloud Fortress

Disaster Recovery: Scoped, Priced, and Deliberately Deferred

Why: While hardening the monitoring scripts, we started pricing an off-site backup and realised the question is much bigger than "how much would Backblaze cost" — it needs its own project, so this entry parks the findings rather than half-solving it.

This is a deferred-work record, not a change. Nothing was implemented. It exists so the next session doesn't have to re-derive any of it.

1. The reframe that stopped the work

The obvious first move is to back up the small irreplaceable set — the Immich Postgres DB, the Plex library DB, the Vaultwarden vault, NPM's certs, configs. That set is tiny and cheap to ship off-site. But Damien's observation killed the framing: in the destructive scenarios that off-site backup exists to survive — theft, fire, flood — a database is close to useless without the content it indexes. A perfectly restored Plex library DB pointing at 30 TB of media that no longer exists is a catalogue of things you no longer own.

So the real goal is mirroring the DAS contents somewhere else, which is a genuinely different and much larger problem (capacity, cost, seeding bandwidth, and a restore procedure that has to actually work). That deserves deliberate design, not an evening.

2. Measurements taken (so they don't need redoing)

The non-media irreplaceable set, measured 2026-08-04:

ItemSize
Plex library DB (watch history, collections, metadata)7.0 G
Immich Postgres DB (/home/plex/immich-app/postgres)3.4 G
/home/plex/www (all sites + this journal)5.9 G
All Docker volumes (Vaultwarden vault, NPM db + certs)851 M
bin + docs + npm config~75 M
Total~17 GB

Photo library (/media/plex1/Photos) — 1.3 TB total, fully measured 2026-08-04:

PathSizeBack up?
library/859 GYES — irreplaceable originals
Damien/259 GProbably — but see dedup question below
thumbs/98 GNO — regenerable derivative
encoded-video/78 GNO — regenerable derivative
backups/16 GNO — Immich's own DB dumps; redundant if Postgres is backed up directly
upload/3.7 GYes — staging, small
immich/ + profile/57 MYes — trivial

Exclusions matter a lot here. thumbs/ + encoded-video/ + backups/ = 192 G that never needs to leave the house — Immich regenerates the first two from originals, and the third duplicates a DB we back up separately. That is ~15% of the library shaved off before the first byte is uploaded.

⚠ Open question worth resolving before any seed: Damien/ (259 G) may substantially duplicate library/. If it is the raw Google Takeout staging and those photos were subsequently imported into Immich, the originals now live in library/ and this is 259 G of redundancy — a quarter of the upload, and an ongoing storage cost. Check before committing to it.

Resulting real cost: irreplaceable photo originals ≈ 1.1 TB (or ~860 G if Damien/ proves redundant), plus the 17 GB non-media set. On Backblaze B2 that is ~$6.70/month (or ~$5.20). The binding constraint is not cost, it is the initial seed — 1.1 TB over a home upstream is on the order of days of continuous transfer, which is itself an argument for the buddy-backup option, where the first seed can happen over LAN before the hardware is moved off-site.

3. Options priced

4. Carved out as a separate, higher-priority piece: a boot-drive mirror

Confirmed 2026-08-04: no boot-drive backup of any kind exists. The only artifact is /media/plex3/pre-swap-backup-2026-06-02/ — a config-and-DB subset captured for the June disk swap, now two months stale. No image, no clone, no Timeshift, nothing bootable. The root SSD holds 621 G used of 938 G and carries every app config, the Immich Postgres DB, the Vaultwarden vault, and NPM's certs.

This is a much smaller problem than off-site DR and protects against the far more likely failure (a dead SSD, not a house fire). Damien ranks it above off-site backup. Sketched approach, not yet implemented: nightly rsync of / with exclusions to a directory on a DAS drive (the blank 5.5 T Toshiba is the natural target), plus sgdisk --backup of the partition table and a copy of the EFI partition, plus a written restore runbook (partition → mkfs → rsync back → install GRUB → fix fstab UUIDs). Online, incremental after the first seed, restore measured in hours. Open question to settle first: database consistency — a live copy of Postgres/MariaDB/SQLite is crash-consistent at best, so it needs either brief container stops (the pattern arr-config-backup.sh already uses) or separate DB dumps taken before the rsync.

5. Status

Both items are open and unstarted, deliberately deferred so the monitoring and alerting project can finish first. Priority order agreed: (1) monitoring/alerting project → (2) boot-drive mirror → (3) full off-site DR design. The existing unmitigated risks are unchanged and still recorded in server-context.md §10: /media/plex2 (~13 TB) has no copy anywhere, the root disk has no backup, and nothing is off-site.

Nothing here was built — this entry exists purely so the next attempt starts from measurements instead of guesses.

← Back to Admin Hub