Secure boot with NixOS and systemd

Last Update: 2023-04-16

Note: This tutorial may not work on laptops, because their BIOS and secure boot implementation tends to be trash.

Save the following in a script in /etc/nixos/secureboot/setup.sh

#!/usr/bin/env bash
cd "$(dirname "$0")"

# From: https://wiki.archlinux.org/title/Unified_Extensible_Firmware_Interface/Secure_Boot#Using_your_own_keys

uuidgen --random > GUID.txt

# Setup platform key
openssl req -newkey rsa:4096 -nodes -keyout PK.key -new -x509 -sha256 -days 90000 -subj "/CN=codefionn Platform Key/" -out PK.crt
openssl x509 -outform DER -in PK.crt -out PK.cer
cert-to-efi-sig-list -g "$(< GUID.txt)" PK.crt PK.esl
sign-efi-sig-list -g "$(< GUID.txt)" -k PK.key -c PK.crt PK PK.esl PK.auth

# Allow removing platform key in user mode
sign-efi-sig-list -g "$(< GUID.txt)" -c PK.crt -k PK.key PK /dev/null rm_PK.auth

# Key exchange key
openssl req -newkey rsa:4096 -nodes -keyout KEK.key -new -x509 -sha256 -days 90000 -subj "/CN=codefionn Key Exchange Key/" -out KEK.crt
openssl x509 -outform DER -in KEK.crt -out KEK.cer
cert-to-efi-sig-list -g "$(< GUID.txt)" KEK.crt KEK.esl
sign-efi-sig-list -g "$(< GUID.txt)" -k PK.key -c PK.crt KEK KEK.esl KEK.auth

# Signature Database key
openssl req -newkey rsa:4096 -nodes -keyout db.key -new -x509 -sha256 -days 90000 -subj "/CN=codefionn Signature Database key/" -out db.crt
openssl x509 -outform DER -in db.crt -out db.cer
cert-to-efi-sig-list -g "$(< GUID.txt)" db.crt db.esl
sign-efi-sig-list -g "$(< GUID.txt)" -k KEK.key -c KEK.crt db db.esl db.auth

Make the script executable with

chmod 700 /etc/nixos/secureboot/setup.sh

and execute it with

/etc/nixos/secureboot/setup.sh

This will created the necessary keys to sign the boot loader and Linux kernel for secure boot.

In your NixOS configuration in /etc/nixos/configuration.nix add the following

# Sign all bootloaders
boot.loader.systemd-boot.extraInstallCommands = ''
  export PATH="$PATH:${pkgs.sbsigntool}/bin"
  for i in /boot/efi/EFI/*/*.efi /boot/efi/EFI/*/*.EFI ; do
    sbsign --key "/etc/nixos/secureboot/db.key" --cert "/etc/nixos/secureboot/db.crt" "$i" --output "$i"
  done
'';

Execute

nixos-rebuild switch

to apply the changes. Notice that the .efi files are now signed.

This will sign all bootloaders every time you update your NixOS installation. Please replace /boot/efi/EFI with your boot path (e.g. just /boot/EFI).

Save the db.esl and db.crt (in the /etc/nixos/secureboot directory) onto a FAT filesystem (a USB-stick or your /boot/EFI directory).

In your BIOS setup (typically launched with the DEL or F1 key at boot) enable secure boot and append the authorized key db.esl or db.crt (maybe one of them will not be accepted by your BIOS setup).

Save the changes and restart.