Restic Backup Advanced Configuration
Restic is a fast, encrypted backup tool that supports multiple storage backends including S3, SFTP, Backblaze B2, and a self-hosted REST server. This guide covers advanced Restic configuration for production Linux servers — multiple repositories, retention policies, bandwidth limiting, monitoring, and REST server setup for a complete backup infrastructure.
Prerequisites
- Ubuntu/Debian or CentOS/Rocky Linux
- At least one backup destination (S3 bucket, SFTP server, or local disk)
- Root or sudo access on the system being backed up
Installing Restic
# Ubuntu/Debian
sudo apt-get install -y restic
# CentOS/Rocky
sudo dnf install -y restic
# Or install the latest binary directly
RESTIC_VERSION=$(curl -s https://api.github.com/repos/restic/restic/releases/latest | grep -o '"tag_name": *"[^"]*"' | cut -d'"' -f4)
curl -sL "https://github.com/restic/restic/releases/download/${RESTIC_VERSION}/restic_${RESTIC_VERSION#v}_linux_amd64.bz2" | \
bunzip2 > /usr/local/bin/restic
chmod +x /usr/local/bin/restic
# Verify installation
restic version
# Enable self-update capability (installed from GitHub)
restic self-update
Repository Initialization and Backends
Local Repository
# Create a password file (more secure than env var for scripts)
echo "your-strong-password" > /root/.restic-password
chmod 600 /root/.restic-password
# Initialize local repository
restic init --repo /backup/restic-repo --password-file /root/.restic-password
# Test backup
restic backup /etc /home --repo /backup/restic-repo --password-file /root/.restic-password
S3 Backend
# Set credentials (or use IAM role on cloud instances)
export AWS_ACCESS_KEY_ID=your-key
export AWS_SECRET_ACCESS_KEY=your-secret
# Initialize S3 repository
restic init \
--repo s3:s3.amazonaws.com/your-bucket/server-backups \
--password-file /root/.restic-password
# For MinIO or other S3-compatible storage
export AWS_ACCESS_KEY_ID=minioadmin
export AWS_SECRET_ACCESS_KEY=minioadmin
restic init \
--repo s3:http://minio.yourdomain.com:9000/backups \
--password-file /root/.restic-password
SFTP Backend
# Ensure SSH key authentication is configured first
# Initialize SFTP repository
restic init \
--repo sftp:[email protected]:/srv/backups/server01 \
--password-file /root/.restic-password
# Custom SSH options
restic init \
--repo "sftp://[email protected]:2222//srv/backups/server01" \
-o sftp.command="ssh -p 2222 -i /root/.ssh/backup_key [email protected] -s sftp" \
--password-file /root/.restic-password
Backblaze B2
export B2_ACCOUNT_ID=your-b2-account-id
export B2_ACCOUNT_KEY=your-b2-application-key
restic init \
--repo b2:your-bucket-name:server-backups \
--password-file /root/.restic-password
Retention Policies and Pruning
Restic's forget and prune commands implement retention policies:
# Keep the last 7 daily, 4 weekly, and 12 monthly snapshots
restic forget \
--repo s3:s3.amazonaws.com/your-bucket/server-backups \
--password-file /root/.restic-password \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 12 \
--keep-yearly 3 \
--prune \
--dry-run # Remove this flag to actually delete
# Prune unreferenced data after forget (without --prune flag above)
restic prune \
--repo s3:s3.amazonaws.com/your-bucket/server-backups \
--password-file /root/.restic-password
# Max-repack-size to limit bandwidth during prune
restic prune \
--repo s3:s3.amazonaws.com/your-bucket/server-backups \
--password-file /root/.restic-password \
--max-repack-size 2G
Multiple Repository Strategy
For resilient backups, write to multiple backends simultaneously:
# Create a backup script that mirrors to multiple repositories
cat > /usr/local/bin/backup-all.sh << 'SCRIPT'
#!/bin/bash
set -euo pipefail
PASSWORD_FILE="/root/.restic-password"
BACKUP_DIRS="/etc /home /var/www /opt"
EXCLUDE_FILE="/etc/restic/excludes.txt"
# Common backup options
RESTIC_OPTS="--password-file $PASSWORD_FILE --exclude-file $EXCLUDE_FILE"
# Backup to S3
export AWS_ACCESS_KEY_ID="your-s3-key"
export AWS_SECRET_ACCESS_KEY="your-s3-secret"
echo "[$(date)] Backing up to S3..."
restic backup $BACKUP_DIRS \
--repo s3:s3.amazonaws.com/your-bucket/server01 \
$RESTIC_OPTS \
--tag automated \
--tag $(hostname)
# Forget old snapshots on S3
restic forget \
--repo s3:s3.amazonaws.com/your-bucket/server01 \
$RESTIC_OPTS \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 6 \
--prune
# Backup to B2 (second copy)
export B2_ACCOUNT_ID="your-b2-id"
export B2_ACCOUNT_KEY="your-b2-key"
echo "[$(date)] Backing up to B2..."
restic backup $BACKUP_DIRS \
--repo b2:your-b2-bucket:server01 \
$RESTIC_OPTS \
--tag automated
# Forget old snapshots on B2
restic forget \
--repo b2:your-b2-bucket:server01 \
$RESTIC_OPTS \
--keep-daily 14 \
--keep-monthly 12 \
--prune
echo "[$(date)] Backup complete"
SCRIPT
chmod +x /usr/local/bin/backup-all.sh
Create an excludes file:
mkdir -p /etc/restic
cat > /etc/restic/excludes.txt << 'EOF'
/proc
/sys
/dev
/run
/tmp
/var/cache
/var/tmp
/home/*/.cache
/home/*/.local/share/Trash
*.log
*.pid
*.sock
node_modules
.git
__pycache__
*.pyc
EOF
Bandwidth Limiting
# Limit upload bandwidth to 50 MB/s
restic backup /var/www \
--repo s3:s3.amazonaws.com/your-bucket/server01 \
--password-file /root/.restic-password \
--limit-upload 51200 # In KiB/s (50 * 1024)
# Limit both upload and download (for restore)
restic restore latest \
--repo s3:s3.amazonaws.com/your-bucket/server01 \
--password-file /root/.restic-password \
--limit-upload 51200 \
--limit-download 102400 \
--target /restore/
# Set limits in environment variables for all operations
export RESTIC_LIMIT_UPLOAD=51200
export RESTIC_LIMIT_DOWNLOAD=102400
Monitoring Backups
Systemd Timer Setup
# Create systemd service
sudo tee /etc/systemd/system/restic-backup.service << 'EOF'
[Unit]
Description=Restic Backup
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup-all.sh
StandardOutput=journal
StandardError=journal
EOF
# Create systemd timer
sudo tee /etc/systemd/system/restic-backup.timer << 'EOF'
[Unit]
Description=Run Restic backup daily
[Timer]
OnCalendar=daily
RandomizedDelaySec=1h
Persistent=true
[Install]
WantedBy=timers.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now restic-backup.timer
# Check timer status
systemctl status restic-backup.timer
journalctl -u restic-backup --since today
Send Alerts on Failure
# Update backup script to send alerts
cat >> /usr/local/bin/backup-all.sh << 'ALERT'
# Send success notification
curl -s -X POST "https://ntfy.yourdomain.com/backups" \
-H "Title: Backup Complete" \
-d "$(hostname): backup completed at $(date)"
ALERT
# Add failure handler at top of script
trap 'curl -s -X POST "https://ntfy.yourdomain.com/backups" \
-H "Title: BACKUP FAILED" \
-H "Priority: urgent" \
-d "$(hostname): backup FAILED at $(date) - check logs"' ERR
Verify Backups
# List snapshots
restic snapshots \
--repo s3:s3.amazonaws.com/your-bucket/server01 \
--password-file /root/.restic-password
# Check repository integrity
restic check \
--repo s3:s3.amazonaws.com/your-bucket/server01 \
--password-file /root/.restic-password
# Read all data (thorough check, takes longer)
restic check --read-data \
--repo s3:s3.amazonaws.com/your-bucket/server01 \
--password-file /root/.restic-password
# Check only a percentage of data (faster for large repos)
restic check --read-data-subset=10% \
--repo s3:s3.amazonaws.com/your-bucket/server01 \
--password-file /root/.restic-password
REST Server Setup
Run a self-hosted Restic REST server as a backup target:
# Download restic-server (rest-server)
wget https://github.com/restic/rest-server/releases/latest/download/rest-server_linux_amd64.tar.gz
tar -xzf rest-server_linux_amd64.tar.gz -C /usr/local/bin rest-server
# Create data directory and user
sudo mkdir -p /srv/restic-server
sudo useradd --system --home /srv/restic-server restic-server
# Create htpasswd file for authentication
sudo apt-get install -y apache2-utils
sudo htpasswd -c /srv/restic-server/.htpasswd backupuser
# Create systemd service
sudo tee /etc/systemd/system/restic-rest-server.service << 'EOF'
[Unit]
Description=Restic REST Server
After=network.target
[Service]
Type=simple
User=restic-server
ExecStart=/usr/local/bin/rest-server \
--path /srv/restic-server \
--listen :8000 \
--htpasswd-file /srv/restic-server/.htpasswd \
--tls \
--tls-cert /etc/letsencrypt/live/backup.yourdomain.com/fullchain.pem \
--tls-key /etc/letsencrypt/live/backup.yourdomain.com/privkey.pem
Restart=always
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable --now restic-rest-server
# Initialize a repository on the REST server from client
restic init \
--repo rest:https://backupuser:[email protected]:8000/server01 \
--password-file /root/.restic-password
Troubleshooting
"no data was written" or connection timeout:
# Test network connectivity to backend
curl -I https://s3.amazonaws.com
curl -I sftp://backup-server:22
# Test credentials
restic snapshots --repo <repo> --password-file /root/.restic-password --verbose
Repository locked:
# Remove stale lock (only if no backup is actually running)
restic unlock --repo <repo> --password-file /root/.restic-password
Prune is very slow:
# Use --max-repack-size to limit data rewritten per run
restic prune --max-repack-size 1G --repo <repo> --password-file /root/.restic-password
# Schedule prune separately from backup (weekly is often enough)
Out of disk space during backup:
# Check space before backup
df -h /backup
# Restic requires temporary space equal to ~1% of backup size
# Add --no-cache flag to skip cache files
restic backup /data --no-cache --repo <repo> --password-file /root/.restic-password
Conclusion
Restic's combination of deduplication, encryption, and multi-backend support makes it one of the most capable backup solutions for production Linux servers. Running backups to multiple repositories simultaneously with automated retention policies and systemd timers creates a robust backup infrastructure. Integrate monitoring with ntfy or alerting tools to ensure you are notified immediately if a backup fails.


