Incremental Backup with rsnapshot: Complete Implementation Guide
Introduction
Rsnapshot is a powerful filesystem snapshot utility built on rsync that creates incremental backups of Linux systems with remarkable storage efficiency. By leveraging hard links and rsync's delta-transfer algorithm, rsnapshot can maintain multiple full backup snapshots while consuming disk space proportional to only the changed data. This elegant approach makes it possible to store daily, weekly, and monthly backups that appear as complete copies but share unchanged files at the filesystem level.
For system administrators managing Linux servers, rsnapshot provides an ideal balance between simplicity, efficiency, and functionality. Unlike traditional incremental backup solutions that require complex restoration procedures involving multiple backup sets, rsnapshot presents each backup interval as a complete, browsable filesystem snapshot. This means users can navigate backup directories just like regular folders, copying files directly without special restoration tools or procedures.
This comprehensive guide covers rsnapshot from installation through advanced production deployments, including configuration best practices, automation strategies, real-world implementation scenarios, and troubleshooting. Whether you're protecting a single server or implementing enterprise-wide backup infrastructure following the 3-2-1 backup rule, rsnapshot provides a proven, reliable solution.
Understanding rsnapshot Architecture
How rsnapshot Works
Rsnapshot creates the illusion of multiple full backups while storing only one copy of unchanged files through hard link technology:
Hard link mechanism: When a file hasn't changed between backup intervals, rsnapshot creates a hard link to the existing file instead of copying it. Multiple directory entries point to the same inode (physical file data), consuming negligible additional space.
Backup rotation: Rsnapshot maintains configurable retention intervals (hourly, daily, weekly, monthly). When rotation occurs, old snapshots are rotated forward, and a new snapshot is created from the live system.
Space efficiency: A year of daily backups might consume only 2-3 times the space of the original data, depending on change rate, versus 365 times for traditional full backups.
Rsnapshot vs Traditional Backup Methods
Comparison with alternative approaches:
Rsnapshot vs rsync:
- Rsync: Single mirror, no historical versions
- Rsnapshot: Multiple dated snapshots with historical retention
- Rsnapshot: Built-in rotation and retention management
- Both: Use rsync for efficient data transfer
Rsnapshot vs tar-based backups:
- Tar: Creates archives requiring extraction
- Rsnapshot: Live filesystem browsing and direct file access
- Tar: Full backups consume cumulative space
- Rsnapshot: Hard links minimize space consumption
Rsnapshot vs LVM snapshots:
- LVM: Filesystem-level, fast creation
- Rsnapshot: File-level, works across systems
- LVM: Limited by volume group size
- Rsnapshot: Can backup to any destination
Rsnapshot vs modern deduplication tools (Borg, Restic):
- Borg/Restic: Block-level deduplication, encrypted repositories
- Rsnapshot: Simple filesystem snapshots, human-readable
- Borg/Restic: Require special tools for browsing/restoration
- Rsnapshot: Direct filesystem access with standard tools
Key Features and Benefits
Multiple retention intervals: Configure hourly, daily, weekly, monthly, and yearly retention policies to match business requirements.
Storage efficiency: Hard links ensure unchanged files consume zero additional space across snapshots.
Simple restoration: Browse backups as regular directories, copy files with standard cp/rsync commands.
Cross-platform: Backup local systems, remote systems via SSH, or network storage.
Flexible scheduling: Integrate with cron for automated execution at defined intervals.
Atomic rotation: Backup operations are atomic—either complete successfully or leave previous backups intact.
Scriptable: Pre- and post-execution scripts enable application-consistent backups (database dumps, service stops, etc.).
Installation and Initial Setup
Installing rsnapshot
Rsnapshot is available in standard Linux distribution repositories:
Ubuntu/Debian:
# Update package lists
sudo apt update
# Install rsnapshot
sudo apt install rsnapshot
# Verify installation
rsnapshot -V
CentOS/Rocky Linux/RHEL:
# Install EPEL repository (if not already available)
sudo dnf install epel-release
# Install rsnapshot
sudo dnf install rsnapshot
# Verify installation
rsnapshot -V
Expected output:
rsnapshot 1.4.x
Directory Structure Overview
Understanding rsnapshot's directory structure is essential:
/backup/
├── hourly.0/ # Most recent hourly snapshot
├── hourly.1/ # Previous hourly snapshot
├── hourly.2/
├── hourly.3/
├── daily.0/ # Most recent daily snapshot
├── daily.1/ # Previous daily snapshot
├── daily.2/
├── ...
├── weekly.0/ # Most recent weekly snapshot
├── weekly.1/
├── ...
└── monthly.0/ # Most recent monthly snapshot
Each directory appears as a complete backup but shares unchanged files via hard links.
Configuration File Basics
The main configuration file is /etc/rsnapshot.conf:
# View default configuration
sudo cat /etc/rsnapshot.conf
# Create backup of original config
sudo cp /etc/rsnapshot.conf /etc/rsnapshot.conf.orig
# Edit configuration
sudo nano /etc/rsnapshot.conf
Critical syntax rules:
- Use TABS (not spaces) between parameters and values
- Trailing slashes matter for directories
- Comments start with #
- Test configuration after changes
Basic Configuration
Essential Configuration Directives
Edit /etc/rsnapshot.conf with these fundamental settings:
#################################################
# rsnapshot.conf - rsnapshot configuration file #
#################################################
# Snapshot root directory (where backups are stored)
snapshot_root /backup/
# External programs (paths must be absolute)
cmd_cp /usr/bin/cp
cmd_rm /usr/bin/rm
cmd_rsync /usr/bin/rsync
cmd_ssh /usr/bin/ssh
cmd_logger /usr/bin/logger
# Optional but recommended
cmd_du /usr/bin/du
# Verbosity level (1-5, higher = more verbose)
verbose 2
# Log level (1-5, higher = more detailed)
loglevel 3
# Log file location
logfile /var/log/rsnapshot.log
# Lock file to prevent concurrent runs
lockfile /var/run/rsnapshot.pid
# Stop on stale lockfile
stop_on_stale_lockfile 0
# Rsync short arguments
rsync_short_args -a
# Rsync long arguments
rsync_long_args --delete --numeric-ids --relative --delete-excluded
# SSH options (if backing up remote systems)
#ssh_args -p 22 -i /root/.ssh/backup_key
# Retain old snapshots
link_dest 1
Defining Retention Intervals
Configure how many snapshots to retain for each interval:
#########################################
# BACKUP LEVELS / INTERVALS #
#########################################
# Each must be unique and in descending order
retain hourly 6
retain daily 7
retain weekly 4
retain monthly 12
This configuration maintains:
- 6 hourly backups (last 6 hours)
- 7 daily backups (last week)
- 4 weekly backups (last month)
- 12 monthly backups (last year)
Specifying Backup Sources
Define what to backup using the backup directive:
#########################################
# BACKUP POINTS / SCRIPTS #
#########################################
# Format: backup SOURCE DESTINATION [EXCLUDE]
# Local filesystem backups
backup /home/ localhost/
backup /etc/ localhost/
backup /var/www/ localhost/
backup /opt/ localhost/
# Remote backup via SSH
backup user@remote-server:/var/www/ remote-web-server/
# With excludes
backup /var/log/ localhost/ exclude=*.gz,exclude=*.old
Path syntax:
/home/- Backup directory itself tolocalhost/home/- Trailing slash creates:
snapshot_root/interval.N/localhost/home/ - Remote paths:
user@host:/path/via SSH
Exclude Patterns
Exclude unnecessary files to optimize storage:
# Global excludes (apply to all backups)
exclude *.tmp
exclude *.swp
exclude cache/
exclude .cache/
# Per-backup excludes (in backup directive)
backup /home/ localhost/ exclude=Downloads/,exclude=.cache/,exclude=*.iso
Create exclude file for complex patterns (/etc/rsnapshot.exclude):
*.log
*.tmp
.cache/
.thumbnails/
node_modules/
vendor/
.git/
__pycache__/
*.pyc
Reference in configuration:
exclude_file /etc/rsnapshot.exclude
Advanced Configuration
Script Execution Hooks
Execute scripts before/after backups for application consistency:
#########################################
# BACKUP SCRIPTS #
#########################################
# Execute before backup (database dumps, etc.)
backup_script /usr/local/bin/pre-backup.sh unused1/
# Execute after backup (cleanup, verification, etc.)
backup_script /usr/local/bin/post-backup.sh unused2/
Example pre-backup script (/usr/local/bin/pre-backup.sh):
#!/bin/bash
# Dump databases before backup
DUMP_DIR="/var/backups/db-dumps"
mkdir -p "$DUMP_DIR"
# MySQL dump
mysqldump --all-databases --single-transaction \
| gzip > "$DUMP_DIR/mysql-all-$(date +%Y%m%d).sql.gz"
# PostgreSQL dump
sudo -u postgres pg_dumpall \
| gzip > "$DUMP_DIR/postgresql-all-$(date +%Y%m%d).sql.gz"
# Cleanup old dumps (keep 3 days)
find "$DUMP_DIR" -name "*.sql.gz" -mtime +3 -delete
exit 0
Example post-backup script (/usr/local/bin/post-backup.sh):
#!/bin/bash
# Verify backup completion and send notification
SNAPSHOT_ROOT="/backup"
LATEST_BACKUP="$SNAPSHOT_ROOT/daily.0"
if [ -d "$LATEST_BACKUP" ]; then
BACKUP_SIZE=$(du -sh "$LATEST_BACKUP" | cut -f1)
echo "Backup completed successfully. Size: $BACKUP_SIZE" | \
mail -s "Backup Success - $(hostname)" [email protected]
else
echo "Backup directory not found!" | \
mail -s "Backup FAILED - $(hostname)" [email protected]
fi
exit 0
Make scripts executable:
sudo chmod +x /usr/local/bin/pre-backup.sh
sudo chmod +x /usr/local/bin/post-backup.sh
Remote Backup Configuration
Backing up remote servers over SSH:
1. Configure SSH key authentication:
# Generate SSH key (on backup server)
ssh-keygen -t ed25519 -f /root/.ssh/rsnapshot_key -N ""
# Copy to remote server
ssh-copy-id -i /root/.ssh/rsnapshot_key.pub user@remote-server
# Test connection
ssh -i /root/.ssh/rsnapshot_key user@remote-server "echo SSH working"
2. Configure rsnapshot for remote access:
# SSH arguments with key
ssh_args -i /root/.ssh/rsnapshot_key
# Remote backup points
backup root@web-server:/var/www/ web-server/
backup root@db-server:/var/lib/mysql/ db-server/
backup root@app-server:/opt/application/ app-server/
LVM Snapshot Integration
For consistent filesystem backups of busy systems:
# Use LVM snapshot for /var
backup /mnt/lvm-snapshot/var/ localhost/
# Script to create LVM snapshot before backup
backup_script /usr/local/bin/create-lvm-snapshot.sh lvm-scripts/
LVM snapshot script:
#!/bin/bash
# /usr/local/bin/create-lvm-snapshot.sh
VG="vg0"
LV="var"
SNAPSHOT_SIZE="5G"
SNAPSHOT_NAME="${LV}_snap"
MOUNT_POINT="/mnt/lvm-snapshot"
# Remove old snapshot if exists
if lvdisplay "/dev/$VG/$SNAPSHOT_NAME" &>/dev/null; then
umount "$MOUNT_POINT" 2>/dev/null
lvremove -f "/dev/$VG/$SNAPSHOT_NAME"
fi
# Create new snapshot
lvcreate -L "$SNAPSHOT_SIZE" -s -n "$SNAPSHOT_NAME" "/dev/$VG/$LV"
# Mount snapshot
mkdir -p "$MOUNT_POINT"
mount -o ro "/dev/$VG/$SNAPSHOT_NAME" "$MOUNT_POINT"
exit 0
Post-backup cleanup script:
#!/bin/bash
# /usr/local/bin/cleanup-lvm-snapshot.sh
umount /mnt/lvm-snapshot
lvremove -f /dev/vg0/var_snap
exit 0
Testing Configuration
Before running production backups, always test your configuration:
Syntax Verification
# Test configuration syntax
sudo rsnapshot configtest
# Expected output:
# Syntax OK
Common syntax errors:
ERROR: /etc/rsnapshot.conf, line X: Interval requires a tab
ERROR: /etc/rsnapshot.conf, line X: Backup requires a tab
ERROR: snapshot_root must be defined
Fix: Ensure TABs (not spaces) separate parameters from values.
Dry Run Testing
Execute dry run to see what would happen without making changes:
# Test hourly backup
sudo rsnapshot -t hourly
# Test daily backup
sudo rsnapshot -t daily
# Verbose dry run
sudo rsnapshot -t -v hourly
Output shows what would be synced:
echo 6 > /backup/.sync/6
/usr/bin/rsync -a --delete --numeric-ids --relative --delete-excluded \
/home/ /backup/hourly.0/localhost/home/
Manual Execution Test
Run an actual backup manually before scheduling:
# Create first hourly backup
sudo rsnapshot hourly
# Verify backup created
ls -la /backup/
# Should show: hourly.0/
# Check backup contents
ls -la /backup/hourly.0/localhost/
# Create second hourly backup to test rotation
sudo rsnapshot hourly
# Verify rotation
ls -la /backup/
# Should show: hourly.0/ and hourly.1/
Automation and Scheduling
Cron-Based Scheduling
The standard approach for automated rsnapshot execution:
Edit root crontab:
sudo crontab -e
Recommended schedule:
# rsnapshot hourly at 30 minutes past the hour
30 */1 * * * /usr/bin/rsnapshot hourly
# rsnapshot daily at 3:30 AM
30 3 * * * /usr/bin/rsnapshot daily
# rsnapshot weekly on Sunday at 3:00 AM
0 3 * * 0 /usr/bin/rsnapshot weekly
# rsnapshot monthly on 1st at 2:30 AM
30 2 1 * * /usr/bin/rsnapshot monthly
Critical scheduling rules:
- Hourly must run more frequently than daily
- Daily must run less frequently than hourly
- Intervals must be called in order of frequency
- Ensure sufficient time between runs for completion
Alternative with logging:
# Hourly with log output
30 */1 * * * /usr/bin/rsnapshot hourly >> /var/log/rsnapshot-cron.log 2>&1
# Daily with email on error
30 3 * * * /usr/bin/rsnapshot daily || echo "Daily backup failed" | mail -s "Rsnapshot Alert" [email protected]
Systemd Timer Configuration
Modern alternative to cron with better logging and dependency management:
Create service file (/etc/systemd/system/rsnapshot-hourly.service):
[Unit]
Description=Rsnapshot Hourly Backup
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/bin/rsnapshot hourly
Nice=19
IOSchedulingClass=2
IOSchedulingPriority=7
[Install]
WantedBy=multi-user.target
Create timer file (/etc/systemd/system/rsnapshot-hourly.timer):
[Unit]
Description=Rsnapshot Hourly Backup Timer
Requires=rsnapshot-hourly.service
[Timer]
OnCalendar=hourly
OnCalendar=*:30:00
Persistent=true
RandomizedDelaySec=5min
[Install]
WantedBy=timers.target
Create daily service and timer:
/etc/systemd/system/rsnapshot-daily.service:
[Unit]
Description=Rsnapshot Daily Backup
After=network-online.target rsnapshot-hourly.service
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/bin/rsnapshot daily
Nice=19
IOSchedulingClass=2
IOSchedulingPriority=7
/etc/systemd/system/rsnapshot-daily.timer:
[Unit]
Description=Rsnapshot Daily Backup Timer
Requires=rsnapshot-daily.service
[Timer]
OnCalendar=daily
OnCalendar=*-*-* 03:30:00
Persistent=true
[Install]
WantedBy=timers.target
Enable and start timers:
# Reload systemd
sudo systemctl daemon-reload
# Enable and start timers
sudo systemctl enable --now rsnapshot-hourly.timer
sudo systemctl enable --now rsnapshot-daily.timer
sudo systemctl enable --now rsnapshot-weekly.timer
sudo systemctl enable --now rsnapshot-monthly.timer
# Check timer status
sudo systemctl list-timers rsnapshot-*
# View logs
sudo journalctl -u rsnapshot-hourly.service
sudo journalctl -u rsnapshot-daily.service
Monitoring and Verification
Log File Analysis
Monitor rsnapshot operations through log files:
# View rsnapshot log
sudo tail -f /var/log/rsnapshot.log
# Check for errors
sudo grep -i error /var/log/rsnapshot.log
# View successful completions
sudo grep "completed successfully" /var/log/rsnapshot.log
Example log output:
[11/Jan/2026:03:30:01] /usr/bin/rsnapshot daily: started
[11/Jan/2026:03:30:01] echo 7 > /backup/.sync/7
[11/Jan/2026:03:30:02] /usr/bin/rsync -a --delete --numeric-ids --relative \
--delete-excluded /home/ /backup/daily.0/localhost/home/
[11/Jan/2026:03:35:42] /usr/bin/rsnapshot daily: completed successfully
Backup Verification Script
Create automated verification to ensure backups completed successfully:
#!/bin/bash
# /usr/local/bin/verify-rsnapshot.sh
SNAPSHOT_ROOT="/backup"
MAX_AGE_HOURS=26
ADMIN_EMAIL="[email protected]"
# Function to check snapshot age
check_snapshot_age() {
local snapshot_dir="$1"
local snapshot_name="$2"
if [ ! -d "$snapshot_dir" ]; then
echo "ERROR: $snapshot_name snapshot not found"
return 1
fi
local snapshot_time=$(stat -c %Y "$snapshot_dir")
local current_time=$(date +%s)
local age_hours=$(( (current_time - snapshot_time) / 3600 ))
if [ $age_hours -gt $MAX_AGE_HOURS ]; then
echo "WARNING: $snapshot_name is $age_hours hours old (>$MAX_AGE_HOURS)"
return 1
else
echo "OK: $snapshot_name is $age_hours hours old"
return 0
fi
}
# Check daily snapshot
check_snapshot_age "$SNAPSHOT_ROOT/daily.0" "daily.0"
DAILY_STATUS=$?
# Check hourly snapshot
check_snapshot_age "$SNAPSHOT_ROOT/hourly.0" "hourly.0"
HOURLY_STATUS=$?
# Report results
if [ $DAILY_STATUS -ne 0 ] || [ $HOURLY_STATUS -ne 0 ]; then
echo "Backup verification FAILED" | \
mail -s "Rsnapshot Verification Alert - $(hostname)" "$ADMIN_EMAIL"
exit 1
else
echo "All snapshots verified successfully"
exit 0
fi
Schedule verification:
# Run verification hourly at 45 minutes past
45 * * * * /usr/local/bin/verify-rsnapshot.sh
Disk Space Monitoring
Monitor backup storage to prevent space exhaustion:
#!/bin/bash
# /usr/local/bin/monitor-backup-space.sh
SNAPSHOT_ROOT="/backup"
WARNING_THRESHOLD=80
CRITICAL_THRESHOLD=90
ADMIN_EMAIL="[email protected]"
# Get disk usage percentage
USAGE=$(df "$SNAPSHOT_ROOT" | awk 'NR==2 {print $5}' | sed 's/%//')
if [ $USAGE -ge $CRITICAL_THRESHOLD ]; then
echo "CRITICAL: Backup disk usage at ${USAGE}%" | \
mail -s "CRITICAL: Backup Disk Space - $(hostname)" "$ADMIN_EMAIL"
exit 2
elif [ $USAGE -ge $WARNING_THRESHOLD ]; then
echo "WARNING: Backup disk usage at ${USAGE}%" | \
mail -s "WARNING: Backup Disk Space - $(hostname)" "$ADMIN_EMAIL"
exit 1
else
echo "OK: Backup disk usage at ${USAGE}%"
exit 0
fi
Real-World Implementation Scenarios
Scenario 1: Small Business Server Backup
Requirements:
- Single physical server
- Web server, database, files
- 30-day retention
- Nightly backups with weekly and monthly archives
Configuration (/etc/rsnapshot.conf):
config_version 1.2
snapshot_root /backup/
cmd_cp /usr/bin/cp
cmd_rm /usr/bin/rm
cmd_rsync /usr/bin/rsync
cmd_ssh /usr/bin/ssh
verbose 2
loglevel 3
logfile /var/log/rsnapshot.log
lockfile /var/run/rsnapshot.pid
retain daily 30
retain weekly 12
retain monthly 12
rsync_short_args -a
rsync_long_args --delete --numeric-ids --relative --delete-excluded
# Pre-backup database dumps
backup_script /usr/local/bin/dump-databases.sh db-dumps/
# System backups
backup /etc/ localhost/
backup /home/ localhost/
backup /var/www/ localhost/
backup /opt/ localhost/
backup /root/ localhost/
# Database dumps
backup /var/backups/db-dumps/ localhost/
# Excludes
exclude *.tmp
exclude .cache/
exclude lost+found/
Cron schedule:
30 2 * * * /usr/bin/rsnapshot daily
0 2 * * 0 /usr/bin/rsnapshot weekly
30 1 1 * * /usr/bin/rsnapshot monthly
Scenario 2: Multi-Server Environment
Requirements:
- Central backup server
- 5 application servers
- 2 database servers
- Different retention for different systems
Configuration (/etc/rsnapshot.conf):
config_version 1.2
snapshot_root /backup/
cmd_cp /usr/bin/cp
cmd_rm /usr/bin/rm
cmd_rsync /usr/bin/rsync
cmd_ssh /usr/bin/ssh
verbose 2
loglevel 3
logfile /var/log/rsnapshot.log
ssh_args -i /root/.ssh/rsnapshot_key -p 22
retain hourly 24
retain daily 7
retain weekly 4
retain monthly 12
rsync_short_args -a
rsync_long_args --delete --numeric-ids --relative --delete-excluded
# Web servers
backup root@web1:/var/www/ web1/
backup root@web2:/var/www/ web2/
backup root@web3:/var/www/ web3/
# Application servers
backup root@app1:/opt/application/ app1/
backup root@app2:/opt/application/ app2/
# Database servers (using pre-dump scripts on remote)
backup root@db1:/var/backups/dumps/ db1/
backup root@db2:/var/backups/dumps/ db2/
# Configuration backups from all servers
backup root@web1:/etc/ web1-config/
backup root@web2:/etc/ web2-config/
backup root@app1:/etc/ app1-config/
backup root@db1:/etc/ db1-config/
Parallel execution script (/usr/local/bin/parallel-rsnapshot.sh):
#!/bin/bash
# Run rsnapshot backups in parallel for faster completion
INTERVAL="$1"
if [ -z "$INTERVAL" ]; then
echo "Usage: $0 {hourly|daily|weekly|monthly}"
exit 1
fi
# Split config into per-server configs
# (Assumes you've created separate configs for each server)
/usr/bin/rsnapshot -c /etc/rsnapshot.d/web-servers.conf "$INTERVAL" &
/usr/bin/rsnapshot -c /etc/rsnapshot.d/app-servers.conf "$INTERVAL" &
/usr/bin/rsnapshot -c /etc/rsnapshot.d/db-servers.conf "$INTERVAL" &
# Wait for all to complete
wait
echo "All $INTERVAL backups completed"
Scenario 3: Development Environment with Rapid Changes
Requirements:
- Frequent backups during work hours
- Code repositories
- Development databases
- Lower long-term retention needs
Configuration:
config_version 1.2
snapshot_root /backup/dev/
retain hourly 12
retain daily 7
retain weekly 4
rsync_short_args -a
rsync_long_args --delete --numeric-ids --relative --delete-excluded
# Source code
backup /home/developers/ localhost/
# Git repositories
backup /var/git/ localhost/
# Development databases
backup /var/lib/postgresql/ localhost/
# Exclude build artifacts
exclude node_modules/
exclude vendor/
exclude .git/objects/
exclude *.o
exclude *.pyc
exclude __pycache__/
Hourly schedule during work hours only:
# Run hourly from 9 AM to 6 PM, Monday-Friday
0 9-18 * * 1-5 /usr/bin/rsnapshot hourly
Restoration Procedures
Browsing Backups
One of rsnapshot's greatest advantages is simple backup browsing:
# List available snapshots
ls -la /backup/
# Browse specific snapshot
ls -la /backup/daily.0/localhost/home/
# Navigate as normal filesystem
cd /backup/weekly.2/localhost/var/www/
ls -la
# Search for specific files
find /backup/daily.*/localhost/home/user/ -name "document.txt"
File-Level Restoration
Restore individual files or directories:
# Restore single file
cp /backup/daily.0/localhost/home/user/document.txt \
/home/user/document.txt
# Restore directory
cp -a /backup/daily.0/localhost/var/www/site.com/ \
/var/www/site.com/
# Restore with rsync (preserves attributes)
rsync -av /backup/daily.0/localhost/home/user/ \
/home/user/
Full System Restoration
Restore complete system after disaster:
# Boot from live USB/rescue system
# Mount target filesystem
mount /dev/sda1 /mnt/target
# Restore from latest snapshot
rsync -av \
/backup/daily.0/localhost/ \
/mnt/target/
# Restore bootloader
grub-install --root-directory=/mnt/target /dev/sda
update-grub
# Reboot
reboot
Point-in-Time Recovery
Restore files from specific time period:
# Find when file was deleted
for snapshot in /backup/daily.*; do
if [ -f "$snapshot/localhost/home/user/lost-file.txt" ]; then
echo "File exists in: $snapshot"
stat "$snapshot/localhost/home/user/lost-file.txt"
fi
done
# Restore from identified snapshot
cp /backup/daily.3/localhost/home/user/lost-file.txt \
/home/user/lost-file.txt
Troubleshooting Common Issues
Stale Lock File
Symptom: rsnapshot: ERROR: lockfile exists
Cause: Previous rsnapshot process didn't complete cleanly
Solution:
# Check if rsnapshot is actually running
ps aux | grep rsnapshot
# If not running, remove stale lock
sudo rm /var/run/rsnapshot.pid
# Or configure to remove stale locks automatically
# In /etc/rsnapshot.conf:
stop_on_stale_lockfile 0
Insufficient Disk Space
Symptom: Backup fails with "No space left on device"
Solutions:
# Check available space
df -h /backup/
# Reduce retention periods
# Edit /etc/rsnapshot.conf
retain daily 5 # Reduce from 7
retain weekly 2 # Reduce from 4
# Remove oldest snapshots manually
sudo rm -rf /backup/monthly.11 /backup/monthly.10
# Identify large files consuming space
sudo du -sh /backup/*/ | sort -h
# Exclude large unnecessary files
# Add to /etc/rsnapshot.conf:
exclude *.iso
exclude *.log
exclude *.mp4
Permission Denied Errors
Symptom: rsync: send_files failed to open: Permission denied
Solutions:
# Run rsnapshot as root
sudo rsnapshot daily
# For remote backups, ensure SSH key has proper permissions
chmod 600 /root/.ssh/rsnapshot_key
# Check remote user has read access
ssh -i /root/.ssh/rsnapshot_key root@remote "ls -la /var/www/"
# Use sudo on remote if needed (configure in SSH)
# Or backup as root user
Hard Link Across Filesystems Error
Symptom: rsync: failed to hard link: Invalid cross-device link
Cause: Snapshot root and temp directory on different filesystems
Solution:
# Ensure snapshot_root is on a single filesystem
# Check current setup
df /backup/
# Reconfigure if needed
# In /etc/rsnapshot.conf:
snapshot_root /backup/rsnapshot/
# Ensure entire path on one filesystem
Slow Backup Performance
Symptoms: Backups exceed maintenance window
Optimizations:
# Exclude unnecessary data
exclude *.log
exclude cache/
exclude tmp/
# Use one_fs to avoid crossing filesystems
# In /etc/rsnapshot.conf:
one_fs 1
# Limit rsync bandwidth if network is bottleneck
rsync_long_args --delete --numeric-ids --relative --bwlimit=50000
# Use ionice for I/O priority
# Wrapper script:
ionice -c3 /usr/bin/rsnapshot daily
Performance Optimization
Optimizing for Large Datasets
# Use parallel rsync
rsync_long_args --delete --numeric-ids --relative --delete-excluded \
--inplace --no-whole-file
# Disable compression for local backups (saves CPU)
# Remove -z from rsync_short_args
rsync_short_args -a
Network Optimization for Remote Backups
# Enable compression for remote transfers
ssh_args -i /root/.ssh/rsnapshot_key -C
# Use faster cipher
ssh_args -i /root/.ssh/rsnapshot_key -c [email protected]
# Limit bandwidth during business hours
# Create separate config for day/night
rsync_long_args --bwlimit=5000 # 5 MB/s during day
Security Considerations
Access Control
# Restrict backup directory permissions
sudo chmod 700 /backup/
sudo chown root:root /backup/
# Protect configuration file
sudo chmod 600 /etc/rsnapshot.conf
sudo chown root:root /etc/rsnapshot.conf
# Secure SSH keys
sudo chmod 600 /root/.ssh/rsnapshot_key
sudo chown root:root /root/.ssh/rsnapshot_key
Encryption
For sensitive data, implement encryption:
# Encrypt backups with encfs
sudo apt install encfs
# Create encrypted backup location
mkdir /backup-encrypted
encfs /backup /backup-encrypted
# Configure rsnapshot to use encrypted mount
snapshot_root /backup-encrypted/
Automate encryption with systemd:
# /etc/systemd/system/backup-encryption.service
[Unit]
Description=Mount Encrypted Backup Volume
Before=rsnapshot-daily.service
[Service]
Type=oneshot
ExecStart=/bin/echo "password" | /usr/bin/encfs -S /backup /backup-encrypted
RemainAfterExit=yes
ExecStop=/bin/fusermount -u /backup-encrypted
[Install]
WantedBy=multi-user.target
Conclusion
Rsnapshot provides an elegant, efficient solution for incremental backups that balances simplicity with powerful functionality. By leveraging hard links and rsync's delta-transfer algorithm, rsnapshot enables space-efficient retention of multiple backup snapshots while maintaining simple, browsable filesystem access for restoration.
Key takeaways from this comprehensive guide:
-
Configure carefully: Use TABs in configuration, test thoroughly with dry runs before production deployment.
-
Plan retention wisely: Balance business requirements against storage capacity when defining retention intervals.
-
Automate reliably: Use cron or systemd timers with proper scheduling to ensure consistent backup execution.
-
Monitor actively: Implement verification scripts and monitoring to detect backup failures promptly.
-
Test restoration: Regularly practice restoration procedures to ensure backups are viable and teams understand processes.
-
Optimize for scale: Apply performance optimizations for large datasets or remote backups.
-
Secure properly: Implement access controls, secure SSH keys, and consider encryption for sensitive data.
-
Integrate thoughtfully: Use pre/post scripts for application-consistent backups, especially for databases.
Whether protecting a single server or implementing enterprise-wide backup infrastructure, rsnapshot offers a proven, reliable foundation. Combined with proper planning, automation, monitoring, and regular testing, rsnapshot enables robust disaster recovery capabilities that align with the 3-2-1 backup rule and protect your organization's critical data assets.
Start with basic configurations, validate thoroughly, and incrementally expand your implementation to meet evolving business requirements. Remember: effective backups are those that are consistently executed, regularly verified, and successfully restorable when needed.


