Fast, secure, cross-platform backup program with deduplication and support for numerous storage backends.

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-update

3. 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 init

SFTP#

restic -r sftp:<user>@<host>:/path/to/repo init

REST 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> init

For 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> init

Amazon 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> init

Backblaze B2#

export B2_ACCOUNT_ID=<account-id>
export B2_ACCOUNT_KEY=<account-key>
restic -r b2:<bucket-name>:<path> init

Rclone (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 init

Backend Comparison#

BackendSpeedCostComplexityUse Case
LocalFastestHardware costMinimalExternal drives, NAS
SFTPFast (LAN)Existing serverLowHome servers, VPS
REST ServerFastExisting serverLowDedicated backup server
S3/MinIOVariablePer-GB pricingMediumCloud backup, off-site
B2VariableLow per-GBMediumBudget cloud backup
RcloneVariableDependsMedium-HighAny cloud provider

5. Creating Backups#

Basic Backup#

restic -r /path/to/repo backup /home /etc /var/log

Backup with Tags#

restic -r /path/to/repo backup --tag daily --tag server1 /data

Backup from stdin#

# Backup a database dump
mysqldump --all-databases | restic -r /path/to/repo backup --stdin --stdin-filename mysql-dump.sql

Dry Run#

restic -r /path/to/repo backup --dry-run --verbose /data

Verbose Output with Statistics#

restic -r /path/to/repo backup --verbose --verbose /data

6. 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+found

Use it:

restic -r /path/to/repo backup --exclude-file=/etc/restic/excludes.txt /

Exclude Patterns Explained#

PatternMatches
*.tmpAny file ending in .tmp at any depth
.cacheAny 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.txt

7. 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 /home

Compare 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 \
  --prune

Without --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 \
  --prune

Remove a Specific Snapshot#

restic -r /path/to/repo forget <snapshot-id> --prune

8. Restoring Data#

Full Restore#

restic -r /path/to/repo restore <snapshot-id> --target /path/to/restore

Restore Latest Snapshot#

restic -r /path/to/repo restore latest --target /path/to/restore

Restore 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/restic

Dump a Single File to stdout#

restic -r /path/to/repo dump <snapshot-id> /path/to/file > restored-file

9. 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-index

Prune Unreferenced Data#

restic -r /path/to/repo prune

# With maximum repack size limit
restic -r /path/to/repo prune --max-repack-size 5G

Repository Statistics#

restic -r /path/to/repo stats
restic -r /path/to/repo stats --mode raw-data

Key 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 passwd

10. Environment Variable Configuration#

Restic reads configuration from environment variables, making automation and scripting easier.

VariableDescription
RESTIC_REPOSITORYRepository location (replaces -r)
RESTIC_PASSWORDRepository password
RESTIC_PASSWORD_FILEPath to a file containing the password
RESTIC_PASSWORD_COMMANDCommand that outputs the password
AWS_ACCESS_KEY_IDS3/MinIO access key
AWS_SECRET_ACCESS_KEYS3/MinIO secret key
B2_ACCOUNT_IDBackblaze B2 account ID
B2_ACCOUNT_KEYBackblaze B2 account key
RESTIC_CACHE_DIROverride default cache directory
RESTIC_COMPRESSIONCompression 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 /data

Environment 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 /data

11. 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 10240

Values 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 /data

Rclone 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 /data

12. 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 check

Timer 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.target

Enable#

sudo systemctl daemon-reload
sudo systemctl enable --now restic-backup.timer

# Check status
systemctl list-timers restic-backup.timer
journalctl -u restic-backup.service -e

Troubleshooting#

IssueCauseSolution
repository master key and target key mismatchWrong password or corrupted keyVerify the correct password; use key list to check keys
Fatal: unable to open repoWrong path or missing credentialsVerify RESTIC_REPOSITORY and backend credentials
unable to create lockStale lock from interrupted backupRun restic unlock; check if another process is running
Slow backup speedNo compression, slow backend, or bandwidth limitSet RESTIC_COMPRESSION=auto; check network; use --limit-upload
pack files are missingPartial repo corruption or interrupted pruneRun restic rebuild-index, then restic check --read-data
High memory usageLarge repository with many snapshotsUse --pack-size to limit pack sizes; prune aggressively
S3 access deniedIncorrect IAM permissionsEnsure s3:GetObject, s3:PutObject, s3:DeleteObject, s3:ListBucket
check found errorsCorrupted pack filesRun restic rebuild-index; restore affected files from other snapshots

See Also#

Sources#