Photo of me

Hugo Osvaldo Barrera

A simple boot setup with SecureBoot

I use a pretty simple setup for booting my systems.

That’s all the OS boot process, but some extra steps happen before I see an actual desktop:

From this point on, it’s assumed that the EFI partition is mounted in /efi.

systemd-boot

(reminder: gummiboot is basically the same tool for non-systemd setups)

First of all, copy the bootloader into the EFI partition and register it with the UEFI firmware. Both things can be done with one command:

bootctl install

It will automatically look for signed bundles in EFI/Linux. Since I usually have my primary bundle and a backup one, I manually configure it to prefer the main one:

# The bundle is located in /efi/EFI/Linux/arch.efi:
bootctl set-default arch.efi

That’s all the setup and configuration that systemd-boot will require.

I don’t configure a menu with a timeout since I want the system to boot directly without any prompt. In case I need to boot from the recovery one, the menu can be triggered by spamming Space during startup.

Note that the menu will only allow picking another stub to boot from, but overriding the cmdline is not possible since it’s embedded in the bundle.

sbctl

sbctl is a tool to manage SecureBoot keys and generate signed bundles with the initrd, cmdline and kernel. Keeping all items in a single signed bundle is important, for example: if the cmdline is just a file in the same partition, it can be altered, which would allow easily executing unsigned code.

The UEFI firmware first needs to be configured to use a key that will be generated and managed by sbctl.

Prepare the firmware

Set up the OS

sudo sbctl create-keys
sudo sbctl enroll-key

Generate the bundles

sbctl will read the cmdline from /etc/kernel/cmdline, so make sure to put your current cmdline there. You can do this with:

cat /proc/cmdline | sudo tee /etc/kernel/cmdline

My partitions has the right Partition Type set, so systemd knows what partition to pick up based on its id. This follows the Discoverable Partitions Specification. The Partition Type can be safely updated for partitions, even if currently mounted (since this updates the GPT, not the partition itself).

Then, generate the sbctl bundle:

sbctl bundle --sign /boot/EFI/Linux/arch.efi

The bundle will use your existing initrd and kernel. So each time mkinitcpio generates a new initrd, you need to rebuild the bundle. Fortunately, sbctl includes pacman hooks to re-build the bundle when you update the kernel or the initrd.

The file /etc/kernel/cmdline is read on each re-generation, so don’t delete it. It’s also the file you want to update when you need to make changes to your cmdline.

Finally, you should also sign the bootloader itself:

# This is the entry explicitly in the UEFI.
# The entry MAY be deleted during firmware updates.
sbctl sign --save /efi/EFI/systemd/systemd-bootx64.efi

# This is default fallback in case there are no entries in the UEFI.
# If you dualboot, some aggressive OSs may overwrite it:
sbctl sign --save /efi/EFI/BOOT/BOOTX64.EFI

Turning on SecureBoot

Reboot and cleanup

You should be able to reboot with SecureBoot turned on. The amount of moving parts in the whole boot process are extremely few, and it’s also very low-maintenance.

I’d recommend also removing all other unnecessary boot entries from the firmware using:

sudo efibootmgr --delete-bootnum  --bootnum 00XX

If you’re unsure which one you should leave, delete all of them and re-run bootctl install afterwards.

Breakage recovery

This setup is unlikely to break by itself – but as with any Arch setup, it may break due to the user fiddling with things (e.g.: a broken cmdline).

I have a small tool that creates the above-mentioned backup bundle after every successful boot. If I break the main bundle and it doesn’t boot, then that image is kept around, and I can reboot off it.

As mentioned above, tapping Space during startup shows the boot entry menu.

Credit

sb-backup relies on go-uefi and sbctl, so thanks to the author for doing all the hard lifting.

Update 1

It seems that using SecureBoot with a discrete GPU can be problematic in some cases. Since the GPU’s firmware is not signed, it may fail to load in some cases due initialisation order, and may result in a bricked motherboard.

I’d recommend you do some serious research before trying this if you have a discrete GPU. See this reddit thread for more details.

— § —