UPDATED 22/Dec/2022, ChangeLog:
- 22/Dec/2022: added the flag “-czstd” for defragmentation and compression.
- 20/Nov/2022: documented the new version of grub-btrfs and its new grub-btrfsd daemon; the configuration for Timeshift is much simpler, but you have to install another package: inotify-tools.
- 17/Nov/2022: documented that I could also create additional subvolumes and move existing contents from the running system
In this post, I’ll describe the same procedure I described in one of my previous posts but applied to Ubuntu (in particular, Ubuntu Jammy 22.04). I’m not describing an autosnap mechanism when performing package updates in Ubuntu, though you might want to try timeshift-autosnap-apt for that.
If you choose the BTRFS filesystem when you install Ubuntu, you get the two subvolumes “@” for “/” and “@home” for “/home”, which will make Timeshift work since that’s what Timeshift expects to find to take BTRFS snapshots.
However, some adjustments are still worth making to avoid useless data ending in the snapshots and to be able to boot snapshots directly (with the help of grub-btrfs).
Adjust compression
Ubuntu does not mount BTRFS subvolumes with compression. Instead, I prefer to have compression on BTRFS.
To do that, right after the installation, I change /etc/fstab by adding compression and “noatime” to the existing entries for “/” and “/home” (as usual, UUID must be replaced with the UUID of your disk partition):
1 2 |
UUID=... / btrfs defaults,noatime,space_cache=v2,compress=zstd:3,subvol=@ 0 1 UUID=... /home btrfs defaults,noatime,space_cache=v2,compress=zstd:3,subvol=@home 0 2 |
Save the file, reboot, and perform “defragment” so that the existing data gets compressed:
1 |
sudo btrfs fi defragment / -r -czstd |
It’s also best to create /var/lib/portables and /var/lib/machines if not already there
1 2 |
sudo mkdir -p /var/lib/portables sudo mkdir -p /var/lib/machines |
I’m not using these directories, but it looks like systemd creates them automatically as nested subvolumes. Nested subvolumes will force you to do some manual removal after restoring a snapshot and removing old snapshots.
The current situation of subvolumes should be as follows:
1 2 3 |
sudo btrfs su li / ID 256 gen 2342 top level 5 path @ ID 257 gen 2342 top level 5 path @home |
Create additional subvolumes
With the current subvolume layout, things like logs and caches will end up in snapshots, giving you problems when you try to boot a snapshot (which we want to be able to do).
Creating a subvolume for the whole /var directory is not ideal because we lost the contents of essential things like /var/lib in the snapshot, so we could not restore a snapshot correctly. Instead, we create subvolumes to mount /var/log, /var/cache, and /var/tmp.
Since we have to move the existing contents of such directories into the new subvolume, it’s better to operate from a Live ISO.
UPDATE 17/Nov/2022: I also tried to create the new subvolumes and move the existing contents in the running system, following the steps described below. It worked! However, I’d still suggest you do the next steps from a Live ISO because you never know 😉
So, let’s boot a Live ISO (e.g., Ubuntu live installation medium).
Switch to superuser (no password required in the live media):
1 |
sudo su - |
Mount the BTRFS filesystem into /mnt, which should already exist in the live media. We have to mount the partition hosting our existing installation. In my example, it is /dev/sdb10:
1 |
mount /dev/sdb10 /mnt |
You should see the existing subvolumes in the mount directory:
1 2 3 4 |
ls -l /mnt/ total 0 drwxr-xr-x 1 root root 172 Aug 20 12:47 @ drwxr-xr-x 1 root root 14 Oct 18 07:44 @home |
Create the new subvolumes
1 2 3 |
btrfs subvolume create /mnt/@log btrfs subvolume create /mnt/@cache btrfs subvolume create /mnt/@tmp |
Here are the new subvolumes:
1 2 3 4 5 6 7 |
ls -l /mnt/ total 0 drwxr-xr-x 1 root root 172 Aug 20 12:47 @ drwxr-xr-x 1 root root 0 Oct 18 12:16 @cache drwxr-xr-x 1 root root 14 Oct 18 07:44 @home drwxr-xr-x 1 root root 0 Oct 18 12:16 @log drwxr-xr-x 1 root root 0 Oct 18 12:16 @tmp |
Let’s move the contents of /mnt/@/var/log to /mnt/@log and the same for /mnt/@/var/cache into /mnt/@cache
1 2 |
mv /mnt/@/var/cache/* /mnt/@cache/ mv /mnt/@/var/log/* /mnt/@log/ |
The directory /mnt/@/var/tmp/ should be empty, so there’s nothing to move (you may want to check that).
Adjust the fstab of the installed system to point to the renamed subvolumes and mount the new subvolumes as /var/log, /var/cache, and /var/tmp
1 |
nano /mnt/@/etc/fstab |
You will have to use the correct UUID, which is the same as the one for the already mounted volumes (when you copy and paste, make sure you update both the mount point and the subvolume name consistently):
1 2 3 |
UUID=... /var/log btrfs defaults,noatime,space_cache=v2,compress=zstd:3,subvol=@log 0 2 UUID=... /var/cache btrfs defaults,noatime,space_cache=v2,compress=zstd:3,subvol=@cache 0 2 UUID=... /var/tmp btrfs defaults,noatime,space_cache=v2,compress=zstd:3,subvol=@tmp 0 2 |
Remember to double-check everything!
Let’s unmount the partition
1 |
umount /mnt |
and we should be able to reboot the system, hopefully without problems
Install Timeshift
We can install it from the Ubuntu repositories with
1 |
sudo apt install timeshift |
NOTE: since this is not the latest version, Timeshift will always generate snapshots in the same directory, so there’s no need for the additional fixed mount point as in Arch (see my previous post).
Let’s create a new Timeshift snapshot and browse it with the Timeshift toolbar button “Browse”. We can verify that the directories @/var/log, @/var/cache, and @/var/tmp are empty in the snapshot. The same holds for home (but that was already true thanks to the initial subvolume for home).
Configure grub-btrfs
We have to install grub-btrfs from sources because there’s no official package for Ubuntu. However, after installing the dependencies,
1 |
sudo apt install build-essential git |
the installation procedure is straightforward:
1 2 3 4 5 |
mkdir -p ~/git cd ~/git git clone https://github.com/Antynea/grub-btrfs.git cd grub-btrfs sudo make install |
We now need to configure that to monitor the Timeshift snapshot directory instead of the default one (/.snapshots).
Updated version (20 November 2022)
UPDATE 20/Nov/2022: A new version of grub-btrfsd is available only by installing from sources. What follows is based on this new version. At the bottom of the post, there are still the old instructions, but they’re not valid anymore.
If you see an ASCII splash screen installing grub-btrfs from sources, you’re using the latest version.
Now, let’s make sure grub-btrfs can find Timeshift’s snapshots (remember, we’ve just created one). So let’s run update-grub, and we should see in the end something like the following output:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ sudo update-grub Sourcing file `/etc/default/grub' Sourcing file `/etc/default/grub.d/init-select.cfg' Generating grub configuration file ... Found linux image: /boot/vmlinuz-5.19.0-23-generic Found initrd image: /boot/initrd.img-5.19.0-23-generic ... Adding boot menu entry for UEFI Firmware Settings ... Detecting snapshots ... Found snapshot: 2022-11-19 15:08:51 | timeshift-btrfs/snapshots/2022-11-19_15-08-51/@ | ondemand | N/A | Found 1 snapshot(s) Unmount /tmp/grub-btrfs.shzoN5Pcoo .. Success done |
The last lines prove that grub-btrfs can detect snapshots.
Automatically update the grub menu upon snapshot creation or deletion (20 November 2022)
UPDATE 20/Nov/2022: A new version of grub-btrfsd is available only by installing from sources. What follows is based on this new version. At the bottom of the post, there are still the old instructions, but they’re not valid anymore.
Grub-btrfs provides a daemon watching the snapshot directory and updates the grub menu automatically every time a snapshot is created or deleted.
Important: This daemon requires an additional package:
1 |
sudo apt install inotify-tools |
By default, this daemon watches the directory “/.snapshots” (the default directory for Snapper). Since Timeshift uses a different directory, we have to tweak the configuration for the daemon.
Let’s run:
1 |
sudo systemctl edit --full grub-btrfsd |
We must change the line
1 |
ExecStart=/usr/bin/grub-btrfsd --syslog /.snapshots |
into
1 |
ExecStart=/usr/bin/grub-btrfsd --syslog --timeshift-auto |
This is required for Timeshift version 22.06 and later because Timeshift creates a new directory named after their process ID in /run/timeshift every time they are started. Since the PID will be different every time, also the directory will be different. Grub-btrfs provides the command line argument –timeshift-auto to correctly detect the current snapshot directory (In previous versions of grub-btrfs, we had to tweak /etc/fstab to deal with that).
Let’s start the daemon:
1 |
sudo systemctl start grub-btrfsd |
In the journalctl log, we should see something like (where the date and time have been stripped off):
1 2 |
grub-btrfsd[9965]: grub-btrfsd starting up... grub-btrfsd[9989]: Watching /run/timeshift for timeshift to start |
Let’s start Timeshift. In the journalctl log, we should see something like this:
1 2 3 4 |
grub-btrfsd[10307]: detected Timeshift startup, PID is: 10232 grub-btrfsd[10611]: Grub submenu recreated systemd[1]: tmp-grub\x2dbtrfs.e6hSsOzTFf.mount: Deactivated successfully. grub-btrfsd[10612]: Watching /run/timeshift/10232/backup/timeshift-btrfs/snapshots for new snapshots... |
Let’s verify that if we create a new snapshot, grub-btrfs automatically updates the GRUB menu: in a terminal window, run “journalctl -f” to look at the log, then create a new snapshot in Timeshift. In the log, you should see something like the following lines:
1 2 3 4 5 6 7 8 9 |
timeshift-gtk.desktop[10232]: Created directory: /run/timeshift/10232/backup/timeshift-btrfs/snapshots/2022-11-20_17-31-59 grub-btrfsd[10667]: Detected snapshot creation/ deletion, recreating Grub menu timeshift-gtk.desktop[10232]: Created subvolume snapshot: /run/timeshift/10232/backup/timeshift-btrfs/snapshots/2022-11-20_17-31-59/@ timeshift-gtk.desktop[10232]: Created control file: /run/timeshift/10232/backup/timeshift-btrfs/snapshots/2022-11-20_17-31-59/info.json timeshift-gtk.desktop[10232]: BTRFS Snapshot saved successfully (0s) timeshift-gtk.desktop[10232]: Tagged snapshot '2022-11-20_17-31-59': ondemand timeshift-gtk.desktop[10232]: ------------------------------------------------------------------------------ grub-btrfsd[11020]: Grub submenu recreated systemd[1]: tmp-grub\x2dbtrfs.OV56bNx3Ax.mount: Deactivated successfully. |
Similarly, if we delete an existing snapshot, we should see something similar in the log.
Remember that it takes a few seconds for grub-btrfs to recreate the grub menu.
Once we’re sure everything works, we can enable the daemon to always start at boot:
1 |
sudo systemctl enable grub-btrfsd |
The next time we boot, our grub menu will also show a submenu to boot snapshots.
Concerning doing some experiments booting a snapshot and restoring it, please look at my other post.
Old version (with old release 4.11)
UPDATE 20/Nov/2022: These are the older instructions for the previous version of grub-btrfs, where there was no “grub-btrfsd.service” and there was another systemd program (“grub-btrfs.path”).
I leave these instructions here just for “historical reasons”.
1 |
sudo systemctl edit --full grub-btrfs.path |
The file contents
1 2 3 4 5 6 7 8 9 10 11 12 |
[Unit] Description=Monitors for new snapshots DefaultDependencies=no Requires=\x2esnapshots.mount After=\x2esnapshots.mount BindsTo=\x2esnapshots.mount [Path] PathModified=.snapshots [Install] WantedBy=\x2esnapshots.mount |
should be replaced with
1 2 3 4 5 6 7 8 9 10 11 12 |
[Unit] Description=Monitors for new snapshots DefaultDependencies=no Requires=run-timeshift-backup.mount After=run-timeshift-backup.mount BindsTo=run-timeshift-backup.mount [Path] PathModified=/run/timeshift/backup/timeshift-btrfs/snapshots [Install] WantedBy=run-timeshift-backup.mount |
Let’s reload and re-enable the monitoring service:
1 2 |
sudo systemctl reenable grub-btrfs.path sudo systemctl start grub-btrfs.path |
If we have already created a few snapshots, we can run update-grub and verify that new grub entries are created for the found snapshots:
1 2 3 4 5 6 7 8 9 10 11 12 |
sudo update-grub Sourcing file `/etc/default/grub' Sourcing file `/etc/default/grub.d/init-select.cfg' Generating grub configuration file ... Found linux image: /boot/vmlinuz-5.15.0-50-generic Found initrd image: /boot/initrd.img-5.15.0-50-generic ... Detecting snapshots ... Found snapshot: 2022-10-18 14:28:23 | timeshift-btrfs/snapshots/2022-10-18_14-28-23/@ | ondemand | N/A | Found 1 snapshot(s) Unmount /tmp/grub-btrfs.wZwQdRnX7x .. Success done |
Let’s verify that if we create (or delete) a snapshot, grub-btrfs automatically updates the GRUB menu: in a terminal window, run “journalctl -f” to look at the log, then create a new snapshot in Timeshift. In the log, you should see something like the following lines (where the date and time have been stripped off):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
timeshift-gtk.desktop[10195]: App config loaded: /etc/timeshift/timeshift.json timeshift-gtk.desktop[10195]: /dev/sdb10 is mounted at: /run/timeshift/backup, options: rw,relatime,compress=zstd:3,ssd,space_cache=v2,subvolid=5,subvol=/ systemd[1826]: Started Application launched by gsd-media-keys. gsd-media-keys[10256]: Sending 'toggle' message to Guake3 timeshift-gtk.desktop[10195]: Creating new backup...(BTRFS) timeshift-gtk.desktop[10195]: Saving to device: /dev/sdb10, mounted at path: /run/timeshift/backup timeshift-gtk.desktop[10195]: Created directory: /run/timeshift/backup/timeshift-btrfs/snapshots/2022-10-18_14-44-00 timeshift-gtk.desktop[10195]: Created subvolume snapshot: /run/timeshift/backup/timeshift-btrfs/snapshots/2022-10-18_14-44-00/@ timeshift-gtk.desktop[10195]: Created control file: /run/timeshift/backup/timeshift-btrfs/snapshots/2022-10-18_14-44-00/info.json timeshift-gtk.desktop[10195]: BTRFS Snapshot saved successfully (0s) systemd[1]: Starting Regenerate grub-btrfs.cfg... timeshift-gtk.desktop[10195]: Tagged snapshot '2022-10-18_14-44-00': ondemand timeshift-gtk.desktop[10195]: ------------------------------------------------------------------------------ bash[10269]: Detecting snapshots ... bash[10269]: Found snapshot: 2022-10-18 14:44:00 | timeshift-btrfs/snapshots/2022-10-18_14-44-00/@ | ondemand | N/A | bash[10269]: Found snapshot: 2022-10-18 14:28:23 | timeshift-btrfs/snapshots/2022-10-18_14-28-23/@ | ondemand | N/A | bash[10269]: Found 2 snapshot(s) bash[10720]: submenu 'Ubuntu snapshots' { bash[10720]: configfile "${prefix}/grub-btrfs.cfg" bash[10720]: } bash[10269]: Unmount /tmp/grub-btrfs.W93IpgdZoU .. Success systemd[1]: tmp-grub\x2dbtrfs.W93IpgdZoU.mount: Deactivated successfully. systemd[1]: grub-btrfs.service: Deactivated successfully. systemd[1]: Finished Regenerate grub-btrfs.cfg. |
This output tells you that the grub-btrfs monitoring service works!
The next time we boot, our grub menu will also show a submenu to boot snapshots.
Concerning doing some experiments booting a snapshot and restoring it, please look at my other post.