From Fedora Project Wiki

Description

Instructions for creating a reversible dual-boot test station. We create a dual boot system with two Fedoras of different release versions, using btrfs snapshots, and otherwise normal system upgrade method. It's reversible, meaning it can easily be switched from dual boot back to single boot by deleting the snapshot.

Setup

  • Fedora 36, any live desktop media, has been installed using default Automatic partitioning.
  • Freshen your backups, just in case

Actions

Make snapshots

  1. Use the df command to find the /dev node+partition for your / mount point, e.g. $BTRFSPOOL = "/dev/nvme0n1p5"
  2. mount $BTRFSPOOL /mnt; cd /mnt; ls -l
  3. You should see two directories, root and home. These are Btrfs subvolumes, which we can snapshot.
  4. btrfs subvolume snapshot root root37 #any name will do

Create a bootloader entry

  1. cd /boot/loader/entries;ls -l;grubby --default-kernel
  2. Duplicate the file matching the current default kernel (should be the most recent), e.g. cp 64db766697e04179a6d3f7a67c2941e1-5.18.16-200.fc36.x86_64.conf 64db766697e04179a6d3f7a67c2941e1-5.18.16-200.fc36.x86_64-upgrade.conf
  3. Edit it nano 64db766697e04179a6d3f7a67c2941e1-5.18.16-200.fc36.x86_64-upgrade.conf
    1. Add a recognizable change to the title such as appending UPGRADE to the line.
    2. Find the option rootflags=subvol=root changing it to match your snapshot, e.g. rootflags=subvol=root37
    3. Save the file
  4. Make it the default, use the filename of the configuration file, removing the .conf* ending, e.g. grub2-set-default 64db766697e04179a6d3f7a67c2941e1-5.18.16-200.fc36.x86_64-upgrade
  • Optional: You could skip all the above by choosing to reveal the hidden GRUB menu, edit the default entry, modifying rootflags=subvol=root to match the name you used for the snapshot, e.g. root37. You'd do this twice: once to boot the root37 snapshot to download the upgrade RPMs; and the following boot after that so it boots root37 thus initiating the offline upgrade.

Reboot

  • Following boot, confirm / is actually using the snapshot you made: mount | grep btrfs e.g.

/dev/vda3 on / type btrfs (rw,relatime,seclabel,compress=zstd:1,space_cache=v2,subvolid=257,subvol=/root) you should see subvol=/root37 or whatever you named the snapshot. If you see root as in this example, oops! You're still working on your original root, and need to figure out what went wrong.

One bootloader

As each Fedora performs updates, it'll occasionally update the bootloaders on /boot/efi. This shouldn't be a problem. But then there's sometimes bugs, so if you don't want to be testing Rawhide bootloaders, consider addingexclude=grub2-* in the test instance's dnf.conf. The time to do this is after the first boot into root37 snapshot, before starting upgrade download.

Initiate the system upgrade

Either of these, just like you normally would:

Post-upgrade

cat /etc/fedora-release to confirm the upgrade happened, and it's booted. rm /boot/loader/entries/64db766697e04179a6d3f7a67c2941e1-5.18.16-200.fc36.x86_64-upgrade.conf this file is no longer needed and confuses grubby, preventing boot back into Fedora 36.

Switching between the two roots

  • Either reveal the GRUB hidden menu (Esc or Tab or see the TIP below) to make manual choices, OR
  • ls -l /boot to see a list of kernels so you can complete the path based on which release version you want to boot, e.g.
  • grubby --set-default=/boot/vmlinuz-5.18.15-200.fc36.x86_64 to boot Fedora 36
  • grubby --set-default=/boot/vmlinuz-5.19.0-65.fc37.x86_64 to boot Fedora 37

Limitations

  • /boot is only 1GiB by default, so this is the limiting factor right now how many Fedoras you can have installed at one time. Two is safe. Three is iffy unless:
  1. configure the test Fedora instances' dnf.conf such exclude=kernel-*;
  2. consider deleting the "rescue" initramfs and kernel for the test instances, and the "rescue" snippet in /boot/loader/entries/, and removing dracut-config-rescue-056-1.fc36.x86_64 from them so these files aren't recreated.

How to delete the test instance

  1. Boot the menu entry for the instance you want to keep
  2. Confirm you've booted it mount | grep btrfs does the subvolume name match what you want to keep?
  3. btrfs subvolume list -t / ##find the ID in the left column that matches the subvolume snapshot name you want to delete
  4. btrfs subvolume delete --subvolid $ID / ##Note that / is the mountpoint for the file system, it's not going to delete your currently running root, it'll delete the ID you specify.

Tips

Show/Hide GRUB menu

  • Use grub2-editenv - unset menu_auto_hide to always show the menu at boot.
  • Use grub2-editenv - set menu_auto_hide=1 to conditionally hide the menu at boot.

Built-in Btrfs command shortcuts

The btrfs command will accept arbitrarily shortened sub-commands so long as they're unambiguous: e.g. these commands are equivalent:

  • btrfs subvolume snapshot, btrfs sub snap, btrfs su sn
  • btrfs filesystem usage, btrfs fi us

No configuration is needed, just try out your own shortened subcommands. If you make it too short, you'll get a hint why it's ambiguous.