--- created: 2026-09-01 modified: 2026-09-01 type: plan client: sam project: web-host-migration status: pending priority: 1 tags: - backup - restore - aws - s3 - borg - kopia - restic aliases: - backup-action-plan - backup-gaps-fix id: 1848129027-BAP --- # Backup Action Plan — Close the Gaps + Restore Procedures > Part of [[Migration Plan — InMotion to Local + AWS Offsite]]. Follow-up to [[Backup Architecture — Offsite to AWS S3]]. > **Status: PLAN ONLY (no changes yet).** Created 2026-09-01 after scope-gap review. ## Why this exists The original offsite S3 plan covered **photos + archive + .27 desktop** — but review (2026-09-01) found: 1. **.13 system configs are not fully in Borg** (`/home/sam/deployment` 23G, voice/audio/pi dirs, etc missing). 2. **.13's Borg repo (`borg/.13`) is NOT in S3** — only .27 is. 3. **.35's backup repos (restic 1.1T, kopia 71G on .23) are NOT in S3** and depend on `.23` (single point of failure, no backup, on-site). 4. **No documented restore procedure** exists in the notes. ## Facts verified 2026-09-01 | Item | Detail | |---|---| | .13 Borg `local-to-storage` covers | `~/Docker`, pocketbase-*, dotfiles, `.ssh`, `/mnt/data/family-home-lab`, photo-pipeline | | .13 NOT in Borg | `~/deployment` (23G), gst-plugins-rs (2.8G), speech_piper (1.5G), voice_bridge (946M), whisper-api (518M), librespot (842M), voice-agent (82M), mopidy-radionet (3.1M), `~/.agents` (844M), `~/.pi` (481M), bin, .config | | .35 Restic (Backrest) plan sources | /docker-config, /docker-containers, /docker-volumes, trilium-data, /host_fs/mnt/hd | | .35 Kopia snapshots | Docker/Containers, trilium-data, var/lib/docker/volumes | | .35 repos on .23 | **restic 1.1T**, kopia 71G, borg-repos 462G | | .23 | NFS file-server; **holds ALL .35 repos + .13 borg copies; itself has NO backup** | | S3 currently | photos/by_date, archive, borg/.27 only | ## Action plan ### Step 1 — Close .13 Borg coverage gap (local, immediate, $0) - [ ] Add to `.13` `backup.nix` `local-to-storage` paths: - `~/deployment` - `~/gst-plugins-rs`, `~/speech_piper`, `~/voice_bridge`, `~/whisper-api`, `~/voice-agent`, `~/librespot`, `~/mopidy-radionet` - `~/.agents`, `~/.pi`, `~/bin`, `~/.config` - [ ] Exclude: `.cache`, `.npm`, `.local` (junk/regenerable) - [ ] Rebuild + run Borg → verify new archive includes `~/deployment` ### Step 2 — Add .13's repo + key dirs to S3 (cheap, ~31G) - [ ] Extend `offsite.nix` S3 seed to include: - `backup/borg/.13` → `borg/.13/` (STANDARD) — tiny (304M) - `~/deployment` + voice/audio dirs → `home/...` (DEEP_ARCHIVE) — ~31G ≈ <$0.05/mo - [ ] First seed after Step 1 completes so .13's own config is offsite too ### Step 3 — Immich/photo offsite (REVISED 2026-09-01 after verification) **Key finding:** Immich originals live at `/mnt/hd/immich/upload` (407G, .35 My Passport) — separate store from .13 `by_date` (376G, already in S3). Kopia does NOT contain photos (only DB+configs). Restic contains /mnt/hd (407G). - [ ] Add `/mnt/hd/immich/upload` → S3 `photos/immich/` (DEEP_ARCHIVE) — 407G ≈ **$0.60/mo steady** (transient ~$15/mo first 90d in Standard) - [ ] Do NOT ship the 1.1T restic / 71G kopia repos (dedup DBs not directly restorable; target data directly instead) - [ ] Result: Immich originals + by_date master both offsite; .23 SPS closure for the highest-value data ### Step 4 — Protect .23 (the single point of failure) - [ ] Since .23 is the hub for ALL repo copies: either - **A:** ship .23's borg-repos to S3 (covers Step 3A), or - **B:** give .23 its own backup (rsync to .13? but .13 is on-site too) — **offsite is the real fix** → S3. - Recommendation: the S3 copies in Step 2+3A effectively close .23's vulnerability for restore-critical data. ### Step 5 — RESTORE PROCEDURES doc (in backup notes) - [ ] Create **Restore Runbook** (in [[Backup Architecture — Offsite to AWS S3]] or new note): step-by-step for: - Restore .27 from `borg/.27` (local + S3) - Restore .13 from `borg/.13` (local + S3) + the /home additions - Restore .35 containers/volumes from Backrest/Kopia (local .23) + from S3 if repos offsited - Restore Immich/My-Passport from S3 photos (DEEP_ARCHIVE — note hours-to-restore) - Restore Gitea (from /Docker/Containers in restic/kopia) - [ ] Add a "test a restore" cadence (e.g. monthly spot-check from S3) ### Step 6 — Verify - [ ] After changes: run backup, confirm S3 object counts for new prefixes - [ ] Test-restore ONE path from S3 (prove read path) - [ ] Update monitoring page to show new prefixes ## Cost estimate (AUD) - Step 2 (.13 → S3): +31G → < $0.10/mo steady (DEEP_ARCHIVE) - Step 3A (borg-repos 462G → S3): ~$0.01/mo steady DEEP_ARCHIVE after first-90-day Standard (~$16/mo transient) - **Total steady-state ≈ $2-4/mo** (vs current ~$1-2). Well within budget. ## Restore flow summary (target) 1. **Machine died, .23 alive:** restore .13/.35 from local repos (fast) — documented runbook. 2. **House fire:** .23 gone → restore .27, .13 configs, photos, Immich from S3 (Glacier hours) — documented runbook. 3. **Monthly:** spot-test one S3 restore. --- *Linked: [[Backup Architecture — Offsite to AWS S3]], [[Migration Work Log]], [[Migration Plan — InMotion to Local + AWS Offsite]].*