From Fedora Project Wiki
No edit summary
 
(25 intermediate revisions by the same user not shown)
Line 1: Line 1:
==Description==
==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.
These are instructions for creating a reversible dual-boot test station. A dual boot system with two Fedoras of different release versions is created, using btrfs snapshots, and normal `dnf system-upgrade`. It's reversible, meaning it can easily be switched from dual boot back to single boot by deleting the snapshot. It's possible to choose the former or upgraded system. A key element is no (re)partitioning is needed.
==Setup==
==Setup==
* Fedora 36, any live desktop media, has been installed using default Automatic partitioning.
* Fedora 39, any live desktop media, has been installed using default Automatic partitioning.
* Freshen your backups, just in case
* Freshen your backups, just in case
* Consider disabling GRUB menu autohide. How to use grubby to switch back and forth is shown below, but if you're not familiar with how to reveal the hidden GRUB menu, now is a good time to configure always showing it:
`grub2-editenv - unset menu_auto_hide`
==Actions==
==Actions==
* Instruction assume root user, I'm  using `sudo -i` to become root.
====Make snapshots====
====Make snapshots====
# Use the `df` command to find the `/dev` node+partition for your `/` mount point, e.g. $BTRFSPOOL = "/dev/nvme0n1p5"
# Use the `df` command to find the `/dev` node+partition for your `/` mount point, e.g. $BTRFSPOOL = "/dev/dm-0"
# `mount $BTRFSPOOL /mnt`; cd /mnt; ls -l
# `mount $BTRFSPOOL /mnt; cd /mnt; ls -l`
# You should see two directories, `root` and `home`. These are Btrfs subvolumes, which we can snapshot.
# You should see two directories, `root` and `home`. They are Btrfs subvolumes which we can snapshot.
# `btrfs subvolume snapshot root root37` #any name will do
# `btrfs subvolume snapshot root root40` #any name will do
====Create a bootloader entry====
====Create a bootloader entry====
# `cd /boot/loader/entries;ls -l;grubby --default-kernel`
# `cd /boot/loader/entries;ls -l;grubby --default-kernel`
# 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`
# Duplicate the file matching the current default kernel (should be the most recent), e.g. `cp 2a837d3749fd4397a3107adde82b7518-6.7.5-200.fc39.x86_64.conf 2a837d3749fd4397a3107adde82b7518-6.7.5-200.fc39.x86_64-UPGRADE.conf`
# Edit it `nano 64db766697e04179a6d3f7a67c2941e1-5.18.16-200.fc36.x86_64-upgrade.conf`
# Edit it `nano 2a837d3749fd4397a3107adde82b7518-6.7.5-200.fc39.x86_64-UPGRADE.conf`
## Add a recognizable change to the title such as appending UPGRADE to the line.
## On the title line, append `UPGRADE` to the end of the line.
## Find the option `rootflags=subvol=root` changing it to match your snapshot, e.g. `rootflags=subvol=root37`
## Find the option `rootflags=subvol=root` and change it to match the snapshot's name, e.g. `rootflags=subvol=root40`
## Save the file
## Save the file
# 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`
# Make the snapshot upgrade boot entry the default, using the configurations filename, removing the `.conf*` ending, e.g. `grub2-set-default 2a837d3749fd4397a3107adde82b7518-6.7.5-200.fc39.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.
====Modify the rootflags argument in the snapshot's `/etc/kernel/cmdline` file====
This step ensures that a new BLS entry with the correct rootflags argument is created during the upgrade.
# `nano /mnt/root40/etc/kernel/cmdline`
# Find the option `rootflags=subvol=root` and change the name to match the snapshot name, e.g. `rootflags=subvol=root40`
====Reboot====
====Reboot====
* Following boot, confirm `/` is actually using the snapshot you made: `mount | grep btrfs` e.g.
* After you reboot, 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.
`/dev/mapper/luks-10d575f0-f041-48a2-b1ed-b1236e03d5e3 on / type btrfs (rw,noatime,seclabel,compress=zstd:1,ssd,discard=async,space_cache=v2,subvolid=524,subvol=/root40)` you should see `subvol=/root40` or whatever you named the snapshot. If you see `root` you're still working on your original root, and need to figure out what went wrong.
====One bootloader====
====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 adding`exclude=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.
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 adding`exclude=grub2-*` in the test instance's `dnf.conf`. The time to do this is after the first boot into `root40` snapshot, before starting upgrade download.
====Initiate the system upgrade====
====Initiate the system upgrade====
Either of these, just like you normally would:
Either of these, just like you normally would:
Line 30: Line 36:
====Post-upgrade====
====Post-upgrade====
`cat /etc/fedora-release` to confirm the upgrade happened, and it's booted.
`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.
 
