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.
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
- Install btrbk.
mkdir /run/btr_pool
.mount /dev/sdb2 /run/btr_pool
cp /etc/btrbk/btrbk.conf.example ~/.btrbk.conf
- 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
- Run btrbk with
sudo btrbk -c ~/.btrbk.conf -v -n run
for a dry-run and without the-n
flag to stop dry-running. - If necessary, use
sudo btrbk -c ~/.btrbk.conf -l debug run
to debug the config. - Once the
btrbk
CLI runs without an error, create a service. To do so, runnvim /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
touch /usr/bin/run_btrbk.sh
.chmod +x /usr/bin/run_btrbk.sh
.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
- Run
sudo systemctl status philsBtrbk.service
to see if the service works. 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
- 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
- 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
- I test that
/etc/fstab
is configured correctly by runningmount -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: