Restic: Modern Backup with REST Server
Fast, secure, efficient backups with Restic. Setup REST server and automate your backup strategy.
Restic is a modern backup program that is fast, secure, and efficient. It uses deduplication, encryption, and supports multiple storage backends. This guide will show you how to set up Restic with a REST server backend for a complete homelab backup solution.
Why Restic?
Restic offers several advantages for homelab backups:
- Encryption by default: All data is encrypted before leaving your system
- Deduplication: Saves storage space by only storing unique data blocks
- Multiple backends: Supports local, SFTP, REST server, S3, B2, Azure, and more
- Incremental backups: Only changed data is transferred
- Verification: Built-in integrity checking and verification
- Cross-platform: Works on Linux, macOS, Windows, and BSD
- Fast and efficient: Written in Go for excellent performance
- Simple restore: Easy to restore individual files or entire snapshots
Architecture Overview
In this guide, we’ll set up:
- Restic REST Server: A lightweight HTTP server for storing Restic repositories
- Restic Client: The backup client running on servers you want to back up
- Automated backups: Systemd timers or cron jobs for scheduled backups
- Monitoring: Scripts to verify backup success and send notifications
Part 1: Setting Up REST Server
The REST server provides an HTTP backend for Restic repositories. It’s lightweight, secure, and perfect for homelabs.
Option A: Docker Installation (Recommended)
Create a directory structure for the REST server:
mkdir -p /opt/restic-server/{data,config}
cd /opt/restic-server Create a docker-compose.yml:
version: '3.8'
services:
restic-rest-server:
image: restic/rest-server:latest
container_name: restic-rest-server
restart: unless-stopped
ports:
- "8000:8000"
volumes:
- ./data:/data
- ./config:/config
environment:
- OPTIONS=--append-only --private-repos
command:
- --path
- /data
- --prometheus
- --listen
- :8000
networks:
- restic-net
networks:
restic-net:
driver: bridge Start the server:
docker compose up -d Option B: Native Installation
Install REST server on Debian/Ubuntu:
# Download latest release
RESTIC_REST_VERSION="0.12.1"
wget https://github.com/restic/rest-server/releases/download/v${RESTIC_REST_VERSION}/rest-server_${RESTIC_REST_VERSION}_linux_amd64.tar.gz
# Extract and install
tar -xzf rest-server_${RESTIC_REST_VERSION}_linux_amd64.tar.gz
sudo mv rest-server /usr/local/bin/
sudo chmod +x /usr/local/bin/rest-server Create a systemd service:
sudo mkdir -p /var/lib/restic-server
sudo useradd -r -s /bin/false -d /var/lib/restic-server restic
sudo chown restic:restic /var/lib/restic-server Create /etc/systemd/system/restic-rest-server.service:
[Unit]
Description=Restic REST Server
After=network.target
[Service]
Type=simple
User=restic
Group=restic
ExecStart=/usr/local/bin/rest-server
--path /var/lib/restic-server --listen :8000 --append-only --private-repos --prometheus
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target Enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable --now restic-rest-server
sudo systemctl status restic-rest-server Securing the REST Server
Create authentication credentials:
# For Docker setup
cd /opt/restic-server/config
# For native setup
cd /var/lib/restic-server
# Create .htpasswd file (requires apache2-utils)
sudo apt install apache2-utils -y
htpasswd -B -c .htpasswd backup-user Update the Docker compose file to use authentication:
volumes:
- ./data:/data
- ./config/.htpasswd:/data/.htpasswd:ro
environment:
- OPTIONS=--append-only --private-repos --htpasswd-file=/data/.htpasswd For production use, put the REST server behind a reverse proxy with TLS:
Nginx configuration example:
server {
listen 443 ssl http2;
server_name backup.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/backup.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/backup.yourdomain.com/privkey.pem;
location / {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Important for large backups
client_max_body_size 0;
proxy_request_buffering off;
}
} Part 2: Installing Restic Client
Install Restic on the systems you want to back up.
Installation Methods
Debian/Ubuntu:
sudo apt update
sudo apt install restic -y From Official Binaries (Latest Version):
RESTIC_VERSION="0.16.3"
wget https://github.com/restic/restic/releases/download/v${RESTIC_VERSION}/restic_${RESTIC_VERSION}_linux_amd64.bz2
bzip2 -d restic_${RESTIC_VERSION}_linux_amd64.bz2
sudo mv restic_${RESTIC_VERSION}_linux_amd64 /usr/local/bin/restic
sudo chmod +x /usr/local/bin/restic Verify installation:
restic version Part 3: Initializing a Restic Repository
Create a repository on the REST server:
# Set environment variables
export RESTIC_REPOSITORY=rest:http://backup-user:YOUR-PASSWORD@YOUR-SERVER-IP:8000/hostname
export RESTIC_PASSWORD="your-encryption-password"
# Initialize the repository
restic init For better security, store credentials in a file:
# Create password file
echo "your-encryption-password" > ~/.restic-password
chmod 600 ~/.restic-password
# Create repository configuration
cat > ~/.restic-env << 'EOF'
export RESTIC_REPOSITORY="rest:http://backup-user:YOUR-PASSWORD@YOUR-SERVER-IP:8000/hostname"
export RESTIC_PASSWORD_FILE="$HOME/.restic-password"
EOF
chmod 600 ~/.restic-env Load credentials:
source ~/.restic-env
restic init Part 4: Creating Backups
Basic Backup Commands
Backup a directory:
restic backup /home/user/documents Backup multiple directories:
restic backup /home /etc /var/lib/docker/volumes Backup with exclusions:
restic backup /home --exclude="*.tmp" --exclude="/home/*/.cache" --exclude="/home/*/Downloads" --exclude-file=/root/.restic-exclude Create an exclude file /root/.restic-exclude:
*.log
*.tmp
*~
.DS_Store
.cache/
node_modules/
__pycache__/
*.pyc
.git/ Advanced Backup Options
Backup with tags:
restic backup /var/lib/docker/volumes --tag docker --tag production Dry run (test without uploading):
restic backup /home --dry-run Verbose output:
restic backup /home --verbose Limit bandwidth:
restic backup /home --limit-upload 10240 # 10 MB/s Part 5: Managing Snapshots
Listing Snapshots
View all snapshots:
restic snapshots View snapshots for specific path:
restic snapshots --path /home View snapshots with specific tag:
restic snapshots --tag docker Snapshot Information
Get detailed snapshot info:
restic snapshots --json | jq '.' Show files in a snapshot:
restic ls SNAPSHOT-ID Compare two snapshots:
restic diff SNAPSHOT-ID1 SNAPSHOT-ID2 Part 6: Restoring Data
Restore Entire Snapshot
Restore to original location:
restic restore SNAPSHOT-ID --target / Restore to different location:
restic restore SNAPSHOT-ID --target /tmp/restore Restore latest snapshot:
restic restore latest --target /tmp/restore Restore Specific Files
Restore specific path from latest snapshot:
restic restore latest --target /tmp/restore --path /home/user/important.txt Restore with include pattern:
restic restore latest --target /tmp/restore --include "*.conf" Mount Repository for Browse and Restore
Mount the repository as a filesystem:
mkdir /mnt/restic
restic mount /mnt/restic Now you can browse snapshots:
ls /mnt/restic/snapshots/
cd /mnt/restic/snapshots/latest/home/user/
cp important-file.txt /home/user/ Unmount when done:
umount /mnt/restic Part 7: Retention Policies and Pruning
Forget Old Snapshots
Restic uses a forget command to mark snapshots for deletion:
# Keep last 7 daily, 4 weekly, 12 monthly snapshots
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --keep-yearly 3 More retention options:
restic forget --keep-last 5 --keep-hourly 24 --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --keep-yearly 3 --keep-tag important Prune to Reclaim Space
Forgetting snapshots doesn’t free space immediately. Run prune:
restic prune Combined forget and prune:
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --prune Part 8: Repository Maintenance
Check Repository Integrity
Basic check:
restic check Read all data (thorough check):
restic check --read-data Check subset of data (faster):
restic check --read-data-subset=10% Rebuild Index
If the repository index is corrupted:
restic rebuild-index Repository Statistics
View repository stats:
restic stats Stats in different modes:
restic stats --mode raw-data
restic stats --mode restore-size
restic stats --mode files-by-contents Part 9: Automation with Systemd
Create a systemd service and timer for automated backups.
Create Backup Script
Create /usr/local/bin/restic-backup.sh:
#!/bin/bash
# Exit on error
set -e
# Load environment
source /root/.restic-env
# Set log file
LOGFILE="/var/log/restic-backup.log"
# Backup function
backup() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - Starting backup" >> "$LOGFILE"
restic backup /home /etc /var/lib/docker/volumes /opt --exclude-file=/root/.restic-exclude --tag automated >> "$LOGFILE" 2>&1
echo "$(date '+%Y-%m-%d %H:%M:%S') - Backup completed" >> "$LOGFILE"
}
# Forget old snapshots
forget() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - Forgetting old snapshots" >> "$LOGFILE"
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --keep-yearly 3 --prune >> "$LOGFILE" 2>&1
echo "$(date '+%Y-%m-%d %H:%M:%S') - Forget completed" >> "$LOGFILE"
}
# Check repository (weekly)
check() {
if [ "$(date +%u)" -eq 7 ]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') - Checking repository" >> "$LOGFILE"
restic check >> "$LOGFILE" 2>&1
echo "$(date '+%Y-%m-%d %H:%M:%S') - Check completed" >> "$LOGFILE"
fi
}
# Run backup
backup
# Run forget on Sundays
if [ "$(date +%u)" -eq 7 ]; then
forget
fi
# Run check
check
echo "$(date '+%Y-%m-%d %H:%M:%S') - All tasks completed" >> "$LOGFILE" Make it executable:
sudo chmod +x /usr/local/bin/restic-backup.sh Create Systemd Service
Create /etc/systemd/system/restic-backup.service:
[Unit]
Description=Restic Backup
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/restic-backup.sh
User=root
Group=root
Nice=19
IOSchedulingClass=idle Create Systemd Timer
Create /etc/systemd/system/restic-backup.timer:
[Unit]
Description=Restic Backup Timer
Requires=restic-backup.service
[Timer]
OnCalendar=daily
OnCalendar=*-*-* 02:00:00
Persistent=true
RandomizedDelaySec=30min
[Install]
WantedBy=timers.target Enable and start the timer:
sudo systemctl daemon-reload
sudo systemctl enable restic-backup.timer
sudo systemctl start restic-backup.timer
sudo systemctl list-timers Test the backup manually:
sudo systemctl start restic-backup.service
journalctl -u restic-backup.service -f Part 10: Cloud Storage Integration
Backblaze B2
Restic natively supports Backblaze B2:
# Install B2 CLI (optional, for management)
sudo pip3 install b2
# Set B2 credentials
export B2_ACCOUNT_ID="your-account-id"
export B2_ACCOUNT_KEY="your-application-key"
export RESTIC_REPOSITORY="b2:bucket-name:path/to/repo"
export RESTIC_PASSWORD="your-encryption-password"
# Initialize repository
restic init Amazon S3
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
export RESTIC_REPOSITORY="s3:s3.amazonaws.com/bucket-name/path"
export RESTIC_PASSWORD="your-encryption-password"
restic init Wasabi S3-Compatible Storage
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
export RESTIC_REPOSITORY="s3:s3.us-west-1.wasabisys.com/bucket-name/path"
export RESTIC_PASSWORD="your-encryption-password"
restic init SFTP Backend
export RESTIC_REPOSITORY="sftp:user@host:/backup/path"
export RESTIC_PASSWORD="your-encryption-password"
restic init Part 11: Monitoring and Notifications
Healthchecks.io Integration
Add health check pings to your backup script:
#!/bin/bash
HEALTHCHECK_URL="https://hc-ping.com/your-uuid-here"
# Start signal
curl -fsS -m 10 --retry 5 "$HEALTHCHECK_URL/start" > /dev/null
# Your backup commands here
source /root/.restic-env
restic backup /home /etc /var/lib/docker/volumes
# Success or failure
if [ $? -eq 0 ]; then
curl -fsS -m 10 --retry 5 "$HEALTHCHECK_URL" > /dev/null
else
curl -fsS -m 10 --retry 5 "$HEALTHCHECK_URL/fail" > /dev/null
fi Email Notifications
Install mailutils:
sudo apt install mailutils -y Enhanced backup script with email:
#!/bin/bash
EMAIL="[email protected]"
HOSTNAME=$(hostname)
# Run backup
if /usr/local/bin/restic-backup.sh; then
echo "Backup completed successfully on $HOSTNAME at $(date)" | mail -s "✓ Backup Success: $HOSTNAME" "$EMAIL"
else
echo "Backup FAILED on $HOSTNAME at $(date). Check logs at /var/log/restic-backup.log" | mail -s "✗ Backup FAILED: $HOSTNAME" "$EMAIL"
fi Prometheus Metrics
The REST server provides Prometheus metrics at /metrics. Configure Prometheus to scrape:
scrape_configs:
- job_name: 'restic-rest-server'
static_configs:
- targets: ['YOUR-SERVER-IP:8000'] Part 12: Security Best Practices
Encryption
- Use strong repository passwords: Minimum 20 characters, random
- Separate encryption from REST auth: Repository password encrypts data, REST password controls access
- Store passwords securely: Use password managers, not plain text files
Access Control
- Use append-only mode: Prevents attackers from deleting backups
- Separate repositories per host: Limits blast radius of compromise
- Use htpasswd authentication: Different credentials per client
- Enable private repos mode: Prevents repository enumeration
Network Security
- Use TLS/HTTPS: Always encrypt data in transit
- Firewall REST server: Only allow connections from backup clients
- Use VPN or Tailscale: Additional network layer security
- Regular security updates: Keep Restic and REST server updated
Backup Verification
Create a verification script /usr/local/bin/restic-verify.sh:
#!/bin/bash
source /root/.restic-env
# Check repository integrity
echo "Checking repository integrity..."
restic check
# Verify latest snapshot can be restored
echo "Testing restore of latest snapshot..."
mkdir -p /tmp/restic-test
restic restore latest --target /tmp/restic-test --path /etc/hostname
if [ -f /tmp/restic-test/etc/hostname ]; then
echo "✓ Restore test successful"
rm -rf /tmp/restic-test
exit 0
else
echo "✗ Restore test failed!"
exit 1
fi Run monthly with cron:
0 3 1 * * /usr/local/bin/restic-verify.sh >> /var/log/restic-verify.log 2>&1 Part 13: Multi-Repository Strategy
For critical data, use multiple repositories with different backends:
# Local repository
export RESTIC_REPOSITORY_LOCAL="rest:http://user:pass@local-nas:8000/hostname"
# Cloud repository
export RESTIC_REPOSITORY_CLOUD="b2:backup-bucket:hostname"
# Backup to both
restic -r $RESTIC_REPOSITORY_LOCAL backup /home /etc
restic -r $RESTIC_REPOSITORY_CLOUD backup /home /etc Automated multi-repo backup script:
#!/bin/bash
REPOS=(
"rest:http://user:pass@nas:8000/hostname"
"sftp:user@offsite:/backups/hostname"
)
for repo in "${REPOS[@]}"; do
echo "Backing up to $repo"
RESTIC_REPOSITORY="$repo" RESTIC_PASSWORD_FILE=/root/.restic-password restic backup /home /etc /var/lib/docker/volumes
done Part 14: Troubleshooting
Common Issues
Lock conflicts:
# List locks
restic list locks
# Remove stale lock
restic unlock Slow backups:
# Check statistics
restic stats --mode raw-data
# Limit concurrent connections
restic backup /home --limit-upload 5120 Repository corruption:
# Check and repair
restic check --read-data
restic rebuild-index
restic prune Out of space:
# Check repository size
restic stats
# Aggressive pruning
restic forget --keep-last 3 --prune Debugging
Enable verbose output:
restic backup /home --verbose=2 Check REST server logs:
# Docker
docker logs restic-rest-server
# Native
journalctl -u restic-rest-server -f Conclusion
You now have a complete, secure backup solution using Restic and REST server. This setup provides:
- Encrypted, deduplicated backups
- Flexible retention policies
- Multiple backend support (local, cloud, SFTP)
- Automated scheduled backups
- Monitoring and notifications
- Easy restore procedures
Next Steps
- Test your restores regularly: Backups are useless if you can’t restore
- Monitor backup success: Set up alerts for failed backups
- Document your setup: Keep notes on your configuration
- Plan for disasters: Have a documented recovery procedure
- Keep multiple copies: Follow the 3-2-1 backup rule
Additional Resources
Remember: The best backup is the one you test. Schedule regular restore tests to ensure your backup strategy works when you need it most.