`rm /boot/loader/entries/2a837d3749fd4397a3107adde82b7518-6.7.5-200.fc39.x86_64-UPGRADE.conf` this file is no longer needed and confuses grubby, preventing boot back into Fedora 39.
 
==Switching between the two roots==
==Switching between the two roots==
* Either reveal the GRUB hidden menu (Esc or Tab or see the TIP below) to make manual choices, OR
* 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.
* `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-6.7.5-200.fc39.x86_64` to boot Fedora 39
* `grubby --set-default=/boot/vmlinuz-5.19.0-65.fc37.x86_64` to boot Fedora 37
 
`grubby --set-default=/boot/vmlinuz-6.8.0-0.rc5.41.fc40.x86_64` to boot Fedora 40
 
==Limitations==
==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:
===Avoid using `grub2-mkconfig`===
Fortunately, these days the `/boot/grub2/grub.cfg` file is static and doesn't need updating. However, if you do use it, it currently will rewrite the `options` line (boot parameters) in favor of `/etc/kernel/cmdline` on the currently running OS, thus breaking the entries for other OS's. [https://bugzilla.redhat.com/show_bug.cgi?id=2120845 Bug2120845]
===How many Fedoras?===
`/boot` is only 1 GiB by default. This is the limiting factor for how many Fedoras you can have installed at one time. Two is safe. Three is iffy unless:
# configure the test Fedora instances' dnf.conf such `exclude=kernel-*`;
# configure the test Fedora instances' dnf.conf such `exclude=kernel-*`;
# 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.
# consider deleting the "rescue" initramfs and kernel for the test instances, and the "rescue" snippet in `/boot/loader/entries/`, and removing `dracut-config-rescue-059-22.fc40.x86_64` from them so these files aren't recreated.
# `/boot` is on a larger file system, e.g. on a Btrfs subvolume, thus pooling (beyond the scope of discussion)
===Fedoras of the same release version?===
It's possible. The caveat is you need to either keep them both consistently up to date, or never update them, or be prepared for some minor bootloader+kernel related breakage. Since same release versions have the same kernel packages, Fedora A could remove Fedora B's kernel+initramfs files from `/boot`. It's doable but really depends on individual comfort level with such details.
==How to delete the test instance==
==How to delete the test instance==
# Boot the menu entry for the instance you want to keep
# Boot the menu entry for the instance you want to keep
Line 45: Line 61:
# `btrfs subvolume list -t /`  ##find the ID in the left column that matches the subvolume snapshot name you want to delete
# `btrfs subvolume list -t /`  ##find the ID in the left column that matches the subvolume snapshot name you want to delete
# `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.
# `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.
# Check `/boot/loader/entries` for boot loader snippets, and remove the ones you no longer need.
# Check `/boot` for no longer needed files, e.g. `ls -l | grep fc39`, and remove them.
# Check `/boot/loader/entries` for no longer needed files using the same command, and remove them.
==Tips==
==Tips==
===Show/Hide GRUB menu===
===Show/Hide GRUB menu===
Line 51: Line 68:
* Use `grub2-editenv - set menu_auto_hide=1` to conditionally hide the menu at boot.
* Use `grub2-editenv - set menu_auto_hide=1` to conditionally hide the menu at boot.
===Built-in Btrfs command shortcuts===
===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:
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 subvolume snapshot`, `btrfs sub snap`, `btrfs su sn`
* `btrfs filesystem usage`, `btrfs fi us`
* `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.
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.
===What if Windows is already installed?===
I tested on a system with Windows 10 and Fedora 39 on LUKS on Btrfs already installed, so it's technically now triboot. So it's OK.
===What about /etc/fstab?===
Right! There's no step for changing the subvolume in `/etc/fstab`. The `/` entry in fstab is unique in that it's a "remount" operation rather than a first time mount operation, like all the other lines in fstab. Since it's a remount, we can't change the subvolume being mounted, thus the `subvol` mount option is ignored. The reason why `subvol` is on the `/` line at all is a side-effect of how the installer creates `/etc/fstab`. If it's confusing, you can modify it accordingly but it's not necessary.

Latest revision as of 06:05, 22 February 2024

Description

These are instructions for creating a reversible dual-boot test station. A dual boot system with two Fedoras of different release versions is created, using btrfs snapshots, and normal dnf system-upgrade. It's reversible, meaning it can easily be switched from dual boot back to single boot by deleting the snapshot. It's possible to choose the former or upgraded system. A key element is no (re)partitioning is needed.

Setup

  • Fedora 39, any live desktop media, has been installed using default Automatic partitioning.
  • Freshen your backups, just in case
  • Consider disabling GRUB menu autohide. How to use grubby to switch back and forth is shown below, but if you're not familiar with how to reveal the hidden GRUB menu, now is a good time to configure always showing it:

grub2-editenv - unset menu_auto_hide

Actions

  • Instruction assume root user, I'm using sudo -i to become root.

Make snapshots

  1. Use the df command to find the /dev node+partition for your / mount point, e.g. $BTRFSPOOL = "/dev/dm-0"
  2. mount $BTRFSPOOL /mnt; cd /mnt; ls -l
  3. You should see two directories, root and home. They are Btrfs subvolumes which we can snapshot.
  4. btrfs subvolume snapshot root root40 #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 2a837d3749fd4397a3107adde82b7518-6.7.5-200.fc39.x86_64.conf 2a837d3749fd4397a3107adde82b7518-6.7.5-200.fc39.x86_64-UPGRADE.conf
  3. Edit it nano 2a837d3749fd4397a3107adde82b7518-6.7.5-200.fc39.x86_64-UPGRADE.conf
    1. On the title line, append UPGRADE to the end of the line.
    2. Find the option rootflags=subvol=root and change it to match the snapshot's name, e.g. rootflags=subvol=root40
    3. Save the file
  4. Make the snapshot upgrade boot entry the default, using the configurations filename, removing the .conf* ending, e.g. grub2-set-default 2a837d3749fd4397a3107adde82b7518-6.7.5-200.fc39.x86_64-UPGRADE

Modify the rootflags argument in the snapshot's /etc/kernel/cmdline file

This step ensures that a new BLS entry with the correct rootflags argument is created during the upgrade.

  1. nano /mnt/root40/etc/kernel/cmdline
  2. Find the option rootflags=subvol=root and change the name to match the snapshot name, e.g. rootflags=subvol=root40

Reboot

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

/dev/mapper/luks-10d575f0-f041-48a2-b1ed-b1236e03d5e3 on / type btrfs (rw,noatime,seclabel,compress=zstd:1,ssd,discard=async,space_cache=v2,subvolid=524,subvol=/root40) you should see subvol=/root40 or whatever you named the snapshot. If you see root 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 root40 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/2a837d3749fd4397a3107adde82b7518-6.7.5-200.fc39.x86_64-UPGRADE.conf this file is no longer needed and confuses grubby, preventing boot back into Fedora 39.

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-6.7.5-200.fc39.x86_64 to boot Fedora 39

grubby --set-default=/boot/vmlinuz-6.8.0-0.rc5.41.fc40.x86_64 to boot Fedora 40

Limitations

Avoid using grub2-mkconfig

Fortunately, these days the /boot/grub2/grub.cfg file is static and doesn't need updating. However, if you do use it, it currently will rewrite the options line (boot parameters) in favor of /etc/kernel/cmdline on the currently running OS, thus breaking the entries for other OS's. Bug2120845

How many Fedoras?

/boot is only 1 GiB by default. This is the limiting factor for 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-059-22.fc40.x86_64 from them so these files aren't recreated.
  3. /boot is on a larger file system, e.g. on a Btrfs subvolume, thus pooling (beyond the scope of discussion)

Fedoras of the same release version?

It's possible. The caveat is you need to either keep them both consistently up to date, or never update them, or be prepared for some minor bootloader+kernel related breakage. Since same release versions have the same kernel packages, Fedora A could remove Fedora B's kernel+initramfs files from /boot. It's doable but really depends on individual comfort level with such details.

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.
  5. Check /boot for no longer needed files, e.g. ls -l | grep fc39, and remove them.
  6. Check /boot/loader/entries for no longer needed files using the same command, and remove them.

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.

What if Windows is already installed?

I tested on a system with Windows 10 and Fedora 39 on LUKS on Btrfs already installed, so it's technically now triboot. So it's OK.

What about /etc/fstab?

Right! There's no step for changing the subvolume in /etc/fstab. The / entry in fstab is unique in that it's a "remount" operation rather than a first time mount operation, like all the other lines in fstab. Since it's a remount, we can't change the subvolume being mounted, thus the subvol mount option is ignored. The reason why subvol is on the / line at all is a side-effect of how the installer creates /etc/fstab. If it's confusing, you can modify it accordingly but it's not necessary.