Automated Backup Strategies
Master the art of automated backups for your Raspberry Pi! This comprehensive guide covers everything from simple file backups to complete system imaging, ensuring your data and configurations are always protected with minimal manual intervention.
Introduction
Data loss is one of the most devastating problems that can affect any computing system, and Raspberry Pi projects are no exception. Whether it's SD card corruption, hardware failure, or accidental deletion, having a robust backup strategy is essential for maintaining project continuity and protecting valuable data.
Benefits of Automated Backups
Implementing automated backup strategies provides:
- Data Protection: Safeguard against hardware failures and corruption
- Quick Recovery: Minimize downtime with fast restoration processes
- Version Control: Track changes and revert to previous configurations
- Peace of Mind: Confidence that your work is always protected
- Reduced Manual Work: Automated processes require minimal intervention
- Compliance: Meet data retention and backup requirements
Backup Strategy Planning
1. Assess Your Backup Needs
Before implementing any backup solution, evaluate:
| # Analyze disk usage
df -h
du -sh /home /etc /var /opt
# Identify critical data
find /home -type f -size +10M
find /etc -name "*.conf" -o -name "*.cfg"
# Check database sizes (if applicable)
sudo du -sh /var/lib/mysql 2>/dev/null
sudo du -sh /var/lib/postgresql 2>/dev/null
|
2. Define Backup Requirements
| Backup Type |
Frequency |
Retention |
Priority |
| System Configuration |
Daily |
30 days |
High |
| User Data |
Hourly |
7 days |
High |
| Application Data |
Daily |
14 days |
Medium |
| Complete System Image |
Weekly |
4 weeks |
Medium |
| Logs |
Daily |
7 days |
Low |
3. Choose Backup Destinations
| # Local storage options
lsblk # List block devices
sudo fdisk -l # List all disks
# Network storage setup
sudo apt install nfs-common cifs-utils sshfs
# Cloud storage preparation
sudo apt install rclone awscli
|
File-Level Backup Solutions
1. Rsync-Based Backups
Basic Rsync Setup
| # Install rsync (usually pre-installed)
sudo apt install rsync
# Create backup directory structure
sudo mkdir -p /backup/{daily,weekly,monthly}
sudo mkdir -p /backup/exclude
# Create exclude file
sudo nano /backup/exclude/rsync-exclude.txt
|
Rsync exclude file:
| # System directories to exclude
/dev/*
/proc/*
/sys/*
/tmp/*
/run/*
/mnt/*
/media/*
/lost+found
# Cache and temporary files
.cache/*
.thumbnails/*
*.tmp
*.log
*.swp
# Large unnecessary files
*.iso
*.img
|
Daily Backup Script
| # Create daily backup script
sudo nano /usr/local/bin/daily-backup.sh
|
Daily backup script:
| #!/bin/bash
# Configuration
SOURCE_DIR="/"
BACKUP_ROOT="/backup/daily"
EXCLUDE_FILE="/backup/exclude/rsync-exclude.txt"
LOG_FILE="/var/log/backup.log"
DATE=$(date +%Y%m%d)
HOSTNAME=$(hostname)
# Create backup directory
BACKUP_DIR="$BACKUP_ROOT/$DATE"
mkdir -p "$BACKUP_DIR"
# Function to log messages
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}
log_message "Starting daily backup to $BACKUP_DIR"
# Perform incremental backup
rsync -avH \
--delete \
--delete-excluded \
--exclude-from="$EXCLUDE_FILE" \
--link-dest="$BACKUP_ROOT/latest" \
"$SOURCE_DIR" \
"$BACKUP_DIR/" 2>&1 | tee -a "$LOG_FILE"
# Check rsync exit status
RSYNC_EXIT_CODE=$?
if [ $RSYNC_EXIT_CODE -eq 0 ]; then
# Update latest symlink
rm -f "$BACKUP_ROOT/latest"
ln -s "$DATE" "$BACKUP_ROOT/latest"
log_message "Backup completed successfully"
# Cleanup old backups (keep 7 days)
find "$BACKUP_ROOT" -maxdepth 1 -type d -name "20*" -mtime +7 -exec rm -rf {} \;
log_message "Cleanup completed"
else
log_message "Backup failed with error code $RSYNC_EXIT_CODE"
exit 1
fi
# Send notification
if command -v mail >/dev/null; then
echo "Daily backup completed on $HOSTNAME" | mail -s "Backup Status" admin@example.com
fi
|
Make script executable:
| sudo chmod +x /usr/local/bin/daily-backup.sh
|
2. Network Backup Solutions
SSH/SCP Remote Backup
| # Create SSH key for automated backups
ssh-keygen -t ed25519 -f ~/.ssh/backup_key -N ""
# Copy key to backup server
ssh-copy-id -i ~/.ssh/backup_key.pub user@backup-server
# Create remote backup script
sudo nano /usr/local/bin/remote-backup.sh
|
Remote backup script:
| #!/bin/bash
REMOTE_HOST="backup-server"
REMOTE_USER="backupuser"
REMOTE_PATH="/backups/raspberry-pi"
SSH_KEY="/home/pi/.ssh/backup_key"
SOURCE_DIRS="/home /etc /var/log /opt"
# Create tar archive
BACKUP_FILE="backup-$(hostname)-$(date +%Y%m%d-%H%M%S).tar.gz"
tar -czf "/tmp/$BACKUP_FILE" $SOURCE_DIRS 2>/dev/null
# Upload to remote server
scp -i "$SSH_KEY" "/tmp/$BACKUP_FILE" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH/"
# Cleanup local file
rm "/tmp/$BACKUP_FILE"
# Cleanup old remote backups (keep 14 days)
ssh -i "$SSH_KEY" "$REMOTE_USER@$REMOTE_HOST" \
"find $REMOTE_PATH -name 'backup-*.tar.gz' -mtime +14 -delete"
|
NFS Network Backup
| # Install NFS client
sudo apt install nfs-common
# Create mount point
sudo mkdir -p /mnt/nfs-backup
# Add to fstab for automatic mounting
echo "backup-server:/export/pi-backups /mnt/nfs-backup nfs defaults,_netdev 0 0" | sudo tee -a /etc/fstab
# Mount NFS share
sudo mount /mnt/nfs-backup
# Create NFS backup script
sudo nano /usr/local/bin/nfs-backup.sh
|
3. Cloud Backup Solutions
Rclone Configuration
| # Install rclone
curl https://rclone.org/install.sh | sudo bash
# Configure cloud storage
rclone config
# Create cloud backup script
sudo nano /usr/local/bin/cloud-backup.sh
|
Cloud backup script:
| #!/bin/bash
CLOUD_REMOTE="gdrive" # Name from rclone config
CLOUD_PATH="/raspberry-pi-backups/$(hostname)"
SOURCE_DIRS="/home /etc"
TEMP_DIR="/tmp/cloud-backup"
DATE=$(date +%Y%m%d)
# Create temporary directory
mkdir -p "$TEMP_DIR"
# Create backup archive
tar -czf "$TEMP_DIR/backup-$DATE.tar.gz" $SOURCE_DIRS
# Upload to cloud
rclone copy "$TEMP_DIR/backup-$DATE.tar.gz" "$CLOUD_REMOTE:$CLOUD_PATH/"
# Cleanup local temp files
rm -rf "$TEMP_DIR"
# Cleanup old cloud backups
rclone delete "$CLOUD_REMOTE:$CLOUD_PATH" --min-age 30d
|
System Image Backups
1. SD Card Imaging
Create Image Backup Script
| # Create system imaging script
sudo nano /usr/local/bin/create-image-backup.sh
|
System imaging script:
| #!/bin/bash
BACKUP_DIR="/backup/images"
DATE=$(date +%Y%m%d)
HOSTNAME=$(hostname)
IMAGE_FILE="$BACKUP_DIR/$HOSTNAME-$DATE.img"
# Create backup directory
mkdir -p "$BACKUP_DIR"
# Get root device
ROOT_DEVICE=$(df / | tail -1 | awk '{print $1}' | sed 's/p[0-9]*$//')
echo "Creating image backup of $ROOT_DEVICE to $IMAGE_FILE"
# Create compressed image
sudo dd if="$ROOT_DEVICE" bs=4M status=progress | gzip > "$IMAGE_FILE.gz"
if [ $? -eq 0 ]; then
echo "Image backup completed successfully"
ls -lh "$IMAGE_FILE.gz"
# Cleanup old images (keep 4 weeks)
find "$BACKUP_DIR" -name "*.img.gz" -mtime +28 -delete
else
echo "Image backup failed"
exit 1
fi
|
PiShrink Integration
| # Download and install PiShrink
wget https://raw.githubusercontent.com/Drewsif/PiShrink/master/pishrink.sh
sudo chmod +x pishrink.sh
sudo mv pishrink.sh /usr/local/bin/
# Create shrinking backup script
sudo nano /usr/local/bin/shrink-backup.sh
|
Shrinking backup script:
| #!/bin/bash
SOURCE_IMAGE="$1"
OUTPUT_DIR="/backup/compressed"
if [ -z "$SOURCE_IMAGE" ]; then
echo "Usage: $0 <source-image>"
exit 1
fi
mkdir -p "$OUTPUT_DIR"
# Copy image to working directory
WORK_IMAGE="$OUTPUT_DIR/$(basename "$SOURCE_IMAGE" .gz)"
if [[ "$SOURCE_IMAGE" == *.gz ]]; then
gunzip -c "$SOURCE_IMAGE" > "$WORK_IMAGE"
else
cp "$SOURCE_IMAGE" "$WORK_IMAGE"
fi
# Shrink image
/usr/local/bin/pishrink.sh "$WORK_IMAGE"
# Compress shrunk image
gzip "$WORK_IMAGE"
echo "Shrunk image created: $WORK_IMAGE.gz"
|
2. Incremental System Backups
BTRFS Snapshots (if using BTRFS)
| # Install btrfs tools
sudo apt install btrfs-progs
# Create snapshot script
sudo nano /usr/local/bin/btrfs-snapshot.sh
|
BTRFS snapshot script:
| #!/bin/bash
SNAPSHOT_DIR="/snapshots"
DATE=$(date +%Y%m%d-%H%M%S)
# Create snapshots directory
sudo mkdir -p "$SNAPSHOT_DIR"
# Create read-only snapshot
sudo btrfs subvolume snapshot -r / "$SNAPSHOT_DIR/root-$DATE"
# List snapshots
sudo btrfs subvolume list "$SNAPSHOT_DIR"
- Cleanup old snapshots (keep 10)
SNAPSHOTS=($(sudo btrfs subvolume list "$SNAPSHOT_DIR" | awk '{print $9}' | sort))
SNAPSHOT_COUNT=$(sudo btrfs subvolume list "$SNAPSHOT_DIR" | wc -l)
if [ $SNAPSHOT_COUNT -gt 10 ]; then
REMOVE_COUNT=$((SNAPSHOT_COUNT-10))
# Remove old snapshots from list
sudo btrfs subvolume list "$SNAPSHOT_DIR" | awk '{print $9}' | sort | head -$REMOVE_COUNT | \
while read snapshot_name; do
sudo btrfs subvolume delete "$SNAPSHOT_DIR/$snapshot_name"
done
fi
|
Database Backups
1. MySQL/MariaDB Backups
| # Create database backup script
sudo nano /usr/local/bin/mysql-backup.sh
|
MySQL backup script:
| #!/bin/bash
DB_USER="backup_user"
DB_PASS="backup_password"
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d)
mkdir -p "$BACKUP_DIR"
# Backup all databases
mysqldump -u"$DB_USER" -p"$DB_PASS" --all-databases --single-transaction \
--routines --triggers > "$BACKUP_DIR/all-databases-$DATE.sql"
# Compress backup
gzip "$BACKUP_DIR/all-databases-$DATE.sql"
# Cleanup old backups (keep 7 days)
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +7 -delete
|
2. PostgreSQL Backups
| # Create PostgreSQL backup script
sudo nano /usr/local/bin/postgres-backup.sh
|
PostgreSQL backup script:
| #!/bin/bash
BACKUP_DIR="/backup/postgres"
DATE=$(date +%Y%m%d)
mkdir -p "$BACKUP_DIR"
# Backup all databases
sudo -u postgres pg_dumpall > "$BACKUP_DIR/all-databases-$DATE.sql"
# Compress backup
gzip "$BACKUP_DIR/all-databases-$DATE.sql"
# Cleanup old backups
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +7 -delete
|
Application-Specific Backups
1. Docker Container Backups
| # Create Docker backup script
sudo nano /usr/local/bin/docker-backup.sh
|
Docker backup script:
| #!/bin/bash
BACKUP_DIR="/backup/docker"
DATE=$(date +%Y%m%d)
mkdir -p "$BACKUP_DIR"
# Backup Docker volumes
docker run --rm -v docker_volume:/data -v "$BACKUP_DIR":/backup \
alpine tar czf "/backup/docker-volumes-$DATE.tar.gz" /data
# Export container configurations
docker-compose config > "$BACKUP_DIR/docker-compose-$DATE.yml"
# Save running container states
docker ps --format "table Names\tImage\tStatus" > \
"$BACKUP_DIR/running-containers-$DATE.txt"
|
2. Home Assistant Backups
| # Create Home Assistant backup script
sudo nano /usr/local/bin/homeassistant-backup.sh
|
Home Assistant backup script:
| #!/bin/bash
HA_DIR="/home/homeassistant/.homeassistant"
BACKUP_DIR="/backup/homeassistant"
DATE=$(date +%Y%m%d)
mkdir -p "$BACKUP_DIR"
# Stop Home Assistant
sudo systemctl stop home-assistant@homeassistant
# Create backup
tar -czf "$BACKUP_DIR/homeassistant-$DATE.tar.gz" -C "$HA_DIR" .
# Start Home Assistant
sudo systemctl start home-assistant@homeassistant
# Cleanup old backups
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +14 -delete
|
Automated Scheduling
1. Cron Configuration
| # Edit crontab for root
sudo crontab -e
|
Example cron schedule:
| # Daily file backup at 2 AM
0 2 * * * /usr/local/bin/daily-backup.sh
# Weekly system image at 3 AM Sunday
0 3 * * 0 /usr/local/bin/create-image-backup.sh
# Hourly user data backup
0 * * * * /usr/local/bin/user-backup.sh
# Daily database backup at 1 AM
0 1 * * * /usr/local/bin/mysql-backup.sh
# Cloud backup every 6 hours
0 */6 * * * /usr/local/bin/cloud-backup.sh
|
2. Systemd Timer Configuration
Create Backup Service
| # Create backup service file
sudo nano /etc/systemd/system/daily-backup.service
|
Systemd service file:
| [Unit]
Description=Daily Backup Service
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/daily-backup.sh
User=root
|
Create Backup Timer
| # Create backup timer file
sudo nano /etc/systemd/system/daily-backup.timer
|
Systemd timer file:
| [Unit]
Description=Daily Backup Timer
Requires=daily-backup.service
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
|
Enable and start timer:
| sudo systemctl enable daily-backup.timer
sudo systemctl start daily-backup.timer
sudo systemctl status daily-backup.timer
|
Backup Monitoring and Alerting
1. Backup Status Monitoring
| # Create backup monitoring script
sudo nano /usr/local/bin/backup-monitor.sh
|
Backup monitoring script:
| #!/bin/bash
BACKUP_DIRS="/backup/daily /backup/weekly /backup/mysql"
ALERT_EMAIL="admin@example.com"
WARNING_HOURS=25 # Alert if backup older than 25 hours
for DIR in $BACKUP_DIRS; do
if [ -d "$DIR" ]; then
LATEST=$(find "$DIR" -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -d' ' -f2-)
if [ -n "$LATEST" ]; then
AGE_HOURS=$(( ($(date +%s) - $(stat -c %Y "$LATEST")) / 3600 ))
if [ $AGE_HOURS -gt $WARNING_HOURS ]; then
echo "WARNING: Backup in $DIR is $AGE_HOURS hours old" | \
mail -s "Backup Alert: $HOSTNAME" "$ALERT_EMAIL"
fi
else
echo "ERROR: No backups found in $DIR" | \
mail -s "Backup Alert: $HOSTNAME" "$ALERT_EMAIL"
fi
fi
done
|
2. Backup Verification
| # Create backup verification script
sudo nano /usr/local/bin/verify-backup.sh
|
Backup verification script:
| #!/bin/bash
BACKUP_DIR="/backup/daily/latest"
TEST_FILES="/etc/passwd /etc/hostname /home/pi/.bashrc"
echo "Verifying backup integrity..."
for FILE in $TEST_FILES; do
if [ -f "$BACKUP_DIR$FILE" ]; then
echo "✓ $FILE exists in backup"
# Compare checksums
ORIG_SUM=$(md5sum "$FILE" | cut -d' ' -f1)
BACKUP_SUM=$(md5sum "$BACKUP_DIR$FILE" | cut -d' ' -f1)
if [ "$ORIG_SUM" = "$BACKUP_SUM" ]; then
echo "✓ $FILE checksum matches"
else
echo "✗ $FILE checksum mismatch"
fi
else
echo "✗ $FILE missing from backup"
fi
done
|
Backup Restoration Procedures
1. File Restoration
| # Create restoration script
sudo nano /usr/local/bin/restore-files.sh
|
File restoration script:
| #!/bin/bash
usage() {
echo "Usage: $0 <backup-date> <source-path> [destination-path]"
echo "Example: $0 20240601 /home/pi/important.txt"
exit 1
}
BACKUP_DATE="$1"
SOURCE_PATH="$2"
# Use source path as destination if not specified
if [ -n "$3" ]; then
DEST_PATH="$3"
else
DEST_PATH="$SOURCE_PATH"
fi
if [ -z "$BACKUP_DATE" ] || [ -z "$SOURCE_PATH" ]; then
usage
fi
BACKUP_DIR="/backup/daily/$BACKUP_DATE"
if [ ! -d "$BACKUP_DIR" ]; then
echo "Error: Backup directory $BACKUP_DIR not found"
exit 1
fi
BACKUP_FILE="$BACKUP_DIR$SOURCE_PATH"
if [ ! -f "$BACKUP_FILE" ]; then
echo "Error: File $BACKUP_FILE not found in backup"
exit 1
fi
echo "Restoring $SOURCE_PATH from backup dated $BACKUP_DATE"
echo "Destination: $DEST_PATH"
# Create destination directory if needed
mkdir -p "$(dirname "$DEST_PATH")"
# Copy file from backup
cp "$BACKUP_FILE" "$DEST_PATH"
echo "Restoration completed"
|
2. System Restoration
| # Create system restoration guide
sudo nano /usr/local/bin/restore-system.sh
|
System restoration script:
| #!/bin/bash
echo "System Restoration Script"
echo "========================"
echo "This script provides guidance for system restoration"
echo ""
echo "1. For file-level restoration:"
echo " sudo /usr/local/bin/restore-files.sh <date> <file-path>"
echo ""
echo "2. For complete system restoration from image:"
echo " sudo dd if=/backup/images/system-backup.img.gz | gunzip | dd of=/dev/mmcblk0 bs=4M"
echo ""
echo "3. For database restoration:"
echo " # MySQL: gunzip < backup.sql.gz | mysql -u root -p"
echo " # PostgreSQL: gunzip < backup.sql.gz | sudo -u postgres psql"
echo ""
echo "4. For configuration restoration:"
echo " sudo rsync -av /backup/daily/latest/etc/ /etc/"
echo ""
echo "WARNING: Always backup current system before restoration!"
|
Backup Strategy Examples
1. Home Server Backup Strategy
| # Create comprehensive home server backup
sudo nano /usr/local/bin/homeserver-backup.sh
|
Home server backup:
| #!/bin/bash
# Configuration
BACKUP_ROOT="/backup"
NAS_MOUNT="/mnt/nas"
CLOUD_REMOTE="gdrive:homeserver"
# Daily incremental backup
/usr/local/bin/daily-backup.sh
# Database backup
/usr/local/bin/mysql-backup.sh
# Copy to NAS
rsync -av "$BACKUP_ROOT/daily/latest/" "$NAS_MOUNT/pi-backup/"
# Weekly cloud sync
if [ "$(date +%u)" -eq 7 ]; then
rclone sync "$BACKUP_ROOT/daily/latest" "$CLOUD_REMOTE"
fi
|
2. IoT Device Backup Strategy
| # Create IoT device backup
sudo nano /usr/local/bin/iot-backup.sh
|
IoT device backup:
| #!/bin/bash
# Minimal backup for IoT devices
CONFIG_DIRS="/etc /home/pi/.config"
DATA_DIR="/var/log /opt/iot-data"
# Create lightweight backup
tar -czf "/tmp/iot-backup-$(date +%Y%m%d).tar.gz" $CONFIG_DIRS $DATA_DIR
# Upload to cloud
rclone copy "/tmp/iot-backup-*.tar.gz" "cloud:iot-backups/"
# Cleanup
rm /tmp/iot-backup-*.tar.gz
|
Best Practices and Tips
1. Backup Best Practices
3-2-1 Rule:
- 3 copies of important data
- 2 different storage media
- 1 offsite backup
Testing:
- Regularly test restoration procedures
- Verify backup integrity
- Document restoration processes
Security:
- Encrypt sensitive backups
- Secure backup storage locations
- Use appropriate access controls
| # Optimize backup performance
echo "vm.dirty_ratio = 5" | sudo tee -a /etc/sysctl.conf
echo "vm.dirty_background_ratio = 2" | sudo tee -a /etc/sysctl.conf
# Use ionice for backup processes
ionice -c 3 nice -n 19 /usr/local/bin/daily-backup.sh
|
3. Storage Management
| # Monitor backup storage usage
df -h /backup
du -sh /backup/*
# Create storage cleanup script
sudo nano /usr/local/bin/backup-cleanup.sh
|
Storage cleanup script:
| #!/bin/bash
BACKUP_ROOT="/backup"
MAX_USAGE=80 # Maximum usage percentage
CURRENT_USAGE=$(df "$BACKUP_ROOT" | tail -1 | awk '{print $5}' | sed 's/%//')
if [ "$CURRENT_USAGE" -gt "$MAX_USAGE" ]; then
echo "Backup storage usage at $CURRENT_USAGE%, cleaning up..."
# Remove oldest daily backups first
find "$BACKUP_ROOT/daily" -maxdepth 1 -type d -mtime +3 -exec rm -rf {} \;
# Remove old compressed images
find "$BACKUP_ROOT/images" -name "*.img.gz" -mtime +14 -delete
echo "Cleanup completed"
fi
|
Troubleshooting Common Issues
1. Backup Failures
| # Check disk space
df -h
# Check permissions
ls -la /backup
# Check cron logs
sudo journalctl -u cron
# Test backup script manually
sudo /usr/local/bin/daily-backup.sh
|
2. Network Backup Issues
| # Test network connectivity
ping backup-server
# Test SSH connection
ssh -i ~/.ssh/backup_key user@backup-server
# Check NFS mount
sudo mount -t nfs backup-server:/path /mnt/backup
|
| # Monitor I/O during backup
sudo iotop
# Check system load
top
htop
# Monitor network usage
sudo nethogs
|
Conclusion
A well-planned and automated backup strategy is essential for protecting your Raspberry Pi projects and data. This comprehensive guide provides multiple approaches to backup automation, from simple file-level backups to complete system imaging.
Key takeaways:
- Implement Multiple Backup Types: Combine file-level, database, and system image backups
- Automate Everything: Use cron jobs or systemd timers for consistent backups
- Test Regularly: Verify backup integrity and practice restoration procedures
- Monitor and Alert: Set up monitoring to ensure backups are working
- Follow Best Practices: Implement the 3-2-1 rule and encrypt sensitive data
Remember that backup strategies should be tailored to your specific needs, considering factors like data importance, recovery time objectives, and available storage resources. Start with basic automated backups and gradually implement more sophisticated solutions as your requirements grow.
The investment in a robust backup strategy will pay dividends when you need to recover from hardware failures, data corruption, or other disasters. Your future self will thank you for implementing these automated backup solutions!