Before you build a rollback plan around Snapper on Fedora, know that the command most guides end on, snapper rollback, does not work on Fedora’s Btrfs layout. On Fedora 45 it refuses to run. Forced with --ambit classic, it reports success and changes nothing after a reboot, because Fedora boots the root subvolume by name. Snapshots, diffs, per-file restores and booting a snapshot from GRUB all work well. The permanent rollback has to be done differently, and that decision shapes the rest of the setup.
This guide sets up Snapper for the root subvolume, fixes the timers Fedora leaves off, and snapshots every dnf5 transaction automatically. It then adds a snapshot submenu to GRUB with grub-btrfs, including a replacement for the systemd unit that fails on Fedora, and rolls back to a snapshot in a way that survives a reboot. We ran all of it on a Fedora 45 Workstation on a default Btrfs install, with Snapper 0.13.0 and btrfs-progs 7.1, and checked the Fedora 44 packages against its repositories. If you are still on Fedora 44, the upgrade guide gets you to the same starting point.
Check the Btrfs layout first
Everything below assumes the layout the Fedora Workstation installer creates, as covered in the Fedora 45 installation guide. Confirm it before installing anything:
findmnt / -o SOURCE,FSTYPE,OPTIONS
sudo btrfs subvolume list /
sudo btrfs subvolume get-default /
grep -v '^#' /etc/fstab
cat /proc/cmdline
Root is the root subvolume, mounted by name, and the filesystem’s default subvolume is still the top level (ID 5):
SOURCE FSTYPE OPTIONS
/dev/sda3[/root] btrfs rw,relatime,seclabel,compress=zstd:1,ssd,discard=async,space_cache=v2,subvolid=257,subvol=/root
ID 256 gen 422 top level 5 path home
ID 257 gen 541 top level 5 path root
ID 258 gen 225 top level 257 path var/lib/machines
ID 5 (FS_TREE)
UUID=f46983c5-ff8c-462e-b078-a4fcc2b02d5b / btrfs subvol=root,compress=zstd:1 0 0
UUID=c06641b5-30b9-4d29-87bb-3b149b791e4b /boot ext4 defaults 1 2
UUID=4D3A-AF85 /boot/efi vfat umask=0077,shortname=winnt 0 2
UUID=f46983c5-ff8c-462e-b078-a4fcc2b02d5b /home btrfs subvol=home,compress=zstd:1 0 0
Three details matter later. /home is its own subvolume, so root snapshots never touch user data. /var is part of root, so logs and package databases roll back with the system. And /boot is a separate ext4 partition, so kernels and the GRUB config are never inside a snapshot. The kernel command line from /proc/cmdline also names the subvolume, which is the part that defeats snapper rollback:
BOOT_IMAGE=(hd0,gpt2)/vmlinuz-7.2.7-300.fc45.x86_64 root=UUID=f46983c5-ff8c-462e-b078-a4fcc2b02d5b ro rootflags=subvol=root rhgb quiet
Install Snapper and create the root config
Snapper is in the Fedora repositories. Install it, along with full vim for the files edited later (Workstation ships only vi from vim-minimal), and create a config for /:
sudo dnf5 install -y snapper vim-enhanced
sudo snapper -c root create-config /
sudo snapper list-configs
create-config writes /etc/snapper/configs/root and creates a .snapshots subvolume nested inside root (it shows up as ID 259 ... path .snapshots):
Config │ Subvolume
───────┼──────────
root │ /
What it does not do is start the schedule. Check the two timers:
systemctl is-enabled snapper-timeline.timer snapper-cleanup.timer
systemctl is-active snapper-timeline.timer snapper-cleanup.timer
On Fedora 45 the timeline timer is enabled but not running, and the cleanup timer is disabled outright:
enabled
disabled
inactive
inactive
That combination is the one to avoid. After the next reboot the timeline timer starts taking hourly snapshots, and with cleanup disabled nothing ever prunes them. Enable and start both now:
sudo systemctl enable --now snapper-timeline.timer snapper-cleanup.timer
systemctl list-timers 'snapper-*' --no-pager
Cleanup runs 10 minutes after boot and then every hour (OnBootSec=10m, OnUnitActiveSec=1h), and the timeline fires on the hour:
NEXT LEFT LAST PASSED UNIT ACTIVATES
Mon 2026-09-28 23:23:30 EAT 8min - - snapper-cleanup.timer snapper-cleanup.service
Tue 2026-09-29 00:00:00 EAT 44min - - snapper-timeline.timer snapper-timeline.service
The retention policy lives in the config file. These are the values Snapper 0.13 writes on Fedora 45:
sudo grep -E '^(TIMELINE|NUMBER|SPACE|FREE)' /etc/snapper/configs/root
Ten hourly, ten daily, ten monthly and ten yearly timeline snapshots, 50 numbered ones, and a cap of half the filesystem:
SPACE_LIMIT="0.5"
FREE_LIMIT="0.2"
NUMBER_CLEANUP="yes"
NUMBER_MIN_AGE="3600"
NUMBER_LIMIT="50"
NUMBER_LIMIT_IMPORTANT="10"
TIMELINE_CREATE="yes"
TIMELINE_CLEANUP="yes"
TIMELINE_MIN_AGE="3600"
TIMELINE_LIMIT_HOURLY="10"
TIMELINE_LIMIT_DAILY="10"
TIMELINE_LIMIT_WEEKLY="0"
TIMELINE_LIMIT_MONTHLY="10"
TIMELINE_LIMIT_QUARTERLY="0"
TIMELINE_LIMIT_YEARLY="10"
On a laptop with a small SSD we would cut the hourly and daily limits and lower SPACE_LIMIT. On a workstation with room to spare, the defaults are reasonable.
Take snapshots and compare them
A manual snapshot on either side of a change is the basic unit of work. Here the change is a package install plus a hand-edited config file:
sudo snapper -c root create --description "before cowsay"
sudo dnf5 install -y cowsay
echo "PermitRootLogin no" | sudo tee /etc/ssh/sshd_config.d/99-lab.conf
sudo snapper -c root create --description "after cowsay"
sudo snapper -c root list
Snapshot 0 is always the live system:
# │ Type │ Pre # │ Date │ User │ Cleanup │ Description │ Userdata
──┼────────┼───────┼─────────────────────────────────┼──────┼─────────┼───────────────┼─────────
0 │ single │ │ │ root │ │ current │
1 │ single │ │ Mon 28 Sep 2026 11:15:26 PM EAT │ root │ │ before cowsay │
2 │ single │ │ Mon 28 Sep 2026 11:15:30 PM EAT │ root │ │ after cowsay │
status lists every file that differs between two snapshots, 84 lines for this small install. Filtered to the interesting part:
sudo snapper -c root status 1..2 | grep -E '99-lab|bin/cowsay|^.{6} /etc/cowsay$'
A + in the first column means the file is new in the later snapshot. The other flags cover deleted files (-), content changes (c), type changes, and permission, owner, group, xattr and ACL changes:
+..... /etc/cowsay
+..... /etc/ssh/sshd_config.d/99-lab.conf
+..... /usr/bin/cowsay
diff shows the content change for a single file, and undochange puts that one file back the way snapshot 1 had it, without touching anything else and without a reboot:
sudo snapper -c root diff 1..2 /etc/ssh/sshd_config.d/99-lab.conf
sudo snapper -c root undochange 1..2 /etc/ssh/sshd_config.d/99-lab.conf
The file did not exist in snapshot 1, so undoing the change deletes it:
--- /.snapshots/1/snapshot/etc/ssh/sshd_config.d/99-lab.conf 1970-01-01 03:00:00.000000000 +0300
+++ /.snapshots/2/snapshot/etc/ssh/sshd_config.d/99-lab.conf 1970-01-01 03:00:00.000000000 +0300
@@ -0,0 +1 @@
+PermitRootLogin no
create:0 modify:0 delete:1
In practice, undochange on a file or directory is the rollback you will use most often. It fixes a broken config without reverting the rest of the system.
Add snapshots to the GRUB menu with grub-btrfs
grub-btrfs is not in Fedora’s repositories. The kylegospo/grub-btrfs COPR serves both Fedora 45 and 44. The package itself is an old noarch build (grub-btrfs-0.0.git.275.8c61d8ef-1.fc38), which still works:
sudo dnf5 copr enable -y kylegospo/grub-btrfs
sudo dnf5 install -y grub-btrfs
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
The package’s config already points at Fedora’s /boot/grub2 and grub2-mkconfig, so the regeneration finds the snapshots straight away:
Generating grub configuration file ...
Adding boot menu entry for UEFI Firmware Settings ...
Detecting snapshots ...
Found snapshot: 2026-09-28 23:15:30 | root/.snapshots/2/snapshot | single | after cowsay |
Found snapshot: 2026-09-28 23:15:27 | root/.snapshots/1/snapshot | single | before cowsay |
Found 2 snapshot(s)
Unmount /tmp/grub-btrfs.T3oqz3UW51 .. Success
done
Error: “Failed to start grub-btrfs.path: Unit \x2esnapshots.mount not found.”
The package ships grub-btrfs.path to regenerate the menu whenever a snapshot appears. Enabling it on Fedora fails:
Created symlink '/etc/systemd/system/\x2esnapshots.mount.wants/grub-btrfs.path' → '/usr/lib/systemd/system/grub-btrfs.path'.
Unit /usr/lib/systemd/system/grub-btrfs.path is added as a dependency to a non-existent unit \x2esnapshots.mount.
Failed to start grub-btrfs.path: Unit \x2esnapshots.mount not found.
The unit has Requires, After and BindsTo on \x2esnapshots.mount. That fits distributions that mount /.snapshots from fstab. On Fedora, .snapshots is a nested subvolume that appears without any mount, so the mount unit never exists. Disable the shipped unit and write a watcher without the dependency:
sudo systemctl disable grub-btrfs.path
sudo vim /etc/systemd/system/grub-btrfs-watch.path
It watches the same directory and triggers the service the package already installed:
[Unit]
Description=Watch /.snapshots and refresh the GRUB snapshot menu
[Path]
PathModified=/.snapshots
Unit=grub-btrfs.service
[Install]
WantedBy=multi-user.target
Enable it and prove it fires by deleting the generated menu and taking a snapshot:
sudo systemctl daemon-reload
sudo systemctl enable --now grub-btrfs-watch.path
sudo rm -f /boot/grub2/grub-btrfs.cfg
sudo snapper -c root create --description "watch test"
sleep 5
sudo journalctl -u grub-btrfs.service -n 6 --no-pager
The service ran within a second of the snapshot and /boot/grub2/grub-btrfs.cfg was back:
Sep 28 23:16:11 fedora-ws01 bash[4747]: Found 3 snapshot(s)
Sep 28 23:16:11 fedora-ws01 bash[4747]: Unmount /tmp/grub-btrfs.74DtEoBSBF .. Success
Sep 28 23:16:11 fedora-ws01 bash[4864]: done
Sep 28 23:16:11 fedora-ws01 systemd[1]: grub-btrfs.service: Deactivated successfully.
Sep 28 23:16:11 fedora-ws01 systemd[1]: Finished grub-btrfs.service - Regenerate grub-btrfs.cfg.
Sep 28 23:16:11 fedora-ws01 systemd[1]: grub-btrfs.service: Consumed 1.098s CPU time over 1.800s wall clock time, 10M memory peak.
Fedora hides the GRUB menu after a successful boot, so you would never see the new entry. Unhide it:
sudo grub2-editenv - unset menu_auto_hide
The next boot shows the menu for GRUB_TIMEOUT seconds (5 by default; the countdown in this capture is longer because we raised it for testing), with a Fedora Linux snapshots entry at the bottom:

