In this post I describe the workflow I currently use to create offsite backups of my servers.
I use restic to create backups since it supports snapshots really well and saves the data in a [content-addressable storage]() which makes it very bandwidth- and space-efficient. Thus it is also quite fast. Another nice feature of restic is also that it supports multiple backends for storing data. I’m using the Backblaze B2 backend.
So let’s just dive right in. I’m not going to explain every single command in the script, because mostly their meaning and actions are rather obvious.
The interesting bit comes at the end: I’m using a systemd service and timer to trigger the backup job at predefined times.
Since systemd is collecting logs for each of the services its running anyway, I use this feature to fetch the logs of the current run.
This is implemented by first getting the timestamp of when that last service activation ended (
InactiveEnterTimestamp) and the getting the logs
since that timestamp from
Then I simply mail these logs to myself through the system mail.
TODO: always send e-mail, send mail when unit fails (systemd?) systemd.unit OnFailure
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
[Unit] Description=Run backup job Documentation=man:restic(1) Documentation=https://restic.readthedocs.io/en/stable/ Requires=local-fs.target Requires=network.target [Service] Type=oneshot Environment="XDG_CACHE_HOME=/var/cache" ExecStartPre=/usr/local/bin/cleanup-backups.sh ExecStart=/usr/local/sbin/restic-backup.sh [Install] WantedBy=multi-user.target
1 2 3 4 5 6 7 8 9 10
[Unit] Description=Activates Backup Job [Timer] # see man 7 systemd.time for possible formats OnCalendar=*-*-* 01:30:00 RandomizedDelaySec=120 [Install] WantedBy=timers.target
The nice thing about systemd timers is that they are a lot more flexible that traditional cronjobs, i.e. you can specify multiple run times for them (e.g. at noon, at midnight, on reboot). It also makes it really simply to random delay the execution of units. This is helpful when you have multiple servers backing up the same backend, so not all servers run it at the same time and the backend does not get overloaded.