Multibooting with GRUB

4th July, updated with BTRFS installations.

Besides Windows (which I rarely use) on my computers, I have a few Linux distributions. Grub 2 does a good job in booting Windows and Linux, especially thanks to os-prober, in autodetecting other operating systems in other partitions of the same computer. However, there are a few “buts” in this strategy:

  1. Typically, the last installed Linux distribution, say L1, installs its own grub as the main one, and when you upgrade the kernel in another Linux distribution, say L2, you have to boot into L1 and “update-grub” so that the main grub configuration learns about the new kernel of L2. Only then can you boot the new kernel of L2. Of course, you can change the main grub by reordering the EFI entries, e.g., by using the computer’s BIOS, but again that’s far from optimal.
  2. Not all Linux distributions’ grub configurations can boot other Linux distributions. For example, Arch-based distros like EndeavourOS and Manjaro can boot Ubuntu-based distros, but not the other way round (unless you fix a few things in the grub configuration of Ubuntu)! Recently, I started to use also Fedora. I found out that os-prober in Ubuntu and EndeavourOS does not detect the configurations correctly to boot Fedora: recently, Fedora switched to “blscfg” (https://fedoraproject.org/wiki/Changes/BootLoaderSpecByDefault), and as a result, Ubuntu and EndeavourOS create grub configurations that do not consider the changes you made in Fedora’s /etc/default/grub.

That’s why I started to experiment with grub configurations. I still have a “main grub” in a Linux installation, which simply “delegates” to the grub configurations of the other Linux installations. This way, I solve both the two problems above!

In this blog post, I’ll show how I did that. Note that this assumes you use EFI boot.

I have Windows 10, Kubuntu, EndeavourOS, and Fedora on the same computer in this example. I will configure the grub installation of Fedora so that it delegates to Windows, Kubuntu, and EndeavourOS, without relying on os-prober.

This is the disk layout of my computer so that you understand the numbers in the grub configuration that I’ll show later (I omit other partitions like Windows recovery).

The key point is modifying the file /etc/grub.d/40_custom. I guess you already know that you should not modify directly grub.cfg, because a system update or a grub update (e.g., “update-grub”) will overwrite that file.

The file /etc/grub.d/40_custom already comes with some contents that must be left as they are: you add your lines after the existing ones. For example, in Fedora, you have:

We will use the option configfile of grub configuration (see https://www.gnu.org/software/grub/manual/grub/grub.html#configfile): “Load file as a configuration file. If file defines any menu entries, then show a menu containing them immediately.” The Arch wiki also explains it well:

If the other distribution has already a valid /boot folder with installed GRUB, grub.cfg, kernel and initramfs, GRUB can be instructed to load these other grub.cfg files on-the-fly during boot.

The idea is to put in /etc/grub.d/40_custom an entry for each Linux distribution, pointing to the grub.cfg of that distribution, after setting the root partition. Thus, the path to the grub.cfg must be intended as an absolute path in that partition. If you look at the partition numbers above, these are the two entries for booting EndeavourOS and Kubuntu:

NOTE: the “rmmod tpm” is required to avoid TPM errors when booting those systems (“Unknown TPM error”, “you need to load the kernel first”). It happened on my Dell XPS 13, for example. Adding that line (i.e., not loading the module “tpm”) solved the problem.

Remember that the path assumes that the /boot directory is not mounted on a separate partition. If instead, that’s the case, you probably have to remove “/boot”, but I haven’t tried that.

Concerning the entry for Windows, here it is:

In this entry, the root must correspond to the EFI partition, NOT to the partition of Windows.

Save the file and regenerate the grub configuration. In other Linux distributions, it would be a matter of running “update-grub,” but in Fedora, it is:

Now reboot, and you should see the grub menu of Fedora and then, at the bottom, the entries for EndeavourOS, Kubuntu, and Windows. Choosing “EndeavourOS” or “Kubuntu” will NOT boot directly in these systems: it will show the grub menu of “EndeavourOS” or “Kubuntu.”

If you upgrade the kernel on one of these two systems, their grub configuration will be correctly updated. There’s no need to boot into Fedora to update its grub configuration 🙂

If you want to configure the grub in another Linux distribution, please remember that Fedora stores the grub.cfg in /boot/grub2 instead of /boot/grub, so you should write the entry for Fedora with the right path. However, if you plan to boot Fedora with this mechanism, you should disable “blscfg” in the Fedora grub configuration, or you will not be able to boot Fedora (errors “increment.mod” and “blscfg.mod” not found).

Now that we verified that it works, we can remove the entries generated by os-prober. In /etc/default/grub add the line:

and regenerate the grub configuration.

If you want grub to remember the last choice, you can look at this post.

On a side note, due to the way Fedora uses grub (https://fedoraproject.org/wiki/Changes/HiddenGrubMenu), without os-prober, you will not see the grub menu unless you press ESC. After the timeout, it will simply boot on the default entry. To avoid that and see the grub menu, just run:

And the grub menu will get back as usual.

Then, you can also remove os-prober in the other Linux installations, since that is useless now.

These were the original grub menus of Fedora and EndeavourOS, before applying the modifications described in this post:

Pretty crowded!

And this is the result after the procedure described in this post (note that from the Fedora grub menu you select EndeavourOS to land its grub menu and Kubuntu to land its grub menu):

Much better! 🙂

If you need to boot an installation in a BTRFS filesystem (which includes also the /boot directory and the grub.cfg), things are slightly more complex. In fact, BTRFS installations are typically based on subvolumes. The root subvolume is typically denoted by the label “@”. This must be taken into consideration when creating the menu entry.

For example, I’ve also installed Arch on my computer using BTRFS, and the root subvolume is denoted by “@”. The menu entry is as follows:

Note the presence of “/@” in the configfile specification.

That’s not all. If the GRUB configuration specified in configfile has submenus, for example, automatically generated by grub-btrfs, you also must define the prefix variable appropriately (in fact, grub-btrfs generates entries relying on such a variable):

 

10 thoughts on “Multibooting with GRUB

  1. Pingback: Testing the new Fedora 36 | Lorenzo Bettini

  2. Pingback: Timeshift and grub-btrfs in Linux Arch | Lorenzo Bettini

  3. Pingback: My notes on the Grub incident in Linux Arch | Lorenzo Bettini

  4. Pingback: Installing Ubuntu Linux on an Acer Aspire Vero | Lorenzo Bettini

  5. Yann

    Hi Lorenzo,
    Thank you for this post, it helped me.
    I have Fedora as my main OS (this is the main GRUB) and Manjaro is located on another disk. On Manjaro, i use BTRFS as filesystem and btrfs-grub to populate some menu-entries in order to be able to boot on any snapshot.

    Well, i didn’t use the prefix variable in the file /etc/grub.d/40_custom
    I directly put :
    menuentry “Manjaro” {
    insmod gzio
    insmod part_gpt
    insmod btrfs
    set root=’hd1,gpt6′
    configfile “/@/boot/grub/grub.cfg”
    }

    I can boot on my Manjaro OS from Fedora. (I do not see any “prefix variable” in my grub-btrfs.cfg though).

    Then, i have an issue i can’t resolve for now. When i am in Manjaro grub menu, i can’t do back to Fedora grub menu. Indeed, when i press ESC key, my computer is stuck, the only way is to do a hard reset….

    Yet on the archwiki https://wiki.archlinux.org/title/GRUB#GNU/Linux
    They say : “When choosing this entry, GRUB loads the grub.cfg file from the other volume and displays that menu. Any environment variable changes made by the commands in file will not be preserved after configfile returns. Press Esc to return to the first GRUB menu.”

    So it should work…do you have any idea ?
    Thanks you
    Regards

    Reply
    1. Lorenzo Bettini Post author

      Hi
      I remember I had the same problem as well: when pressing ESC, things did not work as expected.
      If I remember correctly, I had this problem when the main configuration was Fedora, which I don’t use anymore.
      I did not investigate further because it’s just a matter of rebooting.

      Reply
  6. riccardo

    Hi Lorenzo
    Great post, learnt a lot…

    One question, you use

    sudo grub2-mkconfig -o /boot/grub2/grub.cfg

    to update the configuration, and I did the same… everything works, but I remember I read somewherem this should be used on UEFI-based machines

    sudo grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg

    I see /boot/efi/EFI/redhat/grub.cfg in my PC is quite simple, and the last statement is indeed

    configfile $prefix/grub.cfg

    and $prefix being resolved to /boot/grub2/grub.cfg, so everything works as expected, but just curious if this would work even if I use the “suggested” command, i.e. grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg

    Reply
    1. Lorenzo Bettini Post author

      IIRC, the second method you mention is the old one, which can still be found on old articles. In fact, as you noted, that file simply refers to the new one.

      Reply
  7. Pingback: LG GRAM 16 (16Z90P): Adding a second SSD | Lorenzo Bettini

  8. Pingback: Dell OptiPlex 5040 MiniTower: upgrading SSD | Lorenzo Bettini

Leave a Reply to Lorenzo BettiniCancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.