I use a pretty simple setup for booting my systems.
- UEFI firmware loads a signed bootloader (
systemd-bootin my case, but
gummibootis basically the same for non-systemd systems).
- The bootloader loads a signed executable that bundles the initrd, cmdline and kernel (“the bundle” from here on).
initrdprompts for the encryption passphrase, decrypts everything, and boots the actual OS.
That’s all the OS boot process, but some extra steps happen before I see an actual desktop:
- Once a successful boot completes, the currently booted bundle is backed up, in case I break the main one before the next reboot.
- Upon booting,
tty1automatically logs into my user account and starts up
swayitself starts all other user-session services by triggering a systemd target.
From this point on, it’s assumed that the EFI partition is mounted in
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:
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
# 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
cmdline is not possible since it’s embedded in the bundle.
sbctl is a tool to manage SecureBoot keys and generate signed bundles with
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
Prepare the firmware
- Reboot into the firmware/UEFI menu.
- Disable Secure Boot.
- Turn on custom key mode (this implies “using user-provisioned keys”).
- Turn on setup mode (this implies “mode where the user can alter keys”).
Set up the OS
- Reboot into ArchLinux (or your distro of choice).
- Create and enroll keys:
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 --sign /boot/EFI/Linux/arch.efi
The bundle will use your existing
kernel. So each time
mkinitcpio generates a new
initrd, you need to rebuild the bundle.
sbctl includes pacman hooks to re-build the bundle when you
update the kernel or the
/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
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 into the firmware/UEFI menu.
- Enable Secure Boot (this implies “check that everything is signed”).
- Leave custom key mode on (e.g.: continue using the user-provisioned keys).
- Turn off setup mode (e.g.: disallow further altering the configured keys).
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.
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.
sb-backup relies on
sbctl, so thanks to
the author for doing all the hard lifting.
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.