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

Table of Contents#

  1. Overview
  2. Installation
  3. Core Concepts
  4. Repository Backends
  5. Creating Backups
  6. Exclude Patterns
  7. Managing Snapshots
  8. Restoring Data
  9. Repository Maintenance
  10. Environment Variable Configuration
  11. Bandwidth Limiting and Rclone Integration
  12. Automation with Systemd
  13. Troubleshooting
  14. See Also
  15. 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-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#