Skip to content

Backup & Restore Procedures


Backup Philosophy

  • 3-2-1 rule: 3 copies, 2 different media, 1 offsite
  • Backups that haven't been tested are not backups
  • Restore procedures must be documented before a backup counts as real

Backup Targets

What Method Destination Schedule Retention
Docker volumes tar via docker run NAS (nas01:/backups/docker) Nightly 2 AM 30 days
NAS data Built-in NAS sync Azure Blob Nightly 3 AM 90 days
Config files (~/stacks/) Git push GitHub (private repo) On change Indefinite
VM snapshots Proxmox snapshot Local + NAS Weekly 4 weeks

Docker Volume Backup Script

Save as /usr/local/bin/backup-docker-volumes.sh:

#!/bin/bash
BACKUP_DIR="/mnt/nas/backups/docker"
DATE=$(date +%Y-%m-%d)
mkdir -p "$BACKUP_DIR/$DATE"

for VOLUME in $(docker volume ls -q); do
    docker run --rm \
        -v "$VOLUME":/data \
        -v "$BACKUP_DIR/$DATE":/backup \
        alpine tar czf "/backup/${VOLUME}.tar.gz" -C /data .
done

find "$BACKUP_DIR" -maxdepth 1 -type d -mtime +30 -exec rm -rf {} +
chmod +x /usr/local/bin/backup-docker-volumes.sh
# Crontab: 0 2 * * * /usr/local/bin/backup-docker-volumes.sh >> /var/log/docker-backup.log 2>&1

Restore Procedure — Docker Volume

docker stop <container-name>
docker run --rm \
    -v <volume-name>:/data \
    -v /mnt/nas/backups/docker/<DATE>:/backup \
    alpine tar xzf /backup/<volume-name>.tar.gz -C /data
docker start <container-name>
docker logs <container-name> --tail 50

Restore Verification Log

Date What From Backup Result Notes
YYYY-MM-DD Grafana volume YYYY-MM-DD ✅ Success