Backup & Disaster Recovery
Automated, multi-tier, encrypted where it matters, with off-site replication. Everything backs up to the NAS Host (ZFS); critical data also goes off-site.
Design principles
- Automate everything. Every backup runs on a schedule — cron or systemd timer. No manual steps required for normal operation.
- Encrypt sensitive data. Vaultwarden and Proxy Host backups are GPG-encrypted (AES-256 symmetric) before writing to NFS. Passphrase stored on the source host only, not in the repo.
- Retention with pruning. Application backups keep 7 daily + 4 weekly (Sunday promotion). VM images keep 2 weekly copies. Oldest copies are pruned only after the new backup succeeds.
- Off-site for irreplaceable data. Personal media and documents replicate to Backblaze B2 via Restic (AES-256 encrypted at rest).
- All backups land in one tree. The NAS Host has a unified backup root with per-service subdirectories.
VM image backups (weekly)
All four Hyper-V VMs on the Desktop Host are backed up as full VM images weekly:
| VM | VHDX type | Approximate size |
|---|---|---|
| nginx VM | Dynamic | ~20 GB |
| Docker VM | Differencing | ~124 GB |
| Minecraft VM | Differencing | ~46 GB |
| Stoat VM | Differencing | ~118 GB |
- Method: Hyper-V
Export-VM(native). Works on running VMs — auto-creates a checkpoint for consistency, exports the full VM, then removes the checkpoint. Brief pause (~seconds) during checkpoint creation; no downtime. - Schedule: Weekly Saturday 02:00 AM via Task Scheduler. VMs exported sequentially to avoid saturating disk I/O and network.
- Target: NAS Host SMB share.
- Retention: 2 weekly copies per VM (~618 GB total with retention; ZFS compression reduces on-disk to ~214 GB).
- Network resilience: Robocopy
/Z(restartable — resumes partial copies after interruption) +/J(unbuffered I/O). Per-VM retry loop (3 attempts) with SMB session re-establishment. - Restore:
Import-VM -Copy -GenerateNewIdfrom the NAS share directly. Full VM (OS, packages, Docker images, crontabs, network config) restored in one operation.
Application data backups (nightly)
| What | Method | Retention |
|---|---|---|
| Vaultwarden (database + attachments) | Automated backup to NAS | 7 daily + 4 weekly |
| Minecraft (world + database) | Automated backup to NAS | 7 daily + 4 weekly |
| Stoat Chat (database + files + config) | Automated backup to NAS | 7 daily + 4 weekly |
| Proxy Host (proxy config, certs, DNS) | Automated backup to NAS | 7 daily + 4 weekly |
| Docker VM services (Pi-hole, Paperless, Mealie, etc.) | Automated backup to NAS | 7 daily + 4 weekly |
Sensitive service data is GPG-encrypted (AES-256) before writing to the NAS. Passphrases are stored on the source hosts only. Each backup script handles its own rotation — new backup writes first, then old copies beyond retention are pruned.
Off-site backup (Restic → Backblaze B2)
Personal media and documents from the NAS Host replicate off-site:
- Tool: Restic (deduplicating, encrypted backup program)
- Target: Backblaze B2 cloud storage
- Encryption: AES-256 at rest (Restic handles key management)
- What: Personal media library, documents archive
- Why: If the NAS Host suffers a catastrophic failure (e.g. house fire, multiple disk failures beyond RAIDZ1 tolerance), irreplaceable personal data survives off-site.
Backup tree layout (NAS Host)
All backups land in a single tree on the NAS Host with per-service subdirectories, separated by daily and weekly retention tiers.
Verification
- Audit scripts check backup recency:
make audit-thoroughflags any backup older than its expected threshold (e.g. >36 hours for nightly, >8 days for weekly). - VM image backup logs both locally (Desktop Host) and remotely (NAS Host) for post-run inspection.
- GPG decryption tested periodically to confirm passphrases are correct and archives are intact.
What’s protected vs. what’s not
| Data | Protected by | Recovery time |
|---|---|---|
| VM state (OS, packages, config) | Weekly VHDX image | Import VM (~30 min) |
| Application databases (Vaultwarden, Minecraft, Stoat, Paperless) | Nightly backup to NAS | Restore from latest backup (<1 hour) |
| Proxy Host (nginx, certs, Pi-hole) | Nightly GPG backup to NAS | Rebuild from backup or re-provision from repo + restore data |
| Personal media + documents | ZFS on NAS + off-site (Restic → B2) | Pull from B2 if NAS fails |
| Docker images | Re-pull from registries; locally-built images re-built from source repos | Minutes to hours depending on bandwidth |
| Configuration (nginx, keepalived, fail2ban, Docker Compose) | Homelab repo (source of truth) | make generate-configs + deploy |