Fast, secure, cross-platform backup program with deduplication and support for numerous storage backends.
Table of Contents#
- Overview
- Installation
- Core Concepts
- Repository Backends
- Creating Backups
- Exclude Patterns
- Managing Snapshots
- Restoring Data
- Repository Maintenance
- Environment Variable Configuration
- Bandwidth Limiting and Rclone Integration
- Automation with Systemd
- Troubleshooting
- See Also
- Sources
1. Overview#
Restic is a backup program designed for simplicity, security, and speed. Every backup is encrypted by default using AES-256 before data leaves the source machine. Restic uses content-defined chunking for deduplication, meaning identical data is stored only once regardless of its location across snapshots.
Key features:
- Encryption by default - AES-256 in counter mode with Poly1305-AES MAC; no unencrypted mode
- Deduplication - content-defined chunking across all snapshots
- Multiple backends - local, SFTP, REST server, Amazon S3, MinIO, Backblaze B2, Azure, Google Cloud, rclone
- Cross-platform - Linux, macOS, Windows, FreeBSD
- Mountable snapshots - browse backups as FUSE filesystems
- Fast - parallel processing and efficient delta transfers
2. Installation#
# Debian/Ubuntu
sudo apt install restic
# Fedora
sudo dnf install restic
# Arch Linux
sudo pacman -S restic
# macOS
brew install restic
# Self-update (if installed via official binary)
sudo restic self-update3. Core Concepts#
Repository - the storage location for all backup data, metadata, and encryption keys. Identified by a URI or path.
Snapshot - a point-in-time backup. Each snapshot records the files, their metadata, and references to deduplicated data chunks.
Encryption - all data is encrypted with a key derived from the repository password. Without the password, data is inaccessible.
Pack files - restic groups chunks into pack files for efficient storage and transfer. Each pack file contains multiple encrypted, compressed data chunks.
4. Repository Backends#
Local Filesystem#
restic -r /path/to/repo initSFTP#
restic -r sftp:<user>@<host>:/path/to/repo initREST Server#
The rest-server provides a dedicated HTTP backend:
# On the server
rest-server --path /path/to/data --listen :8000
# On the client
restic -r rest:http://<host>:8000/<repo-name> initFor TLS:
rest-server --path /path/to/data --tls --tls-cert /path/to/cert --tls-key /path/to/key
restic -r rest:https://<host>:8000/<repo-name> initAmazon S3 / MinIO#
# Amazon S3
export AWS_ACCESS_KEY_ID=<key-id>
export AWS_SECRET_ACCESS_KEY=<secret>
restic -r s3:s3.amazonaws.com/<bucket-name> init
# MinIO (S3-compatible)
export AWS_ACCESS_KEY_ID=<key-id>
export AWS_SECRET_ACCESS_KEY=<secret>
restic -r s3:http://<minio-host>:9000/<bucket-name> initBackblaze B2#
export B2_ACCOUNT_ID=<account-id>
export B2_ACCOUNT_KEY=<account-key>
restic -r b2:<bucket-name>:<path> initRclone (Any Rclone-Supported Backend)#
# First configure an rclone remote (e.g., "myremote")
rclone config
# Use it with restic
restic -r rclone:myremote:path/to/repo initBackend Comparison#
| Backend | Speed | Cost | Complexity | Use Case |
|---|---|---|---|---|
| Local | Fastest | Hardware cost | Minimal | External drives, NAS |
| SFTP | Fast (LAN) | Existing server | Low | Home servers, VPS |
| REST Server | Fast | Existing server | Low | Dedicated backup server |
| S3/MinIO | Variable | Per-GB pricing | Medium | Cloud backup, off-site |
| B2 | Variable | Low per-GB | Medium | Budget cloud backup |
| Rclone | Variable | Depends | Medium-High | Any cloud provider |
5. Creating Backups#
Basic Backup#
restic -r /path/to/repo backup /home /etc /var/logBackup with Tags#
restic -r /path/to/repo backup --tag daily --tag server1 /dataBackup from stdin#
# Backup a database dump
mysqldump --all-databases | restic -r /path/to/repo backup --stdin --stdin-filename mysql-dump.sqlDry Run#
restic -r /path/to/repo backup --dry-run --verbose /dataVerbose Output with Statistics#
restic -r /path/to/repo backup --verbose --verbose /data6. Exclude Patterns#
Command-Line Excludes#
restic -r /path/to/repo backup /home \
--exclude="*.tmp" \
--exclude=".cache" \
--exclude="node_modules" \
--exclude="/home/*/.local/share/Trash"Exclude File#
Create an exclude file (e.g., /etc/restic/excludes.txt):
# Temporary files
*.tmp
*.swp
*~
# Caches
.cache
.thumbnails
__pycache__
# Build artifacts
node_modules
target/
build/
dist/
# System
/dev
/proc
/sys
/tmp
/run
/mnt
/media
/lost+foundUse it:
restic -r /path/to/repo backup --exclude-file=/etc/restic/excludes.txt /Exclude Patterns Explained#
| Pattern | Matches |
|---|---|
*.tmp | Any file ending in .tmp at any depth |
.cache | Any file or directory named .cache at any depth |
/home/*/.cache | .cache only directly under each home directory |
node_modules/ | Directories named node_modules (trailing slash) |
Include Only Specific Paths#
restic -r /path/to/repo backup --files-from /etc/restic/includes.txt7. Managing Snapshots#
List Snapshots#
# All snapshots
restic -r /path/to/repo snapshots
# Filter by host
restic -r /path/to/repo snapshots --host <hostname>
# Filter by tag
restic -r /path/to/repo snapshots --tag daily
# Filter by path
restic -r /path/to/repo snapshots --path /homeCompare Snapshots#
restic -r /path/to/repo diff <snapshot-id-1> <snapshot-id-2>Forget Snapshots (Retention)#
restic -r /path/to/repo forget \
--keep-last 5 \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 12 \
--keep-yearly 3 \
--pruneWithout --prune, forget only marks snapshots for deletion. The --prune flag actually reclaims disk space.
Group Forget by Host and Path#
restic -r /path/to/repo forget \
--group-by host,paths \
--keep-daily 7 \
--keep-weekly 4 \
--pruneRemove a Specific Snapshot#
restic -r /path/to/repo forget <snapshot-id> --prune8. Restoring Data#
Full Restore#
restic -r /path/to/repo restore <snapshot-id> --target /path/to/restoreRestore Latest Snapshot#
restic -r /path/to/repo restore latest --target /path/to/restoreRestore Specific Files#
restic -r /path/to/repo restore <snapshot-id> \
--target /path/to/restore \
--include "/home/user/Documents"Mount and Browse#
mkdir -p /mnt/restic
restic -r /path/to/repo mount /mnt/restic
# Browse snapshots at /mnt/restic/snapshots/<id>/
# Copy files as needed, then:
fusermount -u /mnt/resticDump a Single File to stdout#
restic -r /path/to/repo dump <snapshot-id> /path/to/file > restored-file9. Repository Maintenance#
Check Repository Integrity#
# Quick check (metadata only)
restic -r /path/to/repo check
# Full data verification (reads all pack files)
restic -r /path/to/repo check --read-data
# Check a percentage of data (useful for large repos)
restic -r /path/to/repo check --read-data-subset=5%Rebuild Index#
If the index becomes corrupted or out of sync:
restic -r /path/to/repo rebuild-indexPrune Unreferenced Data#
restic -r /path/to/repo prune
# With maximum repack size limit
restic -r /path/to/repo prune --max-repack-size 5GRepository Statistics#
restic -r /path/to/repo stats
restic -r /path/to/repo stats --mode raw-dataKey Management#
# List keys
restic -r /path/to/repo key list
# Add a new key (password)
restic -r /path/to/repo key add
# Remove an old key
restic -r /path/to/repo key remove <key-id>
# Change password
restic -r /path/to/repo key passwd10. Environment Variable Configuration#
Restic reads configuration from environment variables, making automation and scripting easier.
| Variable | Description |
|---|---|
RESTIC_REPOSITORY | Repository location (replaces -r) |
RESTIC_PASSWORD | Repository password |
RESTIC_PASSWORD_FILE | Path to a file containing the password |
RESTIC_PASSWORD_COMMAND | Command that outputs the password |
AWS_ACCESS_KEY_ID | S3/MinIO access key |
AWS_SECRET_ACCESS_KEY | S3/MinIO secret key |
B2_ACCOUNT_ID | Backblaze B2 account ID |
B2_ACCOUNT_KEY | Backblaze B2 account key |
RESTIC_CACHE_DIR | Override default cache directory |
RESTIC_COMPRESSION | Compression mode: auto, max, off (restic 0.14+) |
Password File Setup#
# Create a secure password file
echo "<repository-password>" > /etc/restic/password
chmod 600 /etc/restic/password
chown root:root /etc/restic/password
# Use it
restic -r /path/to/repo --password-file /etc/restic/password backup /dataEnvironment File for Automation#
Create /etc/restic/env:
export RESTIC_REPOSITORY="sftp:backup@server:/path/to/repo"
export RESTIC_PASSWORD_FILE="/etc/restic/password"
export RESTIC_COMPRESSION="auto"Source it before running restic:
source /etc/restic/env
restic backup /data11. Bandwidth Limiting and Rclone Integration#
Built-in Bandwidth Limiting#
# Limit upload to 5 MiB/s
restic -r /path/to/repo backup --limit-upload 5120 /data
# Limit download to 10 MiB/s
restic -r /path/to/repo restore latest --target /restore --limit-download 10240Values are in KiB/s.
Rclone Integration for Advanced Transport#
Rclone provides bandwidth limiting, retry logic, and support for additional backends:
# Configure rclone bandwidth limit globally
rclone config set <remote> --bwlimit "8M"
# Or per-session via restic
restic -o rclone.args="serve restic --stdio --bwlimit 5M" \
-r rclone:<remote>:path/to/repo backup /dataRclone with S3-Compatible Storage#
# Configure rclone remote
rclone config
# Choose s3, enter endpoint, key, secret
# Use with restic
restic -r rclone:<remote-name>:bucket/path init
restic -r rclone:<remote-name>:bucket/path backup /data12. Automation with Systemd#
Service Unit#
Create /etc/systemd/system/restic-backup.service:
[Unit]
Description=Restic backup
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
Nice=19
IOSchedulingClass=idle
EnvironmentFile=/etc/restic/env
ExecStart=/usr/bin/restic backup --verbose --exclude-file=/etc/restic/excludes.txt /home /etc /var/log
ExecStartPost=/usr/bin/restic forget --keep-daily=7 --keep-weekly=4 --keep-monthly=6 --prune
ExecStartPost=/usr/bin/restic checkTimer Unit#
Create /etc/systemd/system/restic-backup.timer:
[Unit]
Description=Run restic backup daily
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
RandomizedDelaySec=1h
[Install]
WantedBy=timers.targetEnable#
sudo systemctl daemon-reload
sudo systemctl enable --now restic-backup.timer
# Check status
systemctl list-timers restic-backup.timer
journalctl -u restic-backup.service -eTroubleshooting#
| Issue | Cause | Solution |
|---|---|---|
repository master key and target key mismatch | Wrong password or corrupted key | Verify the correct password; use key list to check keys |
Fatal: unable to open repo | Wrong path or missing credentials | Verify RESTIC_REPOSITORY and backend credentials |
unable to create lock | Stale lock from interrupted backup | Run restic unlock; check if another process is running |
| Slow backup speed | No compression, slow backend, or bandwidth limit | Set RESTIC_COMPRESSION=auto; check network; use --limit-upload |
pack files are missing | Partial repo corruption or interrupted prune | Run restic rebuild-index, then restic check --read-data |
| High memory usage | Large repository with many snapshots | Use --pack-size to limit pack sizes; prune aggressively |
S3 access denied | Incorrect IAM permissions | Ensure s3:GetObject, s3:PutObject, s3:DeleteObject, s3:ListBucket |
check found errors | Corrupted pack files | Run restic rebuild-index; restore affected files from other snapshots |