Backup & Restore Guide (Verified Compressed Archives)
This guide walks you through setting up automated, scheduled backups for a Raspberry Pi using a compressed archive (.tar.gz) with post-creation verification, as well as how to restore a system from a backup file.
Why Choose This Method Over dd?
- File-System Safe:
rsyncandtaroperate cleanly on active file systems, avoiding disk corruption caused by live sector writes duringddclones. - Storage Efficient: Instead of creating a raw image matching your SD card size (e.g., 32–64 GB), compressed backups only archive actual files—typically resulting in backups of a few hundred megabytes to a few gigabytes.
- Hardware Flexible: Restoring a
ddimage requires a target SD card of equal or larger capacity down to the exact sector count. File archives can be restored to an SD card of any size. - Fast & Verifiable: Automated checks confirm archive integrity immediately upon creation, allowing you to catch storage failures early.
Part 1: Backup Script Setup
1. Create the Script Directory
Create a directory for your custom scripts and open a new file named raspi_backup.sh:
mkdir -p ~/scripts
nano ~/scripts/raspi_backup.sh
2. Script Code
Paste the following code into ~/scripts/raspi_backup.sh. Update BACKUP_PATH to point to your external mount point if it differs.
#!/bin/bash
# Exit immediately if a command exits with a non-zero status
set -e
# Configuration
BACKUP_PATH="/mnt/external_disk/raspi_backups"
DATE=$(date +%Y-%m-%d)
ARCHIVE="$BACKUP_PATH/raspi_backup_$DATE.tar.gz"
TEMP_DIR="/tmp/raspi_backup_temp"
# Script directory and log path
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOG_FILE="$SCRIPT_DIR/raspi_backup.log"
# Helper function to append ISO-timestamped log messages
log_message() {
local MESSAGE="$1"
echo "$(date '+%Y-%m-%d %H:%M:%S') - $MESSAGE" | tee -a "$LOG_FILE"
}
# Enforce strict backup path availability check
if [ ! -d "$BACKUP_PATH" ]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') - ERROR: Backup path '$BACKUP_PATH' is unavailable or incorrect." >> "$LOG_FILE"
exit 1
fi
log_message "START: Beginning system backup to $ARCHIVE"
# Setup clean temporary workspace
rm -rf "$TEMP_DIR"
mkdir -p "$TEMP_DIR"
trap 'rm -rf "$TEMP_DIR"' EXIT
# Export installed package list
dpkg --get-selections > "$TEMP_DIR/package-list.txt"
# Create compressed system archive
tar -czpf "$ARCHIVE" \
--warning=no-file-ignored \
--exclude=/dev \
--exclude=/proc \
--exclude=/sys \
--exclude=/tmp \
--exclude=/run \
--exclude=/mnt \
--exclude=/media \
--exclude=/lost+found \
--exclude='home/*/.cache' \
--exclude='home/*/.local/share/Trash' \
--exclude='home/*/.gvfs' \
-C / \
etc boot home var/www usr/local \
-C "$TEMP_DIR" package-list.txt
# Verify archive integrity
log_message "VERIFYING: Running post-backup archive integrity test..."
if tar -tzf "$ARCHIVE" > /dev/null 2>&1; then
log_message "SUCCESS: Archive verification passed ($ARCHIVE)."
else
log_message "FAILURE: Archive verification failed! Removing corrupted file ($ARCHIVE)."
rm -f "$ARCHIVE"
exit 1
fi
# Clean up archives older than 30 days
find "$BACKUP_PATH" -maxdepth 1 -name "raspi_backup_*.tar.gz" -mtime +30 -exec rm -f {} +
log_message "END: Backup process finished successfully."
3. Set Execution Permissions
Make the script executable:
chmod +x ~/scripts/raspi_backup.sh
Part 2: Schedule the Backup with Cron
Run the backup as root to preserve full system file ownerships:
sudo crontab -e
Add the entry below to run the script every Sunday at 2:00 AM.
Note: The cron output is explicitly piped to
/dev/nullbecause the script handles its own logging internally. Redirecting cron output prevents duplicate entries inraspi_backup.log.
0 2 * * 0 /home/pi/scripts/raspi_backup.sh > /dev/null 2>&1
Log outputs will appear in ~/scripts/raspi_backup.log:
2026-08-30 02:00:00 - START: Beginning system backup to /mnt/external_disk/raspi_backups/raspi_backup_2026-08-30.tar.gz
2026-08-30 02:02:15 - VERIFYING: Running post-backup archive integrity test...
2026-08-30 02:03:10 - SUCCESS: Archive verification passed (/mnt/external_disk/raspi_backups/raspi_backup_2026-08-30.tar.gz).
2026-08-30 02:03:10 - END: Backup process finished successfully.
Part 3: Restoring to a Fresh Raspbian Install
Follow these steps to restore your configurations, user files, and installed software onto a fresh installation.
- 1. Test Archive Integrity: Verify file integrity before extraction. Mount your external drive on the fresh OS install. Test the target archive to ensure it is valid before extracting:
tar -tzf /mnt/external_disk/raspi_backups/raspi_backup_2026-08-30.tar.gz > /dev/null
(If this completes silently without errors, your archive is healthy.)
- 2. Extract System Files: Unpack system directories to root.
Extract the contents of the archive directly into root (
/):
sudo tar -xzpf /mnt/external_disk/raspi_backups/raspi_backup_2026-08-30.tar.gz -C /
- 3. Reinstall Packages: Match previously installed packages. Reinstall all software recorded in the package selection file:
sudo dpkg --clear-selections
sudo dpkg --set-selections < /package-list.txt
sudo apt-get dselect-upgrade -y
sudo rm /package-list.txt
- 4. Reboot System: Apply configuration changes. Reboot to apply network settings, system configuration, and service states:
sudo reboot