Skip to main content

15.2 A real backup, with restic

restic is a backup tool that does the three things that matter: it encrypts everything before it leaves the machine, it deduplicates so repeat backups are cheap, and it can write to a local disk or to cloud storage with the same commands.

It is a single binary with no server component, which is why it suits a lab and why plenty of small companies run it in production.

Decide where the backup goes​

This is the decision, and the tool is the easy part.

It must not be UBNT01. A backup on the machine it protects is a snapshot with extra steps, which is lesson 15.1's whole argument.

OptionGood forHonest downside
USB drive or spare diskFree, simple, genuinely off-machineOnly off-site if you unplug it and take it somewhere. Easy to forget
Another machine on your LANAutomatic, no costSame building, same power, same ransomware blast radius
Cloud object storageGenuinely off-site, cheap at lab scaleCosts a little money and needs an account

For this course, use a USB drive or a second disk, because it costs nothing and every step works identically. Where cloud storage differs is one line, and this lesson shows it.

Mount your drive on UBNT01. If it appears as /dev/sdb1:

# Make a mount point and mount it. lsblk first, to find the
# right device: picking the wrong one is how people format
# the disk they meant to keep.
lsblk
sudo mkdir -p /mnt/backup
sudo mount /dev/sdb1 /mnt/backup

How you know it worked:

# Your drive, with its free space. Confirm the size matches
# the drive you plugged in, which is the check that you
# mounted what you thought you did.
df -h /mnt/backup
Get the device right

lsblk lists every disk. /dev/sda is almost certainly UBNT01's own system disk. Formatting or mounting over that ruins the machine.

Look at the SIZE column and match it against the drive you physically plugged in. If two disks are the same size, unplug the USB one, run lsblk, plug it back in, run it again, and take the device that appeared.

Install restic​

sudo apt update
sudo apt install -y restic

How you know it worked:

# Any version. Expect something like "restic 0.16.4".
restic version

Create the repository​

A restic repository is the encrypted store your backups live in. It is initialised once.

The password is not recoverable. restic encrypts everything with it, and there is no reset. Lose it and your backups are permanently unreadable, which is working as designed and is nonetheless how people lose their backups.

Put it in your password manager before you run the next command.

# You will be asked for a password twice.
restic -r /mnt/backup/lab-repo init

How you know it worked:

created restic repository 09449fe9cb at /mnt/backup/lab-repo

Please note that knowledge of your password is required to access
the repository. Losing your password means that your data is
irrecoverably lost.

Your repository ID will differ. That warning is not boilerplate.

For cloud storage instead, the only change is the -r value, which becomes something like s3:s3.amazonaws.com/your-bucket plus credentials in environment variables. Every other command in this module is identical. That is the property that makes restic worth learning.

Stop typing the password​

Being prompted every time makes automation impossible, and lesson 15.6 automates this.

# A file only you can read, holding the repository password.
# The chmod is the whole security of this arrangement.
echo 'your-repository-password' | sudo tee /root/.restic-password > /dev/null
sudo chmod 600 /root/.restic-password

How you know it worked:

# Expect exactly: -rw------- and root root
sudo ls -l /root/.restic-password

Anything other than -rw------- means other users can read your backup password. This is lesson 5.6's least privilege applied to a file, and the reason it lives in /root is that the backup job will run as root, because backing up a whole system requires reading files your user cannot.

Back something up​

Start with the things that would genuinely hurt to lose:

sudo restic -r /mnt/backup/lab-repo \
--password-file /root/.restic-password \
backup /home /etc /var/lib/docker/volumes

Those three cover your home directories, this machine's configuration, and the Docker volumes from lesson 6.5, which is where your actual service data lives. A container is disposable; its volume is not.

How you know it worked:

Files: 1234 new, 0 changed, 0 unmodified
Dirs: 567 new, 0 changed, 0 unmodified
Added to the repository: 197.574 KiB (196.952 KiB stored)

