Arch EFI Luks
Setting up FDE with UKI (Unified Kernel Images) and Secure Boot with Arch Linux was slightly more confusing that I anticipated. Just wanted to knock out a quick how to on actually building this the right way. It seems to be the right configuration conceptually, but the tools used like dracut vs mkinitcpio in the wiki made it hard to piece together. A opinionated Ansible playbook is hopefully coming soon.
- Boot the system into the UEFI/BIOS. Set
Secure BoottoSetupmode. - Boot into the live Arch ISO and perform typical setup steps from the installation guide.
- Setup networking
timedatectlto sync clocks
- Partition and encrypt the disks. This can be fairly arbitrary, but an unencrypted FAT32 partition for the UKI is required. I’ll outline a sample partition scheme here:
fdisk /dev/sda:gfor GPT,nfor new partition, 1GB size (for EFI),nwith remaining for LUKS,wto savemkfs.fat -F32 /dev/sda1for the EFI filesystemcryptsetup luksFormat /dev/sda2, enter the passphrase. It can be removed later, and we can store the key in the TPMcryptsetup open /dev/sda2 cryptto decrypt and have the device writeablepvcreate /dev/mapper/crypt,vgcreate root /dev/mapper/crypt,lvcreate -l 100%FREE root root-lv,mkfs.ext4 /dev/mapper/root-root-lvto create a root filesystem on the LUKS partition.
- Mount the filesystems, root before EFI to ensure everything is written properly
mount /dev/mapper/root-root-lv /mnt,mount /dev/sda1 /mnt/efi --mkdir
- Pacstrap the system, with whatever packages you need on disk
pacstrap -K /mnt base linux linux-firmware vi sbctl efibootmgr
- Generate the fstab
genfstab -U /mnt >> /mnt/etc/fstab - Chroot
arch-chroot /mnt - Now that we’re in the disk itself, there’s a few tasks to take care of
ln -sf /usr/share/zoneinfo/America/Los_Angeles /etc/localtime- Set locale in
/etc/locale.confand runlocale-gen - Set the hostname in
/etc/hostname
- Use
efibootmgrto remove any unneeded boot entries, like old Windows boot entriesefibootmgr --unicodeto print,efibootmgr --unicode --bootnum 0000 --delete-bootnumto remove
- Set your kernel cmdline parameters in
/etc/kernel/cmdlineand/etc/kernel/cmdline_fallback. These should at least include the UUID’s of the root system.rd.luks.uuid=<<luks uuid>> root=UUID=<<ext4 lvm uuid>> rw
- Edit
/etc/mkinintcpio.confto have the correctHOOKSlineHOOKS=(base systemd keyboard udev autodetect microcode modconf kms keymap consolefont sd-vconsole block sd-encrypt lvm2 filesystems fsck)
- Edit
/etc/mkinitcpio.d/linux.presetto have `mkinitcpio generate the two kernel options with UKIdefault_uki="/efi/EFI/Linux/arch-linux.efi" fallback_uki="/efi/EFI/Linux/arch-linux-fallback.efi" fallback_options="-S autodetect"
- Create the directories for the UKI’s
mkdir /efi/EFI/Linux
- Generate and install the Secure Boot keys. Install the Microsoft keys if required
sbctl create-keyssbctl enroll-keys -m
- Create a hook for
mkinitcpioto sign the created keys/etc/initcpio/post/uki-sbsign: ’’' #!/usr/bin/env bash
uki="$3" [[ -n “$uki” ]] || exit 0
keypairs=(/var/lib/sbctl/keys/db.key /var/lib/sbctl/keys/db.crt)
for (( i=0; i<${keypairs[@]}; i+=2 )); do
key="${keypairs[$i]}" cert="${keypairs[(( i + 1 ))]}"
if ! sbverify –cert “$cert” “$uki” &>/dev/null; then
sbsign –key “$key” –cert “$cert” –output “$uki” “$uki”
fi
done
’’'
16. Create EFI boot entries for the UKI’s:
- efibootmgr --create --disk /dev/sda1 --part 1 --label "Arch Linux" --loader '\EFI\Linux\arch-linux.efi' --unicode
- efibootmgr --create --disk /dev/sda1 --part 1 --label "Arch Linux Fallback" --loader '\EFI\Linux\arch-linux-fallback.efi' --unicode
17. If desired, create a luks key in the TPM
- systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7 /dev/sda2
18. Finish Arch install/user setup as required and reboot. On reboot, Secure Boot should be enabled and working, and the EFI should boot the kernel. Enjoy!