After looking at the very nice videos of Stephen’s Tech Talks, in particular, this one https://www.youtube.com/watch?v=6wUtRkEWBwE, I decided to try to set up Timeshift, Timeshift-autosnap, and grub-btrfs in my Linux Arch installation, where I’m using BTRFS as the filesystem. These three packages allow you to have a timeshift snapshot automatically created each time you update your system; moreover, a new grub entry is automatically generated to boot into a specific snapshot.
The video mentioned above is handy, but unfortunately, some recent changes in Timeshift itself broke the behavior of the two other packages. In this post, I’ll try to show how to fix the problem and go back to a working behavior. I’ll also show an experiment using the snapshots so that, hopefully, it’s clear what’s going on in the presence of such snapshots and how to use them in case you want to revert your system.
First of all, let’s install timeshift and timeshift-autosnap (the latter depends on the former, and they are both available from AUR; I’m using the AUR helper yay here):
|
yay -S timeshift-autosnap |
The first problem is that timeshift has recently changed the strategy for creating snapshots. Instead of creating them in /run/timeshift/backup/timeshift-btrfs/snapshots, it now creates them in /run/timeshift/<PID>/backup/timeshift-btrfs/snapshots, where <PID> is the PID of the Timeshift process. Each time you run Timeshift, the directory will be different, breaking grub-btrfs (which expects to find the snapshots always in the same directory).
Fortunately, there’s a workaround: we add an entry to /etc/fstab in order to mount explicitly the path /run/timeshift/backup/timeshift-btrfs/snapshots:
|
UUID=<UUID> /run/timeshift/backup btrfs defaults,noatime 0 0 |
where, of course, <UUID> has to be replaced with the same UUID of the physical disk partition.
Reboot, and then Timeshift will also put the snapshot in that directory (besides the one with the PID, as mentioned above). You can try to create a snapshot to verify that (this also allows us to use the Timeshift wizard so that we specify to create BTRFS snapshots).
Let’s make sure the mount point is active (and note the unit name)
|
> systemctl list-units -t mount UNIT LOAD ACTIVE SUB DESCRIPTION ... run-timeshift-backup.mount loaded active mounted /run/timeshift/backup ... |
Let’s now install grub-btrfs
|
sudo pacman -S grub-btrfs |
We need to configure that to monitor the Timeshift snapshot directory instead of the default one (/.snapshots).
|
sudo systemctl edit --full grub-btrfs.path |
The file contents
|
[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
|
[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:
|
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 (or, if you have not installed the package update-grub, use the command “grub-mkconfig -o /boot/grub/grub.cfg”) and verify that new grub entries are created for the found snapshots:
|
> sudo update-grub Generating grub configuration file ... Found linux image: /boot/vmlinuz-linux Found initrd image: /boot/intel-ucode.img /boot/amd-ucode.img /boot/initramfs-linux.img Found fallback initrd image(s) in /boot: intel-ucode.img amd-ucode.img initramfs-linux-fallback.img ... Detecting snapshots ... Found snapshot: 2022-06-30 18:07:08 | timeshift-btrfs/snapshots/2022-06-30_18-07-08/@ | ondemand | N/A Found snapshot: 2022-06-30 18:06:17 | timeshift-btrfs/snapshots/2022-06-30_18-06-17/@ | ondemand | N/A Found snapshot: 2022-06-30 16:00:01 | timeshift-btrfs/snapshots/2022-06-30_16-00-01/@ | daily | N/A | Found 3 snapshot(s) Unmount /tmp/grub-btrfs.3u9wTHZNNW .. Success done |
We can also restart the system and prove that we can access the GRUB submenu with the generated entries for the snapshots.
IMPORTANT: If you have several Linux distributions on your computer and you use a multiboot system like the one I blogged about, and this distribution is not the main one, you will have to manually tweak the entry in your main distribution’s GRUB menu. See the linked blog post near the end.
Some experiments
Let’s do some experiments with this configuration.
Here’s the kernel I’m currently running:
|
> uname -a Linux lg-arch 5.18.7-arch1-1 #1 SMP PREEMPT_DYNAMIC Sat, 25 Jun 2022 20:22:01 +0000 x86_64 GNU/Linux |
I’m updating the system (I’m skipping some output below, and you can ignore the “stale mount” errors):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
> yay :: Synchronizing package databases... core 156,5 KiB 855 KiB/s 00:00 [----------------------] 100% extra 1721,1 KiB 3,43 MiB/s 00:00 [----------------------] 100% community 6,7 MiB 4,35 MiB/s 00:02 [----------------------] 100% :: Starting full system upgrade... resolving dependencies... looking for conflicting packages... warning: insufficient columns available for table display Packages (20) alsa-card-profiles-1:0.3.53-2 binutils-2.38-6 docker-compose-2.6.1-1 electron17-17.4.9-1 evolution-3.44.3-1 evolution-data-server-3.44.3-1 geocode-glib-3.26.3-1 glib2-2.72.3-1 glib2-docs-2.72.3-1 gnome-calculator-42.2-1 gnome-control-center-42.3-1 gnome-software-42.3-1 gnome-software-packagekit-plugin-42.3-1 gst-plugin-pipewire-1:0.3.53-2 liblangtag-0.6.4-1 libsoup3-3.0.7-1 linux-5.18.8.arch1-1 pipewire-1:0.3.53-2 wayland-1.21.0-1 xapp-2.2.12-1 Total Download Size: 274,61 MiB Total Installed Size: 627,21 MiB Net Upgrade Size: 0,79 MiB :: Proceed with installation? [Y/n] :: Retrieving packages... ... :: Running pre-transaction hooks... (1/2) Creating Timeshift snapshot before upgrade... Using system disk as snapshot device for creating snapshots in BTRFS mode Mounted '/dev/nvme0n1p13' at '/run/timeshift/2945/backup' Creating new backup...(BTRFS) Saving to device: /dev/nvme0n1p13, mounted at path: /run/timeshift/2945/backup Created directory: /run/timeshift/2945/backup/timeshift-btrfs/snapshots/2022-07-02_15-35-53 Created subvolume snapshot: /run/timeshift/2945/backup/timeshift-btrfs/snapshots/2022-07-02_15-35-53/@ Created control file: /run/timeshift/2945/backup/timeshift-btrfs/snapshots/2022-07-02_15-35-53/info.json BTRFS Snapshot saved successfully (0s) Tagged snapshot '2022-07-02_15-35-53': ondemand ------------------------------------------------------------------------------ Found stale mount for device '/dev/nvme0n1p13' at path '/run/timeshift/2945/backup' Unmounted successfully E: Failed to remove directory Ret=256 Mounted '/dev/nvme0n1p13' at '/run/timeshift/3244/backup' ------------------------------------------------------------------------------ Removing snapshot: 2022-06-30_18-06-17 Deleting subvolume: @ (Id:263) Deleted subvolume: @ (Id:263) Deleted directory: /run/timeshift/3244/backup/timeshift-btrfs/snapshots/2022-06-30_18-06-17 Removed snapshot: 2022-06-30_18-06-17 ------------------------------------------------------------------------------ Found stale mount for device '/dev/nvme0n1p13' at path '/run/timeshift/3244/backup' Unmounted successfully E: Failed to remove directory Ret=256 Generating grub configuration file ... Found linux image: /boot/vmlinuz-linux Found initrd image: /boot/intel-ucode.img /boot/amd-ucode.img /boot/initramfs-linux.img Found fallback initrd image(s) in /boot: intel-ucode.img amd-ucode.img initramfs-linux-fallback.img Adding boot menu entry for UEFI Firmware Settings ... Detecting snapshots ... Found snapshot: 2022-07-02 15:35:53 | timeshift-btrfs/snapshots/2022-07-02_15-35-53/@ | ondemand | {timeshift-autosnap} {created before upgrade} | Found snapshot: 2022-06-30 19:03:38 | timeshift-btrfs/snapshots/2022-06-30_19-03-38/@ | ondemand | {timeshift-autosnap} {created before upgrade} | Found snapshot: 2022-06-30 18:07:08 | timeshift-btrfs/snapshots/2022-06-30_18-07-08/@ | ondemand | {timeshift-autosnap} {created before upgrade} | Found 3 snapshot(s) Unmount /tmp/grub-btrfs.zrVA9quPSF .. Success done ... ==> Generating module dependencies ==> Creating xz-compressed initcpio image: /boot/initramfs-linux-fallback.img |
So it created a snapshot before updating the system (in particular, it installed a new kernel version). Let’s reboot and verify we are running the new kernel (5.18.8 instead of 5.18.7):
|
> uname -a Linux lg-arch 5.18.8-arch1-1 #1 SMP PREEMPT_DYNAMIC Wed, 29 Jun 2022 23:03:08 +0000 x86_64 GNU/Linux |
Let’s reboot and select from GRUB the latest snapshot (remember, the one before applying the upgrade), so timeshift-btrfs/snapshots/2022-07-02_15-35-53 (snapshots are presented in the grub submenu from the most recent to the oldest one). We do that by pretending that the update broke the system (it’s not the case), and we want to get back to a working system before the update we have just performed.
You see that the “Authentication Required” dialog greets us, and in the background, you can see the notification that we “booted into Timeshift Snapshot, please restore the snapshot”:

The password is required because it’s trying to run Timeshift:

In the screenshot, you can see that we are now using the older kernel since we booted in that snapshot where the update has not yet been performed. We have to restore the snapshot manually; otherwise, on the next boot, we’ll get back to the updated system version and not in the snapshot anymore.
So, let’s restore the snapshot:

You see, Timeshift has just created another snapshot ([LIVE]). We now reboot normally (that is, using the main grub entry, NOT the snapshot entries).
Once rebooted normally, we can verify again that we are running the old kernel:
|
> uname -a Linux lg-arch 5.18.7-arch1-1 #1 SMP PREEMPT_DYNAMIC Sat, 25 Jun 2022 20:22:01 +0000 x86_64 GNU/Linux |
Let’s have a look at Timeshift, and we can see the last snapshot is an effective one, not a LIVE one:

Yes, we are now in a system where the update above has never been applied.
Let’s try to rerun the update command (we don’t effectively execute the update, it’s just an experiment):
|
> yay -> /var/lib/pacman/db.lck is present. -> There may be another Pacman instance running. Waiting... |
Why? Because the snapshot had been created automatically by timeshift-autosnap before applying the updates while the package manager was running, its lock is still there.
Let’s remove the lock and try to rerun the update:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
> sudo rm /var/lib/pacman/db.lck > yay :: Synchronizing package databases... core is up to date extra is up to date community is up to date :: Starting full system upgrade... resolving dependencies... looking for conflicting packages... warning: insufficient columns available for table display Packages (20) alsa-card-profiles-1:0.3.53-2 binutils-2.38-6 docker-compose-2.6.1-1 electron17-17.4.9-1 evolution-3.44.3-1 evolution-data-server-3.44.3-1 geocode-glib-3.26.3-1 glib2-2.72.3-1 glib2-docs-2.72.3-1 gnome-calculator-42.2-1 gnome-control-center-42.3-1 gnome-software-42.3-1 gnome-software-packagekit-plugin-42.3-1 gst-plugin-pipewire-1:0.3.53-2 liblangtag-0.6.4-1 libsoup3-3.0.7-1 linux-5.18.8.arch1-1 pipewire-1:0.3.53-2 wayland-1.21.0-1 xapp-2.2.12-1 Total Installed Size: 627,21 MiB Net Upgrade Size: 0,79 MiB |
The output is similar to the one shown above (unless there are even more new updates in the meantime, which might happen in a rolling release), but something is missing:
|
Total Download Size: 274,61 MiB |
Why? Because the downloaded packages in the cache are NOT part of the saved snapshot, they are still present in the current system, even though we restored the snapshot. Why are the cached packages still there, but the lock has been restored with the snapshot? That’s due to the way subvolumes are specified in the /etc/fstab:
|
UUID=... /var/cache btrfs subvol=/@cache,defaults,noatime,compress=zstd:1,ssd 0 0 UUID=... /var/log btrfs subvol=/@log,defaults,noatime,compress=zstd:1,ssd 0 0 |
You see, the cache of downloaded packages and the logs are NOT part of the snapshots, while /var/lib (including the pacman lock) is part of the snapshots.
Let’s now revert the snapshot: we select the one with “Before restoring…”.

Again, we are now in a LIVE situation, and Timeshift tells us again to reboot to make it effective.
Let’s reboot (normally, by using the main grub entry).
We’re back to the updated system, and there’s nothing to update (again, unless new updates have been made available in the meantime):
|
> uname -a Linux lg-arch 5.18.8-arch1-1 #1 SMP PREEMPT_DYNAMIC Wed, 29 Jun 2022 23:03:08 +0000 x86_64 GNU/Linux > yay [sudo] password for bettini: :: Synchronizing package databases... core is up to date extra is up to date community is up to date :: Starting full system upgrade... there is nothing to do :: Searching databases for updates... :: Searching AUR for updates... -> Missing AUR Debug Packages: gnome-terminal-transparency-debug gnome-text-editor-debug there is nothing to do |

If we’re happy with the updated system, we can also remove those two snapshots (remember that grub-btrfs monitors the snapshots so that it will update its grub submenu entries):

I hope you find this blog post helpful, and I hope it complements the wonderful video of Stephen’s Tech Talks mentioned above.