You run a routine upgrade and the desktop vanishes
You run a routine dnf upgrade on a Friday evening. The package manager finishes, you reboot, and your display manager refuses to start. The terminal drops you to a login prompt, but your desktop environment is broken. You spent hours configuring your window manager and dotfiles. Now you need a way to step back in time without reinstalling the operating system.
What is actually happening
Fedora ships with ext4 by default. Ext4 is reliable and fast, but it does not track historical states of your filesystem. Btrfs changes that. It is a copy-on-write filesystem. When you modify a file, Btrfs does not overwrite the existing data on disk. It writes the new version to a fresh block and updates a pointer to the new location. The old data stays exactly where it was. Snapper sits on top of this behavior. It creates read-only subvolumes at specific points in time. When you tell Snapper to roll back, it swaps the active subvolume with a previous one. Your system boots into the exact state it was in when the snapshot was taken.
Think of Btrfs as a document editor that never deletes your previous drafts. Snapper is the version history panel that lets you restore draft three with one click. The filesystem handles the heavy lifting of block allocation and pointer updates. Snapper handles the scheduling, labeling, and cleanup. They work together to give you a safety net that traditional block filesystems cannot provide.
The setup
Anaconda does not offer a one-click Btrfs option on the default storage screen. You need to switch to custom layout. During installation, select Custom for storage configuration. Click Done. The partitioning screen appears. Select your target disk. Click Add. Set the mount point to /. Change the filesystem type to btrfs. Leave the size at the default. Click Add. Click Done. Accept the changes. The installer will create a single Btrfs volume with the default subvolumes.
After the first boot, you need to enable Snapper. Fedora includes the snapper package, but the timeline and transaction hooks are disabled by default. You will edit the root configuration file. Configuration files in /etc/ are user-modified. Files in /usr/lib/ ship with the package. Always edit /etc/. Never edit /usr/lib/.
Here is how to verify the filesystem is actually Btrfs before touching the configuration.
sudo findmnt -n -o FSTYPE /
# Confirms the root filesystem type without parsing long output
# Returns btrfs if the installer applied your custom layout correctly
If the output says ext4, you will need to reinstall with the custom layout. Do not attempt to convert an existing ext4 root to Btrfs while the system is running. The conversion tool exists, but it carries a high risk of data loss on a live root filesystem.
Once Btrfs is confirmed, you will enable automatic snapshots. The configuration lives in /etc/snapper/configs/root. This file controls when snapshots are taken and how long they survive. You will modify two key settings. The first enables timeline snapshots, which capture the system at regular intervals. The second enables pre and post transaction snapshots, which trigger automatically when DNF modifies packages.
Here is how to open the configuration file and apply the necessary changes.
sudo nano /etc/snapper/configs/root
# Opens the root filesystem snapshot configuration in a terminal editor
# Changes here apply only to the root volume, not to separate /home partitions
Locate the TIMELINE_CREATE line. Change the value from no to yes. Locate the NUMBER_LIMIT line. Change it to 10. Locate the NUMBER_LIMIT_IMPORTANT line. Change it to 5. Save the file. These limits prevent your disk from filling up with old snapshots. Btrfs requires free space to perform copy-on-write operations. If the disk reaches 100 percent usage, new writes will fail and the system may become unresponsive.
You also need to enable the DNF plugin so Snapper captures package changes. Fedora ships the snapper-dnf-plugin package. It hooks into the DNF transaction lifecycle. The plugin runs before the transaction starts and after it finishes. It labels the snapshots with the transaction ID so you can correlate them with DNF history.
Here is how to ensure the plugin is installed and active.
sudo dnf install snapper snapper-dnf-plugin
# Installs the snapshot manager and the DNF integration plugin
# The plugin automatically creates pre and post snapshots around every package change
sudo systemctl enable --now snapper-timeline.timer
# Starts the systemd timer that triggers periodic timeline snapshots
# The --now flag applies the change immediately without waiting for a reboot
Run systemctl status snapper-timeline.timer to confirm the timer is active. The timer uses systemd calendar events to run Snapper at configurable intervals. Check the status before restarting any services. Always verify the unit state before making changes.
Verify it worked
You need to confirm that Snapper is actually capturing state. Run a harmless package installation to trigger the DNF plugin. Then check the snapshot list. The plugin will create a pre snapshot before DNF downloads packages and a post snapshot after the transaction commits.
Here is how to trigger a test transaction and inspect the resulting snapshots.
sudo dnf install --refresh curl
# Forces a metadata refresh and installs a small package to trigger the plugin
# The --refresh flag ensures DNF contacts the mirrors before running the transaction
snapper list
# Displays all existing snapshots with their type, number, and creation date
# Look for type pre and post entries that match the curl installation timestamp
The output will show a pre snapshot followed immediately by a post snapshot. The numbers will be sequential. If you see single snapshots instead, the DNF plugin did not fire. Check that the snapper-dnf-plugin package is installed and that no DNF configuration overrides are disabling plugins. You can also check the DNF plugin directory in /etc/dnf/plugins/ to ensure the configuration file is not commented out.
Run btrfs subvolume list / to see how Snapper organizes the storage. Each snapshot appears as a read-only subvolume under /snapshots/. The active root is a writable subvolume. Snapper swaps the mount point during rollback. This is why your system boots into a previous state without touching the underlying blocks.
Verify the snapshot types before proceeding. Trust the package manager. Manual file edits drift, snapshots stay.
Common pitfalls and what the error looks like
Btrfs behaves differently than traditional block filesystems. The biggest issue is space management. Btrfs reports free space differently because it tracks data and metadata separately. You will see df report 90 percent usage while btrfs filesystem usage shows plenty of free space. Always trust btrfs filesystem usage for Btrfs volumes. The df command reads the superblock, which does not account for Btrfs internal allocation pools.
When snapshots consume too much space, you will see write failures. The kernel will log allocation errors.
BTRFS: error (device sda2) in btrfs_free_extent:2078 (errno=-28)
BTRFS: error (device sda2) in btrfs_run_delayed_refs:3045 (errno=-28)
The errno=-28 means ENOSPC. The filesystem ran out of allocatable blocks. Snapper includes a cleanup command that removes old snapshots based on your configured limits. Run it manually if the automatic timer missed a cycle.
sudo snapper cleanup
# Applies the configured limits and deletes snapshots that exceed them
# Frees space immediately so new writes can succeed
sudo btrfs filesystem usage /
# Shows data and metadata usage separately for the root volume
# Confirms that cleanup reclaimed enough space for safe operation
Another common mistake is rolling back the wrong snapshot. Snapper distinguishes between rollback and restore. Rollback replaces the root subvolume and requires a reboot. Restore copies files from a snapshot into the current filesystem without rebooting. Use rollback for system-wide package breaks. Use restore for recovering a single deleted configuration file. If you run snapper rollback on a snapshot that contains a different kernel version, the system will boot into that older kernel. This is expected behavior. The bootloader will update automatically on the next boot.
SELinux denials can also interfere with Snapper operations if you have modified context labels. Check journalctl -t setroubleshoot for one-line summaries before disabling SELinux. Most Snapper issues are space or configuration problems, not security policy blocks.
Run btrfs filesystem usage before you panic. The numbers tell the real story.
When to use this vs alternatives
Filesystem and snapshot strategies depend on your workload and risk tolerance.
Use Btrfs with Snapper when you want automatic, filesystem-level rollbacks that integrate directly with DNF transactions. Use ext4 with Timeshift when you prefer a familiar block filesystem and want a graphical tool that handles /home separately from /. Use ZFS when you need enterprise-grade data integrity, built-in compression, and networked replication. Use Fedora Silverblue when you want an immutable base image that handles rollbacks through rpm-ostree without manual snapshot configuration. Stay on the upstream Workstation with ext4 if you only deviate from the defaults occasionally and do not need frequent rollbacks.