processed 1234 files, 195.374 KiB in 0:03
snapshot dbd28800 saved

Your numbers will be much larger. The line that matters is the last one: snapshot <id> saved. No snapshot ID means no backup, whatever else the output said.

What this is called at work

restic is doing what Veeam, Commvault, Rubrik and Cohesity do: a repository, deduplicated snapshots, a retention policy, and encryption.

What enterprise backup adds is mostly awareness of what it is backing up. It can quiesce a database or a domain controller so the copy is consistent rather than merely recent, which is the problem lesson 15.4 is about. It backs up virtual machines through the hypervisor rather than from inside them. And it schedules and reports across thousands of jobs, because at that scale the question is not "did it work" but "which twelve of last night's four thousand jobs failed".

The feature everybody is buying right now is immutability: backups that cannot be deleted or encrypted even by an administrator, because ransomware operators go for the backups first and often succeed. Your restic repository does not have that, and knowing the gap exists is more useful than pretending it does not.

The thing that does not change is lesson 15.3. An untested backup is not a backup, at any price.

Now run it again, and watch why restic is worth it​

sudo restic -r /mnt/backup/lab-repo \
--password-file /root/.restic-password \
backup /home /etc /var/lib/docker/volumes

The second run is dramatically faster and adds almost nothing. In my test, backing up 195 KiB of data where one small file had changed added this:

Files: 0 new, 1 changed, 2 unmodified
Added to the repository: 1.479 KiB (870 B stored)

870 bytes, to protect the current state of everything.

That is deduplication: restic splits files into chunks, and only stores chunks it has never seen. Identical data is stored once no matter how many times it appears or how many snapshots reference it.

The practical consequence is the one to take away: because each backup is nearly free, you can afford to run them often, and running them often is what makes your RPO from lesson 15.1 small. Cheap backups and frequent backups are the same conversation.

See what you have​

sudo restic -r /mnt/backup/lab-repo \
--password-file /root/.restic-password snapshots
ID Time Host Tags Paths
--------------------------------------------------------------------
dbd28800 2026-08-05 15:31:41 ubnt01 /home
80d70c9c 2026-08-05 15:34:02 ubnt01 /home
--------------------------------------------------------------------
2 snapshots

Each snapshot is a complete, independently restorable point in time. There is no "full versus incremental" distinction to manage, which is the other reason this tool is pleasant.

Check that the repository itself is sound​

Backups can rot. Disks develop bad sectors, and a repository that has been quietly corrupting for a year is worse than no repository, because you believed in it.

sudo restic -r /mnt/backup/lab-repo \
--password-file /root/.restic-password check

How you know it worked:

check all packs
check snapshots, trees and blobs
[0:00] 100.00% 2 / 2 snapshots

no errors were found

no errors were found is the only acceptable output. Anything else means investigate now rather than at restore time.

Note what check does and does not do: it verifies the repository's structure and metadata are intact. It does not prove your data restores correctly, and it is not a substitute for lesson 15.3. Tools that report their own health are still tools reporting on themselves.

Do not keep everything forever​

# Keep a week of dailies and a month of weeklies. --dry-run
# shows what WOULD be removed without removing anything.
sudo restic -r /mnt/backup/lab-repo \
--password-file /root/.restic-password \
forget --keep-daily 7 --keep-weekly 4 --dry-run

Run the dry run first, every time, and read it. forget deletes snapshots. The --dry-run habit here is the same instinct as apt list --upgradable in lesson 13.7 and Ansible's --check in lesson 10.5: see what would change before changing it.

When the output looks right, run it again without --dry-run, then add --prune to actually reclaim the disk space. forget removes the snapshot references; prune deletes the now-unreferenced data.

What you take from this​

An encrypted, deduplicating backup repository on storage that is not the machine it protects, with a retention policy and a password you have stored somewhere you will still have it after the machine dies.

None of which proves you can get your data back. That is the next lesson, and it is the one that counts.