Automatic backup with restic and systemd service

Magnetic hard disk open with the head and platter showing. Photo by Benjamin Lehman on Unsplash

Ever since I read the Automate backups with restic and systemd on Fedora Magazine, I have been meaning to practice the 3-2-1 backup strategy.

For a while, that did not come to fruition. Ultimately, that was down to laziness first of all; secondly, figuring out how and where the backups should be was also another struggle.

However, I finally sat down one weekend and figured out the works.

What is the 3-2-1 backup strategy?

The 3-2-1 strategy boils down to1:

  • 3 copies of data
  • 2 different media
  • 1 copy being off-site

The tutorial in the Fedora Magazine showcased how one can use restic2 and trigger the backup periodically via a systemd service unit file, instead of using cron. This also gave me the opportunity to learn a bit more about creating systemd service and timer units, so I decided to follow this.

However, the tutorial made use of an offsite backup solution provided by BackBlaze B2 Cloud storage. That solution was not one I was comfortable using just yet.

Mainly due to not wanting to use a service that did not provide Unix/Linux native tools, such as ssh, rsync and or sftp capabilities.

Therefore, I came up with these requirements:

  • 1 x local LAN server backup
  • 1 x local external drive backup
  • 1 x Unix/Linux native tool capable offsite backup

LAN server backup

This one was pretty easy, I already had a desktop computer which I use as a Virtual Machine host, that was connected via tailscale and had a lot of disk space using traditional hard disks.

So all I had to do was initialise a folder on this host via restic using SFTP as described in:

Problem #1 solved!

Local drive backup

My laptop is connected to a dock and has a couple of USB-C. I also had a couple of external storage drives, especially the Samsung Portable SSD T7 - 1TB drive.

So all I had to do was make sure that the backup service runs if and only if this drive was mounted.

Problem #2 solved!

In fact, this already in some way, satisfies #1 + #2 of the 3-2-1 strategy.

However, I still needed to make the similar copy backed up offsite. As per my requirements #3, BackBlaze B2 was off the list, sadly. 🤕

A while back, I read an article titled Interview with John Kozubkik - John is the CEO of which is a cloud storage in the form of a UNIX filesytem available over SSH. Ever since then I have been meaning to use this service somehow.

So for my #3 requirement, I researched using and luckily enough, they have a special pricing for restic -

Not only that what makes interesting is that:

there is no app or API - it simply gives you an empty UNIX filesystem accessible with any SSH tool.


So let’s piece the things together.

Systemd service and timer units

Systemd services (ends in .service) can be triggered periodically by Systemd timer units (ends in .timer). This separates the actual command / script that does the work with the timer configuration. I consider this to be neat!

Furthermore, as pointed out by the great ArchLinux wiki3, the benefits are:

  • Jobs can be easily started independently of their timers. This simplifies debugging.
  • Each job can be configured to run in a specific environment (see systemd.exec(5)).
  • Jobs can be attached to cgroups.
  • Jobs can be set up to depend on other systemd units.
  • Jobs are logged in the systemd journal for easy debugging.

So how would this look like in practice?

Let’s say that your backup command is as follows:

restic backup /home/user/secret-stuff \ \
    --verbose \
    --one-file-system \

The systemd service file, let’s call it, offsite-backup.service would be:

Description=Offsite backup with restic

ExecStartPre=restic unlock
ExecStart=restic backup /home/user/secret-stuff \ \
    --verbose \
    --one-file-system \
ExecStopPost=restic unlock

The offsite-backup.timer would be:

Description=Offsite backup with restic

Oncalendar=daily UTC


Repeat the above steps similarly for different configurations for different backup medium. For example, to backup locally to an external drive if and only if it is mounted, I have a service like so:

Description=Local Restic backup service

ExecStart=restic backup /home/user/secret-stuff \ \
    --verbose \
    --one-file-system \

If you are running the services for yourself under your own user, you can put them in ~/.config/systemd/user/ folder, otherwise it will have to go into /etc/systemd/system/ or system-wide user units in /etc/systemd/user/.

After that first reload the systemd daemon so that it knows there are new services available. Note: For user services include the --user argument after systemctl.

systemctl daemon-reload

Enable the timer unit:

systemctl enable --now offsite-backup.timer

To check when is the next scheduled run of your service:

systemctl list-timers

💯 🔥 Now you have an automatic backup job that runs according to the schedule you have setup, meaning you can sleep soundly while it does its job. 😄 🎉

Maverick Kaung
Maverick Kaung
IT Security Enthusiast

Ye Myat “Maverick” Kaung is a highly motivated individual with a passion for security and open source software. Also an aspiring hacker and software engineer.