Ubuntu 20.04 with software RAID1 and UEFI

Software RAID has been relatively simple to use for a long time as it mostly just works. Things are less straightforward when using UEFI as you need an EFI partition that can’t be on a software RAID.

Well, you could put the EFI partition in a software RAID if you put the metadata at the end of the partition. That way the beginning of the partition would be the same as without RAID. The issue with this is if something external writes to the partition as you can’t be sure which drive has the correct state. That’s why we’re going to use another approach.

Instead of putting it on a RAID, we’ll install Ubuntu as usual, and then copy the EFI partition over to the second drive. Then we’ll make sure that either of the two hard drives can go away without affecting the ability to run or boot. We’re going to use the efibootmgr tool to make sure both drives are in the boot-list.

I’ll also add some info on how to handle drive replacements and updates affecting EFI.

So let’s get on with it.

Installing Ubuntu 20.04 with RAID

First, let’s install Ubuntu and get a step closer to our goal of RAID1. When you get to the storage configuration screen, select “Custom storage layout” and follow these steps:

  1. Reformat both drives if they’re not empty. 
  2. Mark both drives as a boot device. Doing so will create an ESP(EFI system partition) on both drives.
  3. Add an unformatted GPT partition to both drives. They need to have the same size. We’re going to use those partitions for the RAID that contains the OS.
  4. Create a software RAID(md) by selecting the two partitions you just created for the OS.
  5. Congratulations, you now have a new RAID device. Let’s add at least one GPT partition to it.
  6. Optional: If you want the ability to swap, create a swap partition on the RAID device. Set the size to the same as your RAM, or half if you have 64 GB or more RAM.
  7. Create a partition for Ubuntu on the RAID device. You can use the remaining space if you want to. Format it as ext4 and mount it at /.

When you have followed the steps above, this is what it will look like:

What partitioning of disks when installing Ubuntu on software raid might look like.
What partitioning of disks when installing Ubuntu on software raid might look like. Note that this is without swap, you will have a partition more if you opted to use swap.

Save the changes and continue along with the installation.

Avoid slow boot

Remove btrfs-progs to speed up the boot process in case of a drive failure:

$ sudo apt purge btrfs-progs

Make sure both drives are bootable

Congratulations, you now have a redundant setup! You can check the status of the RAID by running the following:

$ sudo mdadm --detail /dev/md0

If the RAID has completed syncing you’ll be able to crash or remove one drive and run off of the remaining hard drive.

However, while this is fine, there is one potential lurking issue. If you remove one drive, you might be unable to boot the system. So let’s make sure the ESP is the same on both drives, and that the system will try to boot from either of the hard drives and not just one. Ubuntu’s installer should have taken care of this for you, but feel free to check.

First, show the partition UUIDs:

$ ls -la /dev/disk/by-partuuid/

total 0
drwxr-xr-x 2 root root 120 Oct 1 22:43 .
drwxr-xr-x 7 root root 140 Oct 1 22:43 ..
lrwxrwxrwx 1 root root 10 Oct 1 22:43 04d1fc28-4747-497b-9732-75f691a7ae7a -> ../../sdb2
lrwxrwxrwx 1 root root 10 Oct 1 22:43 0577b983-cf0a-4516-a3ab-92e19c3e9afe -> ../../sda1
lrwxrwxrwx 1 root root 10 Oct 1 22:43 97eecdcd-8ec3-4b8e-a6d9-1114d3baa75b -> ../../sda2
lrwxrwxrwx 1 root root 10 Oct 1 22:43 98d444f0-df7f-41d9-8461-95ca566bd3a7 -> ../../sdb1

Take note of the UUIDs belonging to the first partition on both drives. In this case, it’s the ones starting with 0577b983(sda1) and 98d444f0(sdb1).

Next, check what drive you’re currently using:

$ mount | grep boot

/dev/sdb1 on /boot/efi type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro)

As you can see, we’re currently using sdb1, so that’s working. Let’s copy it over to sda1:

$ sudo dd if=/dev/sdb1 of=/dev/sda1