Snapshot every dnf5 transaction
Fedora still ships python3-dnf-plugin-snapper, and it installs cleanly. It is a dnf4 plugin (it lands in /usr/lib/python3.15/site-packages/dnf-plugins/snapper.py), and dnf5 never loads it. With it installed, dnf5 install fortune-mod produced no snapshots at all. The dnf5 way is the actions plugin, which runs commands at transaction hooks:
sudo dnf5 install -y libdnf5-plugin-actions
Two small scripts do the work. The pre script creates a “pre” snapshot and records its number, and the post script creates the matching “post” snapshot. Create the first one:
sudo vim /usr/local/bin/dnf-snapper-pre
Add these lines:
#!/bin/bash
snapper -c root create -t pre -p -c number -d "dnf transaction" > /run/snapper-dnf-pre
Then the post script:
sudo vim /usr/local/bin/dnf-snapper-post
It exits quietly if no pre snapshot was recorded:
#!/bin/bash
[ -s /run/snapper-dnf-pre ] || exit 0
snapper -c root create -t post --pre-number "$(cat /run/snapper-dnf-pre)" -c number -d "dnf transaction"
rm -f /run/snapper-dnf-pre
Make both executable, then register them with the actions plugin:
sudo chmod 755 /usr/local/bin/dnf-snapper-pre /usr/local/bin/dnf-snapper-post
sudo vim /etc/dnf/libdnf5-plugins/actions.d/snapper.actions
One line per hook. The fields are callback:package_filter:direction:options:command, and leaving the middle three empty makes the hook fire on every transaction:
pre_transaction::::/usr/local/bin/dnf-snapper-pre
post_transaction::::/usr/local/bin/dnf-snapper-post
Install and remove a package to test it:
sudo dnf5 install -y sl
sudo dnf5 remove -y sl
sudo snapper -c root list | tail -4
Each transaction leaves a linked pair, with the post snapshot’s Pre # pointing back at its partner, and both marked for number-based cleanup:
4 │ pre │ │ Mon 28 Sep 2026 11:16:55 PM EAT │ root │ number │ dnf transaction │
5 │ post │ 4 │ Mon 28 Sep 2026 11:16:56 PM EAT │ root │ number │ dnf transaction │
6 │ pre │ │ Mon 28 Sep 2026 11:16:56 PM EAT │ root │ number │ dnf transaction │
7 │ post │ 6 │ Mon 28 Sep 2026 11:16:57 PM EAT │ root │ number │ dnf transaction │
sudo snapper -c root status 6..7 then shows what the removal touched: /usr/bin/sl and its build-id link deleted, and the dnf5 state files in /usr/lib/sysimage/libdnf5/ changed.
Why snapper rollback does nothing on Fedora
On openSUSE, snapper rollback makes a writable copy of a snapshot and sets it as the Btrfs default subvolume, and the next boot mounts whatever the default is. On Fedora the first attempt stops immediately:
sudo snapper -c root rollback 1
Snapper cannot work out how the system boots:
Cannot detect ambit since default subvolume is unknown.
This can happen if the system was not set up for rollback.
The ambit can be specified manually using the --ambit option.
Forcing the classic behaviour looks like it worked:
sudo snapper -c root --ambit classic rollback 1
Snapper creates a backup snapshot and a writable copy, and changes the default subvolume:
Ambit is classic.
Creating read-only snapshot of current system. (Snapshot 8.)
Creating read-write snapshot of snapshot 1. (Snapshot 9.)
Setting default subvolume to snapshot 9.
After a reboot, findmnt / still showed subvol=/root, and cowsay, installed after snapshot 1, was still there. Both rootflags=subvol=root on the kernel command line and subvol=root in fstab override the default subvolume, so the new default is never used. If you already ran it, put the default back so it does not surprise you later:
sudo btrfs subvolume set-default 5 /
Snapshots 8 and 9 stay in the list. You can remove them later with sudo snapper -c root delete 8 9 once you no longer need them. The trade-off is clear. Changing fstab and GRUB to follow the default subvolume would make snapper rollback work, but it moves Fedora away from its supported layout. Swapping the root subvolume keeps the layout exactly as Fedora expects it, and that is the method we use.
Roll back by booting a snapshot and swapping the root subvolume
Start by booting the snapshot you want, which is also how you confirm it is the right one. The Fedora Linux snapshots entry lists every Snapper snapshot with its date, type and description. Snapshots 8 and 9 in this list are the leftovers from the classic rollback attempt above:

Picking a snapshot opens a list of the kernels currently in /boot. Because /boot is not part of the snapshot, choose a kernel whose modules exist inside the snapshot, which usually means one that was installed when the snapshot was taken:

The snapshot boots to the normal login screen with rootflags=compress=zstd:1,subvol=root/.snapshots/1/snapshot on the command line. Snapper snapshots are read-only subvolumes, so the root filesystem is read-only even though the mount options say rw. On our test the system came up fine with three failed units, auditd, audit-rules and tuned, most likely because they need to write to the root filesystem. For a quick check that is harmless. Confirm the snapshot is the state you want:
findmnt / -o SOURCE
rpm -q cowsay
This is the system before cowsay was installed:
SOURCE
/dev/sda3[/root/.snapshots/1/snapshot]
package cowsay is not installed
Now make it permanent from inside this session. Mount the top level of the Btrfs filesystem, rename the current root, and create a writable snapshot of snapshot 1 under the name root. The mount point goes under /run because the snapshot’s own root is read-only, and mkdir /mnt/... fails with “Read-only file system”:
DEV=$(findmnt -no SOURCE / | sed 's/\[.*//')
sudo mkdir -p /run/btrfs-top
sudo mount -o subvolid=5 "${DEV}" /run/btrfs-top
sudo mv /run/btrfs-top/root /run/btrfs-top/root.broken
sudo btrfs subvolume snapshot /run/btrfs-top/root.broken/.snapshots/1/snapshot /run/btrfs-top/root
The new root has empty placeholder directories where the nested subvolumes used to be, because Btrfs snapshots do not descend into nested subvolumes. Move the real .snapshots and var/lib/machines subvolumes across, so Snapper keeps its history and systemd-machined keeps its storage. On a default install those are the only two; the list -o line shows every nested subvolume under the old root, and any extra ones (Docker or Podman on the btrfs storage driver, for example) need the same rmdir and mv:
sudo btrfs subvolume list -o /run/btrfs-top/root.broken
sudo rmdir /run/btrfs-top/root/.snapshots /run/btrfs-top/root/var/lib/machines
sudo mv /run/btrfs-top/root.broken/.snapshots /run/btrfs-top/root/.snapshots
sudo mv /run/btrfs-top/root.broken/var/lib/machines /run/btrfs-top/root/var/lib/machines
sudo btrfs subvolume list /run/btrfs-top | grep -vE 'snapshots/[0-9]+/snapshot'
The top level now holds the new root (ID 269) with both nested subvolumes under it, plus the old one as root.broken:
ID 256 gen 544 top level 5 path home
ID 257 gen 637 top level 5 path root.broken
ID 258 gen 225 top level 269 path root/var/lib/machines
ID 259 gen 605 top level 269 path root/.snapshots
ID 269 gen 638 top level 5 path root
Check the kernel before you reboot, because /boot did not roll back. Compare the kernels whose modules exist in the restored root with the kernel GRUB will boot by default:
ls /run/btrfs-top/root/usr/lib/modules
sudo grubby --default-kernel
If the default kernel is not in that list (the bad update you are undoing installed a new kernel), point GRUB at one that is, for example sudo grubby --set-default /boot/vmlinuz-7.2.7-300.fc45.x86_64, and after the reboot run sudo dnf5 install kernel so the rolled-back package database and /boot agree again. Our test rolled back across a change that kept the same kernel, so this step comes from how Fedora’s /boot and BLS entries work, not from a run where it was needed. Then unmount and reboot into the normal default entry, which mounts subvol=root by name and so picks up the new subvolume without any GRUB or fstab change:
sudo umount /run/btrfs-top
sudo systemctl reboot
After the reboot, check that the system runs from the new subvolume, read-write, with Snapper intact:
findmnt / -o SOURCE,OPTIONS
rpm -q cowsay
getenforce
systemctl --failed --no-pager --no-legend
sudo snapper -c root list | tail -2
Subvolume 269 is mounted as root, cowsay is gone, SELinux is enforcing, and no units failed:
SOURCE OPTIONS
/dev/sda3[/root] rw,relatime,seclabel,compress=zstd:1,ssd,discard=async,space_cache=v2,subvolid=269,subvol=/root
package cowsay is not installed
Enforcing
8 │ single │ │ Mon 28 Sep 2026 11:17:26 PM EAT │ root │ number │ rollback backup │ important=yes
9 │ single │ │ Mon 28 Sep 2026 11:17:26 PM EAT │ root │ │ writable copy of #1 │
Anything written under /var after the snapshot, such as container images, VM disks in /var/lib/libvirt/images, databases or system Flatpaks, now lives only in root.broken. Copy what you need out of /run/btrfs-top/root.broken first. Once you are happy, delete the old root. Until then it is your way back:
sudo mkdir -p /run/btrfs-top
sudo mount -o subvolid=5 "$(findmnt -no SOURCE / | sed 's/\[.*//')" /run/btrfs-top
sudo btrfs subvolume delete /run/btrfs-top/root.broken
sudo umount /run/btrfs-top
One consequence caught us out. The rollback reverts everything installed after the snapshot, including the tooling itself. Snapshot 1 predated grub-btrfs and the dnf5 hook, so after the swap rpm -q grub-btrfs libdnf5-plugin-actions reported both as not installed, and grub-btrfs-watch.path was gone. Meanwhile /boot, which is not snapshotted, still held a grub.cfg with the snapshots submenu. Run sudo grub2-mkconfig -o /boot/grub2/grub.cfg after any rollback so the boot menu matches the system again (we also deleted the stale /boot/grub2/grub-btrfs.cfg), and reinstall whatever the snapshot predates. For grub-btrfs that means running dnf5 copr enable again, because the COPR repo file was rolled back as well.
Snapshot /home separately
Because /home is its own subvolume, a root rollback never reverts your documents, which is usually exactly what you want. To protect user data as well, give it a separate config with its own schedule:
sudo snapper -c home create-config /home
sudo snapper -c home create --description "baseline"
sudo snapper list-configs
Both configs are now managed by the same timers:
Config │ Subvolume
───────┼──────────
home │ /home
root │ /
Restore individual files from /home/.snapshots/N/snapshot/ or with snapper -c home undochange. The subvolume swap above is for root. For home, restoring files is almost always the better move than replacing the subvolume.
Fedora 45 vs Fedora 44 packages
The steps are the same on both releases. The Fedora 44 column comes from its repositories, not a test install:
| Package | Fedora 45 | Fedora 44 |
|---|---|---|
| snapper | 0.13.0-4 | 0.13.0-3 |
| btrfs-progs | 7.1 | 7.1 (updates), 6.19.1 at release |
| libdnf5-plugin-actions | 5.4.6.0-2 | 5.4.6.0-1 |
| grub-btrfs (kylegospo COPR) | fedora-45 repo available | fedora-44 repo available |
| btrfs-assistant (GUI) | 2.2-7 | 2.2-6 |
For a graphical view of the same snapshots, btrfs-assistant is in the Fedora repositories on both releases.
Harden the setup before you depend on it
Snapshots are only a rollback plan if they are there, and restorable, on the day you need them. We would check these on any machine running this setup:
- Take a fresh baseline snapshot after installing grub-btrfs and the dnf5 hook, so a rollback to it keeps the tooling.
- Keep
snapper-cleanup.timerenabled and watchsudo btrfs filesystem usage /, because every snapshot pins the blocks that have changed since it was taken. - Before a kernel update, remember that
/bootmoves forward on its own. Keep at least one older kernel installed (Fedora’s defaultinstallonly_limitof 3 does this) so old snapshots still have a matching kernel. - Test the swap procedure once on a VM or a spare machine before you rely on it. It is a handful of
mvcommands, but they are the kind you want to have typed before. - Snapshots are not backups. They live on the same disk. Pair them with an off-machine backup of
/home.
For the other Fedora-side tooling on the same machine, the dnf5 cheat sheet covers the history and rollback commands that complement these snapshots, and the Fedora 45 post-install checklist is where this setup fits in a new install.
A fresh install of Fedora 44 does not create a /var subvolume in my case.
You are right. A stock Fedora Workstation install creates only root and home subvolumes, with /var sitting inside root; a separate var subvolume only shows up with custom partitioning or on the Atomic spins like Silverblue. The catch worth knowing: on that default layout, a snapper rollback of / also reverts /var (journals, container images, databases), since /var rides inside the root subvolume. I have updated the guide to cover both layouts and how to check which one you have.
(my) Fedora 44 does not have snapper-tools and inotify-tools in its standard repos.
You are right about snapper-tools and the article is fixed, thank you. There is no snapper-tools package in Fedora at all, on 44, 43 or 42; that name belongs to openSUSE. The reason inotify-tools looked missing too is that dnf refuses the entire transaction with
No match for argument: snapper-tools, so nothing on that line gets installed. inotify-tools is in the Fedora 44 repository (4.23.9.0-6.fc44) and installs cleanly once the bad name is gone. The command now readssudo dnf install -y snapper inotify-tools.Re-running the whole guide on a Fedora 44 VM to check this turned up two more problems, both now corrected in the article:
–
python3-dnf-plugin-snapperis a dnf4 plugin. Under dnf5 it is never loaded, so transactions ran and not one pre/post snapshot appeared. The article now useslibdnf5-plugin-actionswith two short scripts, which does produce the pre and post pair around every transaction.– The
grub-btrfs.pathunit from the COPR cannot start on Fedora. It carries BindsTo on\x2esnapshots.mount, and Fedora’s snapper creates/.snapshotsas a btrfs subvolume rather than a separate mount, so the unit fails withUnit \x2esnapshots.mount not found. A drop-in cannot fix it, because BindsTo is one of the settings systemd will not let you reset. The article now installs a small path unit of its own that triggers the same service, and it does regenerate the boot menu on every new snapshot.