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.