Automating Backups With Btrbk On Fedora 34

January 14, 2022

Back in 2019, I wrote an article discussing core-principles of creating backups on a Linux machine. Ever since I wrote that piece, I refined my setup. My setup is built around a computer storage format called btrfs, which is based on the data structure of a copy-on-write B-Tree. That data structure makes generating snapshots a byproduct of storing data.

Schema Btrbk Backups

I leverage the great btrbk to manage snapshots with a systemd timer unit. I like the way btrbk creates, deletes and copies the snapshots for me. I also like the systemd timer unit. The setup works really well for my purpose.

Now, this is not intended to be a step-by-step guide for setting up btrbk. This comes without any strings attached. Backups are really important, and if I were you and you had any critical data on your disk, I wouldn’t trust a random blog post on how to set things up. This started out as my private documentation for how I set up my backup schedule. If it ends up helping you, dear unknown reader, that’s great. But don’t expect this to work and/or any support 🙂.

Basics Without btrbk#

To creat a quick backup of my /home folder, I run

btrfs subvolume snapshot -r /home /.snapshots/home-1

and create the /.snapshots/ directory beforehand. To test the capabilities of the snapshot, I run

touch ~/file.txt
btrfs subvolume snapshot -r /home /.snapshots/home-2

and then I navigate into /.snapshots/. The home-1/ directory doesn’t contain file.txt, whereas the file home-2/file.txt exists. I like how easy this is. I don’t need to mount a container, go through a list of archives and jump through hoops to access my backup. Everything is available on the disk, and I can access it immediately.

The next step of backing up data is sending snapshots to an external drive. I don’t want all my backups to sit on one drive, because if that drive fails or the house burns, my data is gone. I expect there to be an external drive mounted at /run/media/user/disk.

mkdir /run/media/user/disk/bk
sudo btrfs send /.snapshots/home-day1 | sudo btrfs receive /run/media/user/disk/bk

Great! I just sent a snapshot to an external drive. To set up incremental snapshots on the external drive, I run

sudo btrfs send -p /.snapshot/home-day1 /.snapshot/home-day2 | sudo btrfs receive /run/media/user/mydisk/bk

and the next day

sudo btrfs subvolume snapshot -r /home /.snapshots/home-day3
sudo btrfs send -p /.snapshot/home-day2 /.snapshot/home-day3 | sudo btrfs receive /run/media/user/mydisk/bk

Which is a low-key, manual version of what btrbk does. Next, I’ll automate this. Also, see this article for where I go my inspiration form.

Automation With btrbk#

  1. Install btrbk.
  2. mkdir /run/btr_pool.
  3. mount /dev/sdb2 /run/btr_pool
  4. cp /etc/btrbk/btrbk.conf.example ~/.btrbk.conf
  5. That config file looks like this for me:
transaction_log            /var/log/btrbk.log

stream_buffer              512m


# keep all snapshots for 2 days, no matter how frequently you (or your cron job) run btrbk
# keep daily snapshots for 14 days (very handy if you are on the road and the backup disk is not attached)
# keep monthly backups forever
# keep weekly backups for 10 weeks
# keep daily backups for 20 days

timestamp_format        long
snapshot_preserve_min   2d
snapshot_preserve       14d

target_preserve_min     no
target_preserve         20d 10w *m

archive_preserve_min    latest
archive_preserve        12m 10y

# Backup to external disk mounted on /run/media/philipp/phils-disk/btr_backup
volume /run/btr_pool

  snapshot_dir      _btrbk_snapshots
  target            /run/media/philipp/phils-disk/btrbk_backup
  subvolume         home
  subvolume         root

  # no action if external disk is not attached
  snapshot_create  ondemand



  # subvolume  kvm
  #   # use different retention policy for kvm backups
  #   target_preserve     7d 4w
  1. Run btrbk with sudo btrbk -c ~/.btrbk.conf -v -n run for a dry-run and without the -n flag to stop dry-running.
  2. If necessary, use sudo btrbk -c ~/.btrbk.conf -l debug run to debug the config.
  3. Once the btrbk CLI runs without an error, create a service. To do so, run nvim /etc/systemd/system/philsBtrbk.service and write into it:
# This service runs btrbk hourly to create new snapshots
# of my entire machine. These are then stored on the
# laptop's drive at /run/btr_pool/_btrbk_snapshots/,
# and on my external harddrive, which mounts to
# /run/media/philipp/$drive_name/btrbk_backup

# I used this article as a reference to create the config:
# https://opensource.com/article/20/7/systemd-timers

[Unit]
Description=Creates snapshots of the btrfs filesystem
Wants=philsBtrbk.timer

[Service]
Type=oneshot
ExecStart=/usr/bin/run_btrbk.sh

[Install]
WantedBy=multi-user.target
  1. touch /usr/bin/run_btrbk.sh.
  2. chmod +x /usr/bin/run_btrbk.sh.
  3. nvim /usr/bin/run_btrbk.sh and copy the following into it:
#!/bin/bash

# I use this script for philsBtrbk.service managed
# by systemd. For more details, run
# `systemctl list-timers`
sudo btrbk -c /home/philipp/.btrbk.conf run
  1. Run sudo systemctl status philsBtrbk.service to see if the service works.
  2. nvim /etc/systemd/system/philsBtrbk.timer and copy the following into it:
# This runs the snapshotting for my filesystem with btrbk
# hourly.

[Unit]
Description=Creates a snapshot and stores it on my external drive
Requires=philsBtrbk.service

[Timer]
Unit=philsBtrbk.service
OnCalendar=*-*-* *:00:00

[Install]
WantedBy=timers.target
  1. Run thhese commands
systemctl daemon-reload
systemctl start philsBtrbk.timer
systemctl enable --now philsBtrbk.timer

to start and enable the timer. To check if the timer really works, use sytemctl list-timers all.

mount /dev/sdb2 /run/btr_pool

  1. To mount /dev/sdb2/ at /run/btr_pool/ at startup, I edit /etc/fstab and add to the bottom of the file
UUID={YOUR_DISK_ID} /run/btr_pool		  btrfs	  defaults	  1 2
  1. I test that /etc/fstab is configured correctly by running mount -a. Be careful, messing up the fstab file will potentially prevent a machine from booting.

Final Thoughts#

That’s it. Maybe this is helpful to someone out there. Feel free to contact me if you want to add anything or comment. These are the resources I used to get going: