
So, let’s say you got Debian/Ubuntu Server running on Btrfs and you’d like to make use of the snapshots feature to rollback.
In case you didn’t know, snapshots are a way to create point in time freezes of a filesystem. This allows you do revert to a previous snapshot, e.g. if something went wrong during a software install or you accidentally deleted a file. Snapshots are space efficient because they only store the differences between snapshots (if done right).
In this guide, I’m using Ubuntu Server 24.04 LTS and a Btrfs volume, with the subvolumes @
and @home
for /
and /home
respectively.
My Btrfs volume is residing on /dev/mapper/root
(because I’m using dm-crypt to encrypt it all).
Setting things up
First thing we’ll do, is mount our Btrfs volume somewhere and create a subvolume for snapshots:
mkdir -p /mnt/btrfs
mount /dev/mapper/root /mnt/btrfs
btrfs subvolume create /mnt/btrfs/@snapshots
umount /mnt/btrfs
mkdir -p /snapshots
echo '/dev/mapper/root /snapshots btrfs nosuid,nodev,noexec,compress=zstd,subvol=@snapshots 0 0' >> /etc/fstab
mount -av
Now we have our snapshots directory ready to use. Of course you have to adjust /dev/mapper/root
to point to your actual volume (if it’s a block device, use the UUID!)
The reason we’re creating our separate snapshots subvolume and directory, is so that we have one central and clean place for them, and hopefully no recursive snapshotting.
Creating our first snapshots
So, now that we have our destination set up, we’ll manually create our first snapshots of root and home:
btrfs subvolume snapshot -r / /snapshots/@_2024-12-14_12-32
btrfs subvolume snapshot -r /home /snapshots/@home_2024-12-14_12-32
Please note that we’re using the -r
option here to make a read-only snapshot. This is important to be able to use the Btrfs “send” functionality, but more on that later.
This is nice and all, but we can do better.
Automating our snapshots
Manually creating snapshots can be useful, e.g. imminently before a distro upgrade or installing some new major software.
However, what’s even better is if we create automatic snapshots to make sure we can’t forget to make them. For this, we’ll use btrbk:
sudo apt update && sudo apt install -y btrbk
sudo touch /etc/btrbk/btrbk.conf
sudo chmod 0600 /etc/btrbk/btrbk.conf
It was at this point that the genius author realized that Ubuntu 22.04 ships btrbk 0.31.3 which is too old to specify absolute paths and work with my structure, so, I’ll quickly create a new snapshot called @_2024-12-14_pre_upgrade
and upgrade to 24.04 (which was the whole reason I set up snapshots in the first place). So, this guide will only work with 24.04.
[one annoyance later]
I’m back on 24.04 with btrbk 0.32.5, let’s continue! :D
We edit the file /etc/btrbk/btrbk.conf
and add the following contents:
# Basic Options
timestamp_format long-iso
snapshot_create onchange
incremental yes
# Retention Options
snapshot_preserve_min 1d
snapshot_preserve 24h 7d 4w 12m 5y
preserve_day_of_week wednesday
preserve_hour_of_day 6
# Paths
snapshot_dir /snapshots
subvolume /
subvolume /home
Now btrbk will create snapshots of /
and /home
and store them in our /snapshots
subvolume. Let me explain the config a bit:
We choose the timestamp format to be long-iso, which means we will get the full date and time with seconds and timezone according to an ISO standard; this helps us avoid duplicate naming if we run things twice (thanks to the seconds) and the timezone information can help us sort things across different systems (across different timezones).
We define snapshots to only be created if the filesystem actually had any change. So, e.g. if root had a change, but home was unchanged, only root would get a new snapshot. We also make sure that snapshots are incremental to save space.
As for the retention options, we make sure that all snapshots are kept for at very least one full day. But in addition, the retention options say that we should keep 24 hourly backups, 7 daily backups, 4 weekly backups, 12 monthly backups and 5 yearly backups. Anything older should be deleted. We specify that the time for the daily backups is 06:00am, and the time for weekly backups is Wednesday; backups will still be created every hour/day but those are the time and day which “count” for the long-term preservation. I chose Wednesday because I tend to do maintenance during the weekends, and things are unlikely to change in the middle of the week and seems like a good day to be able to roll back to.
To test that the config is working, we make a dry-run which won’t actually make any changes:
btrbk run -v -n
If we’re satisfied with what it does, we can run it for real:
btrbk run -v
Cool! We got our first snapshot. If everything worked as intended, we automate it:
mkdir -p /etc/cron.hourly/
touch /etc/cron.hourly/btrfs-snapshots
chmod 0700 /etc/cron.hourly/btrfs-snapshots
We edit the contents of /etc/cron.hourly/btrfs-snapshots
to be:
#!/bin/sh
exec /usr/bin/btrbk -q run
Now we should have our task run hourly. (:
Note: The reason I’m calling the cron file btrfs-snapshots
and not btrbk
is because you might already have a btrbk.timer
packaged by your distro’s package maintainer, which can conflict with our cronjob. In the case of Ubuntu 24.04 it’s definitely there and runs once a day. Since I want to run it hourly, I create my own hourly cron and then:
systemctl disable btrbk.timer
systemctl mask btrbk.timer
Conclusion
Setting up Btrfs snapshots is quite straightforward once you know what you’re doing. In future articles we’ll talk about offloading those local snapshots to other storage mediums or servers over SSH to back them up, since snapshots are not backups themselves, and are instead just meant for quick disaster recovery when e.g. deleting files or breaking things during an update. We’ll also talk about how to actually restore and rollback our snapshots.
I run this blog in my free time, if I helped you out, consider donating a cup of coffee. (:
Leave A Comment