This past weekend I taught my laptop to wake up in the middle of the night and create a backup of itself. This is something I’ve always wanted to do but until recently I didn’t think it was possible in Linux. Turns out it’s not only possible but actually pretty easy to setup.

Why Create Automatic Backups?

In short, because humans are notoriously bad at being consistent. I can’t tell you how many times I’ve nearly missed an important meeting or almost forgotten to pay rent because I’m stupidly good at getting hooked on a problem at work. You may have the most elaborate and secure backup system in the world, but when you accidentally loose your data it will only as good as the last time it made a backup.

As a note however, I’m sure there are cases where it doesn’t make sense to make automatic backups, I just haven’t found them in my own systems yet.

Why Make Backups At Night?

Although I’ve been automatically making backups of my laptop for a while now, they always just occurred whenever I first opened my laptop in the morning. This has been great because even through those dumb moments like when I accidentally reformatted my ssd instead of a usb drive, I’ve never actually lost any important data.

However, its hard not to look over at the Apple ecosystem where backups and updates happen automatically at night and not get a little jealous when my laptop’s fan goes full throttle first thing in the morning.

So why make backups at night? I guess because I want my laptop to be ready to go every morning when I am and use less energy from it’s battery when it can do a task at night when its almost alway plugged in.

Waking a System Up From Sleep

If you’re running a Linux distribution with Systemd and your laptop has a realtime clock, it is surprisingly easy to get your computer to wake up from sleep. All you have to do when you define your systemd timer is use use the WakeSystem=true argument. This will tell systemd to set an wake up alarm on your system for the specified time. But wait! What if I’m on a 16 hour flight? Couldn’t that wake up my laptop while it’s still in my bag? Yes! So along with waking up your system I’d also strongly suggest you use the ConditionACPower=true parameter in your service file to make sure long running tasks don’t run when you aren’t ready for them.

My Restic Backup System

Although you can use systemd to run any backup program at night I personally use restic and so that’s what I’ve used here. Speaking of, if you don’t already have a backup system, I highly recommend using restic. It is an incredibly powerful backup system and using rclone you can backup your data from it onto almost any cloud storage provider.

Below is a redacted version of my restic backup system. Let’s start with the systemd timer which will wake up the system from sleep every night at 3AM and run the restic-backup.service. This timer is not persistent which means if it misses it’s backup time it won’t keep trying to reschedule the backup. However if you would like to make the system automatically reschedule a missed backup you can change this parameter from false to true.

/etc/systemd/system/restic-backup.timer

[Unit]
Description=Backup Laptop Data to Nextcloud
Documentation=man:restic

[Timer]
OnCalendar=*-*-* 3:00
WakeSystem=true
Persistent=false

[Install]
WantedBy=timers.target

Here in our restic backup service file we will define which command should be run as part of our backup and limit it to only run when the laptop is plugged in with the ConditionACPower=true parameter. Additionally we’ll state that the service requires the network to be online so that our backup will only run after the laptop has reconnected to our WiFi.

Note: If you’re using restic backups make sure to include your restic backup password in the environment parameter here. Also run,

$ sudo chmod o-r /etc/systemd/system/restic-backup.service

to make sure that no one other than root can read your restic encryption password.

/etc/systemd/system/restic-backup.service

[Unit]
Description=Backup Laptop Data to Nextcloud
Documentation=man:restic
ConditionACPower=true
Requires=network-online.target
After=network-online.target

[Service]
Type=simple
User=root
Group=root
Environment=RESTIC_PASSWORD={{INSERT-SECRET-PASSPHRASE-HERE}}
ExecStart=/bin/systemd-inhibit --what=handle-lid-switch --why=restic-backup /bin/su alecbcs -c /bin/restic-backup

[Install]
WantedBy=network-online.target

Lastly, this is how I’ve defined my restic backup script. I’m backing up onto a Nextcloud instance using Rclone & WebDAV but you can use any remote you’ve got setup on rclone by simply by replacing nextcloud with the name of your remote. Additionally make sure to replace alecbcs with your username throughout the backup script.

To learn more about using restic, checkout their getting started guide here.

/bin/restic-backup

#! /bin/bash

# wait for network manager to bring up the wifi interface
nm-online -q -t 300

# take a snapshot of your home directory using restic
restic -r rclone:nextcloud:path/to/backup/location backup \
       --verbose --exclude=/home/alecbcs/.cache/ \
       --exclude=/home/alecbcs/go \
       --exclude=/home/alecbcs/.local/share/Trash/ \
       --exclude=/home/alecbcs/.var/ \
       /home/alecbcs

# check the integrity of your restic backups
restic -r rclone:nextcloud:path/to/backup/location check

# remove old restic backups
restic -r rclone:nextcloud:path/to/backup/location forget \
       --prune \
       --keep-last 10 \
       --keep-hourly 24 \
       --keep-daily 7 \
       --keep-weekly 52 \
       --keep-monthly 120 \
       --keep-yearly 10