Key Takeaways
- Encrypted by default: Every restic repository is encrypted with AES-256-CTR + Poly1305-AES. There is no unencrypted restic repository — encryption cannot be disabled.
- Deduplication saves space: Restic chunks files using content-defined chunking (CDC) — identical content is stored once regardless of filename or path. Incremental backups of databases typically add 5–15% of the original size per backup.
restic checkis mandatory: A backup you haven’t verified is not a backup. Runrestic checkweekly andrestic check --read-datamonthly to verify data integrity.- SovereignScore 99/100: Restic is open-source (BSD 2-clause), encryption keys stay local, and all 14 backends support air-gapped operation after initial setup.
Introduction
Direct Answer: How do I set up Restic for encrypted backups on Ubuntu 24.04 in 2026?
Install Restic with sudo apt-get install -y restic. Initialise a repository with restic init --repo /mnt/backup/myserver — you’ll be prompted to set a password that encrypts all backup data. Create the first backup with restic backup --repo /mnt/backup/myserver /etc /home /opt --tag server-backup. Check what was backed up with restic snapshots --repo /mnt/backup/myserver. Restore a specific file with restic restore latest --repo /mnt/backup/myserver --target /tmp/restore --include "/etc/nginx". To automate, create a systemd timer that runs restic backup daily and a weekly restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 to prune old snapshots. The repository password must be stored securely — store it in /etc/restic-password with chmod 600, referenced via --password-file in all restic commands.
Part 1: Installation
sudo apt-get install -y restic
restic version
Expected output:
restic 0.17.1 compiled with go1.22.2 on linux/amd64
Part 2: Create a Repository and First Backup
# ── LOCAL REPOSITORY (on the same server, for quick restores) ─────────────
# Create the repository directory
sudo mkdir -p /mnt/backup/myserver
sudo chown $USER:$USER /mnt/backup/myserver
# Store the repository password securely (do NOT use a weak password)
# Generate a strong password:
openssl rand -base64 32 | sudo tee /etc/restic-password
sudo chmod 600 /etc/restic-password
sudo chown root:root /etc/restic-password
echo "Password file created"
# Initialise the repository
restic init --repo /mnt/backup/myserver --password-file /etc/restic-password
Expected output:
created restic repository abc1234567 at /mnt/backup/myserver
Please note that knowledge of your password is required to access
the repository. Losing your password means that your backed up
data cannot be recovered.
# Create the first backup
restic backup \
--repo /mnt/backup/myserver \
--password-file /etc/restic-password \
--tag server \
--tag initial \
/etc \
/home \
/var/log \
/opt \
--exclude "/home/*/.cache" \
--exclude "/home/*/.local/share/Trash" \
--exclude "*.tmp"
Expected output:
repository abc1234567 opened (version 2, compression level auto)
created new cache in /root/.cache/restic
Files: 8,432 new, 0 changed, 0 unmodified
Dirs: 1,247 new, 0 changed, 0 unmodified
Added to the repository: 2.341 GiB (1.123 GiB stored) ← Deduplication
snapshot 7f3a2b1c saved
“2.341 GiB stored as 1.123 GiB” — 52% space savings from deduplication and compression on first backup.
# List snapshots
restic snapshots --repo /mnt/backup/myserver --password-file /etc/restic-password
Expected output:
repository abc1234567 opened (version 2)
ID Time Host Tags Paths
──────────────────────────────────────────────────────────────────
7f3a2b1c 2026-04-28 13:00:00 hetzner-cx22 server,initial /etc, /home, /var/log, /opt
1 snapshots
Part 3: Remote Repository via SFTP
For the offsite backup copy (3-2-1 rule):
# Initialise repository on a remote server via SFTP
# Requires SSH key authentication to the remote server
restic init \
--repo "sftp:[email protected]:/backups/myserver" \
--password-file /etc/restic-password
Expected output:
created restic repository def567890a at sftp:[email protected]:/backups/myserver
# Backup to the remote repository (same command, different --repo)
restic backup \
--repo "sftp:[email protected]:/backups/myserver" \
--password-file /etc/restic-password \
--tag server \
/etc /home /opt
# Verify the remote backup is intact
restic check \
--repo "sftp:[email protected]:/backups/myserver" \
--password-file /etc/restic-password
Expected output:
using temporary cache in /tmp/restic-check-cache-123
load indexes
check all packs
check snapshots, trees and blobs
no errors were found
Part 4: Automated Backups with systemd
# Create backup script
sudo tee /usr/local/bin/restic-backup.sh << 'SCRIPT'
#!/bin/bash
set -euo pipefail
REPO_LOCAL="/mnt/backup/myserver"
REPO_REMOTE="sftp:[email protected]:/backups/myserver"
PASSWORD_FILE="/etc/restic-password"
LOG="/var/log/restic-backup.log"
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG"; }
log "=== Backup started ==="
# Local backup
log "Backing up to local repository..."
restic backup \
--repo "$REPO_LOCAL" \
--password-file "$PASSWORD_FILE" \
--tag daily \
--exclude "/home/*/.cache" \
--exclude "*.tmp" \
/etc /home /opt /var/log \
2>&1 | tee -a "$LOG"
# Prune old snapshots (keep 7 daily, 4 weekly, 12 monthly)
log "Pruning old snapshots..."
restic forget \
--repo "$REPO_LOCAL" \
--password-file "$PASSWORD_FILE" \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 12 \
--prune \
2>&1 | tee -a "$LOG"
# Remote backup
log "Syncing to remote repository..."
restic backup \
--repo "$REPO_REMOTE" \
--password-file "$PASSWORD_FILE" \
--tag daily \
--exclude "/home/*/.cache" \
/etc /home /opt \
2>&1 | tee -a "$LOG"
log "=== Backup complete ==="
SCRIPT
sudo chmod +x /usr/local/bin/restic-backup.sh
# Create systemd service
sudo tee /etc/systemd/system/restic-backup.service << 'EOF'
[Unit]
Description=Restic Backup
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/restic-backup.sh
StandardOutput=journal
StandardError=journal
EOF
# Create systemd timer (runs at 2:30 AM daily)
sudo tee /etc/systemd/system/restic-backup.timer << 'EOF'
[Unit]
Description=Run Restic backup daily at 2:30 AM
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true # Run immediately if missed (e.g., server was off)
RandomizedDelaySec=600 # Randomise within 10 minutes to avoid thundering herd
[Install]
WantedBy=timers.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now restic-backup.timer
# Verify timer is scheduled
systemctl list-timers restic-backup.timer
Expected output:
NEXT LEFT LAST PASSED UNIT
Tue 2026-04-29 02:30:00 UTC 13h left n/a n/a restic-backup.timer
# Test the backup runs successfully
sudo systemctl start restic-backup.service
sudo journalctl -u restic-backup.service -n 20
Expected output:
Apr 28 13:30:00 server restic-backup.sh[12345]: [2026-04-28 13:30:00] === Backup started ===
Apr 28 13:30:00 server restic-backup.sh[12345]: [2026-04-28 13:30:00] Backing up to local repository...
Apr 28 13:30:02 server restic-backup.sh[12345]: snapshot 8a4b3c2d saved
Apr 28 13:30:02 server restic-backup.sh[12345]: [2026-04-28 13:30:02] === Backup complete ===
Part 5: Restore Files
# List available snapshots
restic snapshots --repo /mnt/backup/myserver --password-file /etc/restic-password
# Browse snapshot contents (without restoring)
restic ls --repo /mnt/backup/myserver --password-file /etc/restic-password latest /etc/nginx
# Restore a single file
restic restore latest \
--repo /mnt/backup/myserver \
--password-file /etc/restic-password \
--target /tmp/restore \
--include "/etc/nginx/sites-available/mysite.conf"
ls -la /tmp/restore/etc/nginx/sites-available/
# Restore an entire directory
restic restore latest \
--repo /mnt/backup/myserver \
--password-file /etc/restic-password \
--target /tmp/restore-full \
--include "/home/ubuntu"
# Restore from a specific snapshot (not latest)
SNAPSHOT_ID="7f3a2b1c"
restic restore $SNAPSHOT_ID \
--repo /mnt/backup/myserver \
--password-file /etc/restic-password \
--target /tmp/restore-old
Expected output:
restoring <Snapshot 7f3a2b1c of [/etc/nginx/sites-available/mysite.conf]> to /tmp/restore
Summary: Restored 1 files/dirs (4.212 KiB) in 0:00
Part 6: Weekly Integrity Check
# Add a weekly integrity check timer
sudo tee /etc/systemd/system/restic-check.service << 'EOF'
[Unit]
Description=Restic Repository Integrity Check
[Service]
Type=oneshot
ExecStart=restic check \
--repo /mnt/backup/myserver \
--password-file /etc/restic-password \
--read-data-subset 10%% # Verify 10% of data chunks (fast + thorough)
StandardOutput=journal
StandardError=journal
EOF
sudo tee /etc/systemd/system/restic-check.timer << 'EOF'
[Unit]
Description=Weekly Restic integrity check
[Timer]
OnCalendar=Sun 04:00:00
Persistent=true
[Install]
WantedBy=timers.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now restic-check.timer
# Run a check now to verify everything is healthy
sudo restic check \
--repo /mnt/backup/myserver \
--password-file /etc/restic-password
Expected output:
using temporary cache in /tmp/restic-check-cache
load indexes
check all packs
check snapshots, trees and blobs
no errors were found
Troubleshooting
Fatal: unable to open config file
Cause: Repository not initialised at this path, or wrong path.
Fix: restic init --repo /path/to/repo --password-file /etc/restic-password to create it, or check the path is correct.
Backup taking too long — subsequent backups should be fast
Cause: First backup is always slow (full copy). Subsequent backups are incremental — only changed files are uploaded. Normal behaviour: A 10GB initial backup might take 5 minutes. The same directory the next day (with minimal changes) should take 10–30 seconds.
restic check reports errors
Cause: Repository corruption — possibly from interrupted backup, disk failure, or transmission error. Fix:
# Rebuild the repository index
restic rebuild-index --repo /mnt/backup/myserver --password-file /etc/restic-password
# Then re-check
restic check --repo /mnt/backup/myserver --password-file /etc/restic-password
If errors persist, restore from the offsite backup copy.
Conclusion
Restic is running: encrypted incremental backups to a local repository every night at 2:30 AM, automatically pruned to 7 daily + 4 weekly + 12 monthly snapshots, with a weekly integrity check. The identical command syntax against the SFTP remote repository provides the offsite copy for the 3-2-1 backup rule.
This backup infrastructure protects the data on the servers built throughout the Dev Corner guides — see Ubuntu 24.04 LTS Server Setup Checklist for the full server hardening workflow this backup system completes.
People Also Ask
Is Restic better than rsync for backups?
They solve different problems. rsync is a file sync tool that copies files from source to destination — it is fast and simple but the destination is a plain directory that can be accidentally modified or deleted. Restic is a proper backup tool — it stores immutable snapshots, deduplicates data across snapshots, encrypts everything, and supports versioning and retention policies. Use rsync for mirroring files between servers. Use Restic for server backups where you need encryption, versioning, and data integrity verification.
Where should I store the repository password?
The password file (/etc/restic-password) must be: (1) readable by the user/service running restic, (2) not readable by other users (chmod 600), and (3) stored separately from the backup repository. If the password is lost, the backup is permanently unrecoverable — Restic’s AES-256-CTR encryption has no backdoor. Store the password in a password manager (Bitwarden, KeePass) as well as in the file. For team setups, store it in a secrets manager (HashiCorp Vault, Infisical). Never store the password in the same location as the repository.
Can Restic back up a running PostgreSQL or MySQL database?
Restic can back up database data directories, but this is not safe for running databases — the files may be in an inconsistent state mid-transaction. The correct approach: dump the database first, then back up the dump. A pre-backup hook in the restic-backup.sh script handles this:
# In restic-backup.sh, before the restic backup command:
sudo -u postgres pg_dumpall | gzip > /var/backups/postgres-$(date +%Y%m%d).sql.gz
Restic then backs up the compressed dump file, which captures a consistent snapshot.
Further Reading
- Ubuntu 24.04 LTS Server Setup Checklist — the baseline configuration this backup system protects
- PostgreSQL Performance Tuning Guide — includes pg_dump patterns to use alongside Restic
- Cron Jobs and systemd Timers on Ubuntu 24.04 — the scheduling mechanism used in this guide
- WireGuard VPN on Ubuntu 24.04 — secure the SFTP connection used for offsite backups
Tested on: Ubuntu 24.04 LTS (Hetzner CX22). Restic 0.17.1. Last verified: April 28, 2026.