Runbook: Backup Strategy
- Last Updated
-
2026-02-08
- Owner
-
evanusmodestus
- Review Frequency
-
Quarterly
Purpose
Protect all critical data using a defense-in-depth backup strategy that survives:
-
Hardware failure (SSD death)
-
Ransomware (offline copies)
-
Fire/flood (offsite storage)
-
Long-term bit rot (archival media)
The 3-2-1 Rule (Extended)
| Rule | Meaning | Implementation | Recovery Time |
|---|---|---|---|
3 copies |
At least 3 copies of data |
Hot + Warm + Cold |
N/A |
2 storage types |
Different media types |
SSD + HDD/NAS + Optical |
N/A |
1 offsite |
Geographic separation |
LUKS USB #2 offsite |
Hours to days |
+Archival |
1000+ year durability |
M-Disc in fireproof safe |
Days |
Tier 1: HOT (Primary)
Tier 2: WARM (Automated)
What Lives Here
| Data | NAS Path | Backup Method |
|---|---|---|
ISE configs |
|
|
WLC configs |
|
|
VyOS configs |
|
|
IOS switch configs |
|
|
KVM VM definitions |
|
|
Keycloak realms |
|
|
Workstation (Borg) |
|
|
Infrastructure Backup Commands
dsource d000 dev/network
netapi ise backup --upload-nas
netapi wlc backup --upload-nas
netapi vyos backup --upload-nas
netapi ios backup --all --upload-nas
netapi kvm backup --all --upload-nas
dsource d000 dev/identity
netapi keycloak backup --upload-nas
dsource d000 dev/network
netapi synology backup-status --detailed
Borg Workstation Backup
sudo mount -t nfs nas-01.inside.domusdigitalis.dev:/volume1/borg_backups /mnt/synology
dsource d000 dev/storage
sudo -E BORG_PASSPHRASE="$BORG_PASSPHRASE" ~/.local/bin/borg-backup-synology.sh
dsunsource
sudo umount /mnt/synology
|
If |
Tier 3: COLD (Offline)
Location
-
Seagate Primary (seagate-crypt): Daily local encrypted mirror
-
Seagate Backup (seagate-backup): Weekly sync from primary
-
LUKS USB #1: Home safe
-
LUKS USB #2: Offsite (quarterly rotation)
Seagate USB Drives
| Drive | LUKS Mapper | Mount Point |
|---|---|---|
Seagate Primary |
seagate-crypt |
/mnt/seagate |
Seagate Backup |
seagate-backup |
/mnt/seagate-backup |
Directory structure on each drive:
Seagate Commands
Daily: Backup to Primary
gopass show -c v3/domains/d000/storage/seagate-primary
lsblk -o NAME,SIZE,MODEL | grep -i seagate
seagate-primary-mount /dev/sdX1
seagate-primary-mount /dev/sda1
seagate-primary-backup
seagate-primary-umount
Weekly: Sync Primary to Backup
gopass show -c v3/domains/d000/storage/seagate-primary
gopass show -c v3/domains/d000/storage/seagate-secondary
lsblk -o NAME,SIZE,MODEL | grep -i seagate
seagate-primary-mount /dev/sdX1
seagate-backup-mount /dev/sdY1
rsync -av --delete /mnt/seagate/secrets/ /mnt/seagate-backup/secrets/
rsync -av --delete /mnt/seagate/configs/ /mnt/seagate-backup/configs/
rsync -av --delete /mnt/seagate/backups/ /mnt/seagate-backup/backups/
rsync -av --delete /mnt/seagate/storage/ /mnt/seagate-backup/storage/
echo "PRIMARY:" && du -sh /mnt/seagate/
echo "BACKUP:" && du -sh /mnt/seagate-backup/
seagate-backup-umount
seagate-primary-umount
What Lives Here
CRITICAL: These are the recovery keys for everything else.
| Data | Why Critical |
|---|---|
|
Decrypts all |
SSH private keys |
Access to all systems |
GPG secret keys |
Signing, encryption |
LUKS headers |
Recovery if header corrupted |
|
Vault master keys |
LUKS USB Commands
Monthly Sync to USB
sudo cryptsetup luksOpen /dev/sdX1 backup-usb
sudo mount /dev/mapper/backup-usb /mnt/backup
rsync -av ~/.secrets/.metadata/keys/ /mnt/backup/keys/
rsync -av ~/.ssh/id_* /mnt/backup/ssh/
gpg --export-secret-keys > /mnt/backup/gpg/secret-keys.asc
sudo cryptsetup luksHeaderBackup /dev/nvme0n1p2 \
--header-backup-file /mnt/backup/luks/workstation-header.img
sudo umount /mnt/backup
sudo cryptsetup luksClose backup-usb
Tier 4: ARCHIVAL (M-Disc)
What Lives Here
Disc contents (age-encrypted tarballs):
| File | Contents |
|---|---|
|
GPG, SSH, pass, secrets, age keys (RESTORE FIRST) |
|
Complete backup (~/.secrets, ~/.config, ~/atelier, etc.) |
|
Decryption and restore instructions |
|
Integrity verification checksums |
Schedule
-
Annual: Burn new M-Disc
-
Quarterly: Verify disc readability and checksums
-
Before storing: Test readability immediately after burn
Why M-Disc
-
Durability: 1000+ year lifespan (vs ~5 years for regular DVD)
-
Offline: Immune to ransomware
-
Disaster-proof: Survives fire, flood, EMP
M-Disc Commands
Annual Burn Procedure
mkdir /tmp/mdisc-backup
tar -cvf /tmp/p0-critical.tar \
~/.secrets/.metadata/keys/ \
~/.ssh/ \
~/.gnupg/ \
~/.age/ \
~/.passage/ \
~/.arcanum/ \
~/.password-store/ \
~/.pki/ \
~/.local/share/gopass/ \
~/.config/gopass/ 2>&1 | awk 'END {print NR " files archived"}'
age -e -R ~/.age/recipients/self.txt \
-o /tmp/mdisc-backup/P0-CRITICAL-$(date +%Y-%m-%d).tar.age \
/tmp/p0-critical.tar
tar -cvf /tmp/full-backup.tar \
~/.secrets \
~/.gnupg \
~/.age \
~/.passage \
~/.arcanum \
~/.password-store \
~/.ssh \
~/.pki \
~/.config \
~/.local \
~/.ansible \
~/.claude \
~/.mozilla \
~/.vscode-oss \
~/.vim \
~/.tmux \
~/.terraform.d \
~/.gemini \
~/.w3m \
~/atelier \
~/bin \
~/Documents \
~/Pictures \
~/.zshrc.bak.* \
~/.zsh_history \
~/.bash_history \
~/.viminfo \
~/.claude.json \
~/.npmrc 2>&1 | awk 'END {print NR " files archived"}'
| Excludes reinstallable (~25G saved): ~/.cache, ~/.npm, ~/.rustup, ~/.cargo, ~/.pyenv, ~/.ollama, ~/.zoom |
age -e -R ~/.age/recipients/self.txt \
-o /tmp/mdisc-backup/FULL-BACKUP-$(date +%Y-%m-%d).tar.age \
/tmp/full-backup.tar
cat > /tmp/mdisc-backup/RECOVERY-README.txt << 'EOF'
COLD STORAGE ARCHIVE - RECOVERY
CONTENTS:
- P0-CRITICAL-*.tar.age Keys and secrets (RESTORE FIRST)
- FULL-BACKUP-*.tar.age Complete backup
DECRYPT:
age -d -i ~/.age/identities/personal.key FILE.age > FILE.tar
tar -xvf FILE.tar
OR PIPE DIRECTLY:
age -d -i ~/.age/identities/personal.key FILE.age | tar -xvf -
RESTORE ORDER:
1. Restore P0-CRITICAL first (you need keys to decrypt other things)
2. Restore FULL-BACKUP
3. Run: chown -R $USER:$USER ~
IF YOU LOST YOUR AGE KEY:
These files are UNRECOVERABLE. Store age key in multiple locations.
EOF
cd /tmp/mdisc-backup && sha256sum *.age > SHA256SUMS.txt
genisoimage -o /tmp/backup-$(date +%Y-%m-%d).iso /tmp/mdisc-backup/
wodim -v /tmp/backup-$(date +%Y-%m-%d).iso
sudo mount /dev/sr0 /mnt/cdrom
cd /mnt/cdrom && sha256sum -c SHA256SUMS.txt
sudo umount /mnt/cdrom
shred -vzn 3 /tmp/p0-critical.tar /tmp/full-backup.tar
rm -rf /tmp/mdisc-backup /tmp/backup-*.iso /tmp/*.tar
Quarterly Verification
Use this procedure to verify M-Disc integrity periodically.
sudo mount /dev/sr0 /mnt/cdrom
ls -la /mnt/cdrom/
cat /mnt/cdrom/RECOVERY-README.txt
cd /mnt/cdrom && sha256sum -c SHA256SUMS.txt
age -d -i ~/.age/identities/personal.key /mnt/cdrom/P0-CRITICAL-*.tar.age | tar -tvf - | head -20
sudo umount /mnt/cdrom
Recovery Procedures
Priority Order
-
age key - Without this, nothing else can be decrypted
-
SSH keys - Access to systems
-
dsec secrets - Credentials
-
Infrastructure - ISE, WLC, etc.
Scenario: Lost Workstation
sudo cryptsetup luksOpen /dev/sdX1 backup-usb
sudo mount /dev/mapper/backup-usb /mnt/backup
mkdir -p ~/.secrets/.metadata/keys
cp /mnt/backup/keys/master.age.key ~/.secrets/.metadata/keys/
chmod 600 ~/.secrets/.metadata/keys/master.age.key
cp -r /mnt/backup/ssh/* ~/.ssh/
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_*
git clone <secrets-repo> ~/.secrets
dsec show d000 dev/network
See Disaster Recovery for full procedures.
Verification Schedule
| Frequency | Action | Verification |
|---|---|---|
Weekly |
Check NAS backup dates |
|
Monthly |
Sync to LUKS USB #1 |
Mount and verify file dates |
Quarterly |
Rotate LUKS USB offsite |
Test decrypt on both USBs |
Annually |
Full recovery drill |
Restore to test VM |
Quick Reference
Daily Infrastructure Backup
dsource d000 dev/network
netapi ise backup --upload-nas
netapi wlc backup --upload-nas
netapi vyos backup --upload-nas
netapi ios backup --all --upload-nas
netapi kvm backup --all --upload-nas
netapi synology backup-status --detailed