How to Make Encrypted, Deduplicated Backups with restic

The rsync-and-tar approach (tutorial 23) works, but it has limits: every dated archive is a full copy, nothing is encrypted, and restoring one file from last Tuesday means unpacking the whole archive. restic fixes all three. It takes snapshots — each one looks like a full backup, but only the blocks that changed are stored — encrypts everything, and can write to a local folder, an SFTP server, Backblaze B2 or any S3 bucket with the same commands.
Quick reference
| Task | Command |
|---|---|
| Install | sudo apt install restic -y && sudo restic self-update |
| Create a repository | restic init -r /mnt/backup/restic |
| Back up | restic backup /home /etc /var/www |
| List snapshots | restic snapshots |
| Restore | restic restore latest --target ~/restore --include /etc/nginx |
| Thin out old snapshots | restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --prune |
| Check integrity | restic check |
1. Install
sudo apt install restic -y
sudo restic self-update
2. Create a repository
A repository is just a folder (or bucket) restic manages. Locally:
sudo restic init -r /mnt/backup/restic
It asks for a password. Write it down somewhere off the server — the repository is unreadable without it.
For Backblaze B2 instead:
export B2_ACCOUNT_ID=keyid B2_ACCOUNT_KEY=appkey
restic init -r b2:bucket-name:server
3. Stop typing the password and path
sudo nano /root/.restic.env
export RESTIC_REPOSITORY=/mnt/backup/restic
export RESTIC_PASSWORD=your-repo-password
sudo chmod 600 /root/.restic.env, then source /root/.restic.env before any restic command (the script below does this).
4. First backup
sudo bash -c 'source /root/.restic.env && restic backup /home /etc /var/www /home/john/docker --exclude /home/*/.cache'
The first run copies everything. Every run after that takes seconds to minutes, because only changed blocks are sent — even inside large files.
Databases still need dumping first (mysqldump to a file that restic then backs up).
5. Look at what you've got
sudo restic snapshots
sudo restic ls latest /etc/nginx
sudo restic diff <id1> <id2>
Or mount the whole history and browse it like folders:
sudo mkdir -p /mnt/restic && sudo restic mount /mnt/restic
/mnt/restic/snapshots/2026-10-08T02:00:01/etc/... — every snapshot, every file, read-only. Ctrl + C unmounts.
6. Restore
One folder from the latest snapshot:
sudo restic restore latest --target /tmp/restore --include /etc/nginx
Everything from a specific snapshot: sudo restic restore 3a1b2c3d --target /.
7. Keep it tidy
sudo restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --prune
That keeps a snapshot for each of the last 7 days, 4 weeks and 12 months, and --prune reclaims the space.
8. The nightly script
sudo nano /usr/local/bin/restic-backup.sh
#!/bin/bash
set -e
source /root/.restic.env
mysqldump --all-databases | gzip > /var/backups/db.sql.gz
restic backup /home /etc /var/www /var/backups /home/john/docker --exclude-caches --quiet
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --prune --quiet
echo "restic ok $(date +%F)"
sudo chmod +x /usr/local/bin/restic-backup.sh
sudo crontab -e
0 2 * * * /usr/local/bin/restic-backup.sh >> /var/log/restic.log 2>&1
Run sudo restic check monthly.
Two repositories
The best setup is a local repository for fast restores and a B2 one for disaster. Either run the backup twice with different RESTIC_REPOSITORY values, or rclone the local repository to the cloud (tutorial 54) — restic repositories copy perfectly.
Troubleshooting
"repository is already locked". A previous run was interrupted. restic unlock.
"wrong password or no key found". The password in .restic.env doesn't match. Repositories can have several keys: restic key add.
Backup is slow on the first run. Expected; it reads everything once. Later runs are fast.
Disk filling despite forget. You forgot --prune, which actually deletes the data.
Wrapping up
Init a repository, back up a list of folders, forget-and-prune on a policy, cron it. Encrypted, deduplicated, browsable snapshots to anywhere, with the same four commands whether the target is a USB drive or a bucket on the other side of the world.
