Boring, reliable backups with restic and a systemd timer

2026-08-30 · 6 min read

For years my backup strategy was "copy things to a USB drive when I remember". This post describes what replaced it: restic, an S3-compatible bucket and two small systemd units.

Why restic

It is a single static binary, it encrypts everything client-side, deduplicates well and supports a dozen storage backends. Most importantly, restoring a single file is easy — which means I actually test it.

The service unit

[Unit]
Description=restic backup

[Service]
Type=oneshot
EnvironmentFile=/etc/restic/env
ExecStart=/usr/bin/restic backup /home /etc --exclude-caches
ExecStartPost=/usr/bin/restic forget \
    --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

The environment file holds the repository URL, the credentials and the repository password. It is owned by root with mode 0600, which is the least I can do.

The timer

[Unit]
Description=nightly restic backup

[Timer]
OnCalendar=*-*-* 03:30
RandomizedDelaySec=15m
Persistent=true

[Install]
WantedBy=timers.target

Persistent=true matters on a machine that is not always on: if it was asleep at 03:30, the job runs at the next boot instead of being skipped silently.

Testing restores

A backup you have never restored is a hope, not a backup. Once a week another job picks a random file from the latest snapshot, restores it into a temporary directory and compares its checksum with the original. If they differ, or if the snapshot is older than two days, I get an email.

What I would do differently

I should have set up the monitoring first. For about three months the timer was failing because of an expired token, and I only noticed when I went looking for a deleted file. Now the absence of a fresh snapshot is itself an alert.

That's the whole setup. Nothing clever — which is exactly the point.