How To Boot Multiple Ubuntu Installs With EFI

You may wish to have multiple Ubuntu installations installed on the same system, perhaps to run different versions of the distribution for app compatibility or testing, or perhaps like me you are a little paranoid and you have a “main” Ubuntu install to do general purpose browsing, gaming, and development, and then a “secure” Ubuntu install that you use to access online banking or other sites that require your social security number or control your life savings.

Regardless of the reason, booting multiple Ubuntu installations with EFI is not quite as straightforward as it should be. In the BIOS days if you wanted to isolate multiple installations you could have one main GRUB installation “chainload” another from a different partition.

You would think that in the UEFI days that this would be simpler, but unfortunately a couple aspects of the way the Ubuntu installer was designed complicate things. One is that the installer does not let you select an EFI “bootloader ID” to install with. It just defaults to “ubuntu”. And the second and slightly more insidious is that the path “/EFI/ubuntu” is hard-coded in the grubx64.efi EFI loader so that even if you do install another GRUB EFI loader it will not use the configuration file from that new EFI loader’s directory in the EFI system partition!

So we need to work around these design decisions. This takes a little bit of post-installation work, but the good news is that it is possible to set up how we want.

By the way, this guide was developed using Kubuntu 20.04. The same should work with other Ubuntu distributions or Ubuntu-based systems such as Linux Mint.

Install First Ubuntu System

This guide will use the names “main” and “secure” for the names of the two Ubuntu installations because this was my setup. Substitute as desired for different distribution versions, use cases, etc…

Install the first Ubuntu installation normally (you’ll need to use manual partitioning in order to leave space for the second system unless you are using a separate drive). If you desire to make use of full-partition encryption, you may be interested to see https://www.tangibleabstraction.com/2020/05/21/full-disk-encryption-on-ubuntu-with-manual-partitioning/. I used a separate 1GB /boot partition and then a larger encrypted system partition. But the same idea should work with a single unencrypted root partition.

The installation will install a GRUB EFI loader with the name “ubuntu”. After the installation, we would like to install another GRUB EFI loader for this system with a different name, so that the name does not conflict with the second Ubuntu installation we will be installing later.

Open a terminal and as root run this command to install a new GRUB EFI loader with the name “ubuntu-main”: grub-install --bootloader-id ubuntu-main.

Install Second Ubuntu System

Run the installer again to install the second Ubuntu system. Do not use the same /boot partition for the second system. Either create a separate /boot partition (needed if you will encrypt your full root partition), or just create one new root partition for the new system without a separate /boot partition. Again, after installation completes, open a terminal and as root install a new GRUB EFI loader with the name “ubuntu-secure” (swap out as desired): grub-install --bootloader-id ubuntu-secure.

At this point if you were to reboot you would not even have an option to boot into the first Ubuntu system! This is an unfortunate aspect of the way the Ubuntu installer works.

Now, at this point, take a look at your /boot/efi/EFI directory. There will be subfolders called ubuntu (the default one created by the installer), as well as ubuntu-main and ubuntu-secure.

There is a key file in each of these directories and in fact is the only file that differs among them: grub.cfg. This file is loaded by GRUB and tells GRUB where to find your Ubuntu system’s GRUB configuration file to load.

The first thing I do is to run cp /boot/efi/EFI/ubuntu-main/grub.cfg /boot/efi/EFI/ubuntu. This will replace the grub.cfg written by the latest Ubuntu installer with the one for the “main” system, making the “main” system the default one to boot into. Note that even at this point if you were to use your EFI firmware to select either “ubuntu-main” or “ubuntu-secure” you would still end up booting the same system, because the grubx64.efi loader from each of these locations still loads the same /boot/efi/EFI/ubuntu/grub.cfg configuration file!

Alright, so now we have reset our default system to the “main” one. But we still want to be able to boot into our second system. So we will add a GRUB menu entry to the main GRUB configuration file to allow loading the configuration from the second system.

Add GRUB Entry for Second System

Reboot into the main system to perform these steps.

First take note of which device your EFI partition is on. You can figure this out with the lsblk command. For me, my EFI partition was /dev/nvme0n1p1. In GRUB’s terminology, this is called (hd0,gpt1).

Edit the file /etc/grub.d/40_custom to add a new GRUB menu entry. Add the following lines (change the name and EFI partition as desired):

menuentry 'Ubuntu Secure' {
  configfile (hd0,gpt1)/EFI/ubuntu-secure/grub.cfg
}

Next, edit /etc/default/grub and change the value of GRUB_TIMEOUT_STYLE from hidden to menu, and change GRUB_TIMEOUT to 10 (or a different timeout of your choosing).

Finally, run update-grub to regenerate your main system’s GRUB configuration file.

At this point finally when you boot your system you will boot using EFI and will have a GRUB prompt allowing you to select between your multiple Ubuntu systems.

Fix grub-update Overwriting Entry

The last thing we need to do is fix grub-update from overwriting the /boot/efi/EFI/ubuntu/grub.cfg file. To do this, we can add a script to the /etc/grub.d directory. Running the following commands as root from the secondary Ubuntu system(s) will do what we need:

cat > /etc/grub.d/90_fix_efi_entry <<EOF
#!/bin/sh
cp /boot/efi/EFI/ubuntu-main/grub.cfg /boot/efi/EFI/ubuntu
EOF
chmod +x /etc/grub.d/90_fix_efi_entry

Now, when update-grub runs, it will restore the desired grub.cfg file from our “main” Ubuntu installation.

Troubleshooting

If something goes wrong, the following tricks might help.

First, if you are not getting a GRUB menu, use your EFI firmware boot menu to select the “ubuntu” boot entry, and immediately after selecting it, hold the down arrow key to force the GRUB menu to appear.

Once you get to a GRUB menu, you can use the “e” key to edit a menu entry, or the “c” key to get a command line.

To see your EFI firmware’s recorded boot order you can use the efibootmgr command. You can also add new EFI entries and reorder them with this command as well.

Comments are closed.