Now we have a working ESP on both drives, so the next step is to make sure both ESP exists in the boot-list:

$ efibootmgr -v

BootCurrent: 0005
Timeout: 0 seconds
BootOrder: 0001,0005,0006,0000,0002,0003,0004
Boot0000* UiApp FvVol(7cb8bdc9-f8eb-4f34-aaea-3ee4af6516a1)/FvFile(462caa21-7614-4503-836e-8ab6f4662331)
Boot0001* UEFI VBOX CD-ROM VB2-01700376 PciRoot(0x0)/Pci(0x1,0x1)/Ata(1,0,0)N…..YM….R,Y.
Boot0002* UEFI VBOX HARDDISK VBf2f22214-890bfc65 PciRoot(0x0)/Pci(0xd,0x0)/Sata(0,65535,0)N…..YM….R,Y.
Boot0003* UEFI VBOX HARDDISK VB7e066f6b-0343c49a PciRoot(0x0)/Pci(0xd,0x0)/Sata(1,65535,0)N…..YM….R,Y.
Boot0004* EFI Internal Shell FvVol(7cb8bdc9-f8eb-4f34-aaea-3ee4af6516a1)/FvFile(7c04a583-9e3e-4f1c-ad65-e05268d0b4d1)
Boot0005* ubuntu HD(1,GPT,98d444f0-df7f-41d9-8461-95ca566bd3a7,0x800,0x100000)/File(\EFI\ubuntu\shimx64.efi)
Boot0006* ubuntu HD(1,GPT,0577b983-cf0a-4516-a3ab-92e19c3e9afe,0x800,0x100000)/File(\EFI\ubuntu\shimx64.efi)

You should see two entries called Ubuntu. Make sure the UUIDs are the same as the two you took note of earlier.

If an entry is missing, you’ll need to add it.

Example of how to add an entry for the UUID starting with 0577b983(sda1) if it’s missing:

$ sudo efibootmgr --create --disk /dev/sda --part 1 --label "ubuntu" --loader "\EFI\ubuntu\shimx64.efi"

You should now be able to remove any of the two drives and still boot the system.

Adding a fresh drive after a failure

So, a drive has failed, and you’ve replaced it with a new one. How do you set it up?

First, find the new drive:

$ sudo fdisk -l

It’s probably one without any partitions. Make sure you’re using the right drive. In my case, it’s /dev/sdb, so I’ll want to back up the partition table from /dev/sda and write it to /dev/sdb.

Change the source to the existing drive and dest to the new one:

$ source=/dev/sda
$ dest=/dev/sdb

Create a backup in case you mix it up:

$ sudo sgdisk --backup=backup-$(basename $source).sgdisk $source
$ sudo sgdisk --backup=backup-$(basename $dest).sgdisk $dest

Create a replica of the source partition table and then grenerate new UUIDs for the new drive:

$ sudo sgdisk --replicate=$dest $source
$ sudo sgdisk -G $dest

Start syncing the raid, replace the X with the correct partition(it’s 2 for me):

$ sudo mdadm --manage /dev/md0 -a $(echo "$dest"X)

Now, copy over the ESP(replace X with the correct partition, it’s 1 for me):

$ sudo dd if=$(echo "$source"X) of=$(echo "$dest"X)

Then list the current drive UUIDs:

$ ls -la /dev/disk/by-partuuid/

Then show the boot-list:

$ efibootmgr -v

Take note of the BootOrder in case you want to change it.

If any of the ubuntu entries points to a UUID that currently don’t exist, delete it(replace XXXX with the ID form the boot-list):

$ sudo efibootmgr -B -b XXXX

If any of the current UUIDs for partition 1 on the drives don’t exist in the boot-list, add it(replace the X with the drive that is missing):

$ sudo efibootmgr --create --disk /dev/sdX --part 1 --label "ubuntu" --loader "\EFI\ubuntu\shimx64.efi"

Verify that it’s correct:

$ efibootmgr -v

All good? Great! You now have a working RAID again.

Leave a Reply

Your email address will not be published. Required fields are marked *