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 we humans are notoriously bad at being consistent. Ever try to start a workout routine on January 1? You may have the most elaborate and secure backup system in the world, but when you accidentally loose your data it will only be as good as the last time it made a backup.

(I’m sure there are cases where it doesn’t make sense to make automatic backups, I just haven’t found them in for 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 or at some point randomly during the day. These backups have saved by butt in those dumb late night moments like when I accidentally reformatted my ssd instead of a usb drive.

However, I’ll admit I’ve been tempted to cancel a backup or two when my laptop’s fan goes full throttle first thing in the morning or when I’m on a meeting with someone.

So why make backups at night? Because I want my laptop to be ready to go to work every morning when I am and use less energy when I’m at a coffee shop tempting fate with 10% battery and I haven’t yet pushed a git commit. (I know not one of my proudest moments.)

At night my laptop is almost always plugged in, on a reasonably stable internet connection, and not burning a hole through my lap.

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 a “wake up” alarm on your system for the specified time, triggering the CPU to wake from sleep.

This works great until your on an 11 hour flight to Tokyo and you realize your backpack is strangely warm. So along with waking up your system I highly recommend using 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’ll demo 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 Persistent=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

In the 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 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