> **Key improvement over Fedora 42:** libdnf5 integration means snapshots are created automatically whether you install packages via `dnf`, GNOME Software, or KDE Discover. ## Partitions and Subvolumes Layout | Partition | Size | Filesystem | Mount Point | | ----------- | --------- | ---------- | ----------- | | `/dev/vda1` | 1 GiB | vfat | `/boot/efi` | | `/dev/vda2` | Remaining | btrfs | (top-level) | > No separate `/boot` partition — kernel lives inside Btrfs root so rollbacks also roll back the kernel. > No swap partition — Fedora uses SwapOnZRAM automatically. ### Btrfs Subvolumes | Name | Mount Point | Purpose | | ------------- | --------------------- | ---------------------------------------------- | | `root` | `/` | Core system files (snapshot-enabled) | | `home` | `/home` | User data, isolated from system rollbacks | | `opt` | `/opt` | Third-party software | | `cache` | `/var/cache` | Package cache (excluded from snapshots) | | `log` | `/var/log` | Preserved across rollbacks for diagnostics | | `spool` | `/var/spool` | Transient data (excluded) | | `tmp` | `/var/tmp` | Temporary files (excluded) | | `containers` | `/var/lib/containers` | Container data (large and frequently changing) | | `flatpak` | `/var/lib/flatpak` | Prevents snapshot bloat from Flatpak apps | | `gdm` | `/var/lib/gdm` | GNOME login data (see note below) | | `libvirt` | `/var/lib/libvirt` | VM data, isolated from rollbacks | > **Desktop environment variants for the display manager subvolume:** > - KDE Plasma → `/var/lib/plasmalogin` (name: `plasmalogin`) > - XFCE → `/var/lib/lightdm` (`lightdm`) and `/var/lib/lightdm-data` (`lightdm-data`) ## Post-Installation Configuration ```bash # Verify filesystem and layout sudo btrfs filesystem show / lsblk -p /dev/vda sudo btrfs subvolume list / # Enable Btrfs compression on all subvolumes (not set with custom layout) sudo sed -i.bkp '/ btrfs / s/subvol=[^ ,]*/&,compress=zstd:1/' /etc/fstab # Reboot to apply new mount options reboot # Optional: recompress existing data after reboot sudo btrfs filesystem defragment -r -v -czstd / sudo btrfs filesystem defragment -r -v -czstd /home # Update system sudo dnf update -y && reboot ``` ## Set Up Snapper, grub-btrfs, and Btrfs Assistant Fedora 44 uses an automated install script from the [SysGuides GitHub repo](https://github.com/SysGuides/sysguides-snapper-fedora): ```bash sudo dnf install git -y git clone https://github.com/SysGuides/sysguides-snapper-fedora cd sysguides-snapper-fedora chmod +x install.sh ./install.sh ``` The script installs and configures: - **Snapper** — automatic pre/post transaction snapshots - **grub-btrfs** — boot snapshots directly from GRUB menu - **Btrfs Assistant** — graphical snapshot management - Timeline and cleanup policies - DNF5 integration (works with `dnf`, GNOME Software, and KDE Discover) ```bash # Verify Snapper configs after install snapper ls # root snapper -c home ls # home ``` ## Snapshot Management ```bash # List snapshots snapper ls # root snapper -c home ls # home # Delete a range of snapshots sudo snapper delete 10-50 # Check actual disk usage of snapshots sudo btrfs filesystem du -s --human-readable /.snapshots/*/snapshot ``` ## Rollback (Btrfs Assistant GUI) 1. Boot into a snapshot from the GRUB **Fedora Linux snapshots** submenu. 2. Open **Btrfs Assistant**. 3. Go to **Snapper** → **Browse/Restore** tab. 4. Set **Select target** to `root`. 5. Choose the desired snapshot and click **Restore** → **Yes**. 6. Reboot — root subvolume is restored. ## Adding Subvolumes to a Default Fedora 44 Install If Fedora 44 was installed using the default automatic disk layout, the installer only creates `root` and `home` subvolumes. Follow these steps to add the remaining subvolumes post-installation. > [!warning] Boot from a Fedora Live USB > **Do not perform the data migration steps (Step 3) while booted into the installed system.** Several directories are actively in use by the running OS: > - `/var/log` — continuously written to by journald and other services > - `/var/lib/gdm` — held open by the GDM display manager during a GNOME session > - `/var/spool`, `/var/tmp` — may have active files > > Boot from a **Fedora Live USB** and mount the installed system's partition manually before proceeding with Step 3 onwards. Steps 1 and 2 (creating the subvolumes) can technically be done live, but it's simplest to do everything from the live environment in one pass. > > **Live environment workflow:** Boot the live USB → open a terminal → mount your Btrfs partition with `subvolid=5` → create subvolumes → migrate data → update `/etc/fstab` on the installed system → reboot into the installed OS. ### 1. Find Your Btrfs Partition and UUID From the live environment, run: ```bash lsblk -f ``` From the output, identify: - The **raw partition** (e.g. `/dev/vda2`, `/dev/nvme0n1p3`) — `TYPE` will be `part` - Whether LUKS is in use — `FSTYPE` will be `crypto_LUKS` on the partition, with a `luks-<UUID>` child device underneath it - The **Btrfs UUID** — shown in the `UUID` column on the Btrfs line (the child mapper device if LUKS, or directly on the partition if not) > Do **not** use `cat /etc/fstab` here — in the live environment that reads the live system's fstab, not the installed system's. The UUID must be read from `lsblk -f` output at this stage. **No LUKS:** your device is the raw partition (e.g. `/dev/vda2`). Use this in all mount commands below. **With LUKS:** your raw partition holds the LUKS container. The decrypted device will be at `/dev/mapper/luks-<partition-UUID>` once unlocked (or whatever name you choose in `cryptsetup open`). Use the mapper path in all mount commands below. The Btrfs filesystem UUID (from `lsblk -f`) is what goes into the fstab entries in Step 5 — it is always the UUID of the decrypted Btrfs content, not the LUKS partition UUID. ### 2. Mount the Installed System Set a variable for your device to avoid repeating it throughout the steps: ```bash # No LUKS — use the raw partition directly: DEVICE=/dev/vda2 # With LUKS — unlock the container first, then point to the mapper device: sudo cryptsetup open /dev/vda2 btrfs-luks DEVICE=/dev/mapper/btrfs-luks ``` Now mount the installed root subvolume (to access existing data) and the Btrfs top-level (to create new subvolumes): ```bash # Mount the installed root subvolume sudo mkdir -p /mnt/sysroot sudo mount -o subvol=root $DEVICE /mnt/sysroot # Mount the Btrfs top-level to create and populate subvolumes sudo mkdir -p /mnt/btrfs sudo mount -o subvolid=5 $DEVICE /mnt/btrfs ``` ### 3. Create the Subvolumes ```bash sudo btrfs subvolume create /mnt/btrfs/opt sudo btrfs subvolume create /mnt/btrfs/cache sudo btrfs subvolume create /mnt/btrfs/log sudo btrfs subvolume create /mnt/btrfs/spool sudo btrfs subvolume create /mnt/btrfs/tmp sudo btrfs subvolume create /mnt/btrfs/containers sudo btrfs subvolume create /mnt/btrfs/flatpak sudo btrfs subvolume create /mnt/btrfs/gdm sudo btrfs subvolume create /mnt/btrfs/libvirt ``` ### 4. Migrate Existing Data Copy existing data from the installed root into each new subvolume, then remove the original directory and recreate it as an empty mount point. All paths go through `/mnt/sysroot` (the installed system) and `/mnt/btrfs` (the new subvolumes). ```bash # /var/log sudo cp -arv /mnt/sysroot/var/log/. /mnt/btrfs/log/ sudo rm -rfv /mnt/sysroot/var/log && sudo mkdir -v /mnt/sysroot/var/log # /var/cache sudo cp -arv /mnt/sysroot/var/cache/. /mnt/btrfs/cache/ sudo rm -rfv /mnt/sysroot/var/cache && sudo mkdir -v /mnt/sysroot/var/cache # /var/spool sudo cp -arv /mnt/sysroot/var/spool/. /mnt/btrfs/spool/ sudo rm -rfv /mnt/sysroot/var/spool && sudo mkdir -v /mnt/sysroot/var/spool # /var/tmp sudo cp -arv /mnt/sysroot/var/tmp/. /mnt/btrfs/tmp/ sudo rm -rfv /mnt/sysroot/var/tmp && sudo mkdir -v /mnt/sysroot/var/tmp # /opt sudo cp -arv /mnt/sysroot/opt/. /mnt/btrfs/opt/ sudo rm -rfv /mnt/sysroot/opt && sudo mkdir -v /mnt/sysroot/opt # /var/lib/gdm sudo cp -arv /mnt/sysroot/var/lib/gdm/. /mnt/btrfs/gdm/ sudo rm -rfv /mnt/sysroot/var/lib/gdm && sudo mkdir -v /mnt/sysroot/var/lib/gdm # /var/lib/flatpak sudo cp -arv /mnt/sysroot/var/lib/flatpak/. /mnt/btrfs/flatpak/ sudo rm -rfv /mnt/sysroot/var/lib/flatpak && sudo mkdir -p /mnt/sysroot/var/lib/flatpak # /var/lib/containers (likely empty on a fresh install) sudo mkdir -p /mnt/sysroot/var/lib/containers # /var/lib/libvirt (likely empty on a fresh install) sudo mkdir -p /mnt/sysroot/var/lib/libvirt ``` ### 5. Update /etc/fstab Edit the **installed system's** fstab — not the live environment's: ```bash sudo nano /mnt/sysroot/etc/fstab ``` Add the following entries. Replace `<UUID>` with the Btrfs UUID from Step 1. Match the mount options already present for `root` and `home` (typically `compress=zstd:1`): ``` UUID=<UUID> /opt btrfs subvol=opt,compress=zstd:1 0 0 UUID=<UUID> /var/cache btrfs subvol=cache,compress=zstd:1 0 0 UUID=<UUID> /var/log btrfs subvol=log,compress=zstd:1 0 0 UUID=<UUID> /var/spool btrfs subvol=spool,compress=zstd:1 0 0 UUID=<UUID> /var/tmp btrfs subvol=tmp,compress=zstd:1 0 0 UUID=<UUID> /var/lib/containers btrfs subvol=containers,compress=zstd:1 0 0 UUID=<UUID> /var/lib/flatpak btrfs subvol=flatpak,compress=zstd:1 0 0 UUID=<UUID> /var/lib/gdm btrfs subvol=gdm,compress=zstd:1 0 0 UUID=<UUID> /var/lib/libvirt btrfs subvol=libvirt,compress=zstd:1 0 0 ``` ### 6. Unmount and Reboot ```bash sudo umount /mnt/btrfs sudo umount /mnt/sysroot sudo reboot ``` ### 7. Restore SELinux Contexts and Verify After booting into the installed system: ```bash sudo restorecon -RFv /opt sudo restorecon -RFv /var/cache /var/log /var/spool /var/tmp sudo restorecon -RFv /var/lib/containers /var/lib/flatpak /var/lib/gdm /var/lib/libvirt # Confirm all subvolumes are mounted correctly sudo btrfs subvolume list / lsblk -p /dev/vda ``` --- ## References - [Snapper (ArchWiki)](https://wiki.archlinux.org/title/Snapper) - [Btrfs Assistant](https://gitlab.com/btrfs-assistant/btrfs-assistant) - [sysguides-snapper-fedora (GitHub)](https://github.com/SysGuides/sysguides-snapper-fedora)