Arch base install with Secure Boot, BTRFS, TPM2 LUKS, and UKIs
This very much is a rehash of Walian’s Arch install guide.. It’s a fantastic guide, please give it a read. Full credit goes to him.
Create a bootable USB
There are plenty of ways to do this, the Arch Wiki mentions a few ways. Here is a fairly basic way to do it.
- Download an Arch image
- Create a bootable usb (keeping in mind the path to the Arch Image and the USB):
dd bs=4M if=path/to/archlinux-version-x86_64.iso of=/dev/disk/by-id/usb-My_flash_drive conv=fsync oflag=direct status=progress
- If your BIOS has Secure Boot enabled, disable it. (By default the DIY editions of the Framework laptops have it enabled)
- Boot into the USB
Connect to the Internet
If you have an ethernet connection you should be fine. If you’re on wifi the Arch live disk comes with iwd
Run iwctl
to get into the interactive prompt then:
- Find your device name:
device list
- Make sure you can find your network (replace device_name with your device from step 1):
station device_name scan
station device_name get-networks
- Connect (replacing both device_name and network_name):
station device_name connect network_name
- Exit out of interactive prompt:
exit
Preparing the disks
Find our drive name using: lsblk
In my case it’s nvme0n1
, but if it’s a SATA drive it may be something like sda
.
Like in Walian’s guide we’ll create a 512MB FAT32 for boot, and the rest on a btrfs partition for root.
We’ll use sgdisk
to partition it.
EFI
and LINUXROOT
can be whatever labels you like.
sgdisk -Z /dev/nvme0n1
sgdisk -n1:0:+512M -t1:ef00 -c1:EFI -N2 -t2:8304 -c2:LINUXROOT /dev/nvme0n1
partprobe -s /dev/nvme0n1
Running lsblk
again should show our newly created partitions.
We only want to encrypt our root partition: nvme0n1p2
in my case.
To do that:
cryptsetup luksFormat --type luks2 /dev/nvme0n1p2
cryptsetup luksOpen /dev/nvme0n1p2 linuxroot
To create the filesystems:
mkfs.vfat -F32 -n EFI /dev/nvme0n1p1
mkfs.btrfs -f -L linuxroot /dev/mapper/linuxroot
To close off the preparing disks section, lets mount the partitions and create the btrfs subvolumes.
mount /dev/mapper/linuxroot /mnt
mkdir /mnt/efi
mount /dev/nvme0n1p1 /mnt/efi
btrfs subvolume create /mnt/home
btrfs subvolume create /mnt/srv
btrfs subvolume create /mnt/var
btrfs subvolume create /mnt/var/log
btrfs subvolume create /mnt/var/cache
btrfs subvolume create /mnt/var/tmp
Base install
Update pacman mirrors (replacing country with the most relevant country code for you):
reflector --country AU --protocol https --age 24 --sort rate --save /etc/pacman.d/mirrorlist
Pacstrap a base install. Taking note of amd-ucode
, which you may want to swap out for intel-ucode
if you’re using an Intel processor.
pacstrap -K /mnt base base-devel linux linux-lts linux-firmware amd-ucode neovim cryptsetup btrfs-progs dosfstools util-linux git unzip sbctl networkmanager sudo plasma-meta kitty fwupd
Note: If you get a corrupt package error run
pacman -Sy archlinux-keyring
beforehand.
Update the locale settings. Edit /mnt/etc/locale.gen
with your text editor of choice (vim
). Uncomment out the relevant entries.
In my case
- ja_JP.UTF-8 UTF-8
- en_AU.UTF-8 UTF-8
- en_US.UTF-8 UTF-8
Run systemd-firstboot --root /mnt --prompt
for further setup.
For keymap
I do jp106
because I have a JIS layout keyboard, but for the majority of people us
will be appropriate.
Timezone and hostname are up to you. (Melbourne is timezone: 359
)
Run arch-chroot /mnt locale-gen
Create User
Create the local user, and then assign a password to them.
arch-chroot /mnt useradd -G wheel -m sebastiaan
arch-chroot /mnt passwd sebastiaan
Next we want to edit the sudoers file: /mnt/etc/sudoers
Ensure this line is uncommented: %wheel ALL=(ALL:ALL) ALL
. Additionally if you like asterisks as you type your password, add this line: Defaults pwfeedback
.
Unified Kernel Images
Create our kernel parameters. Because we’re using Discoverable Partitions it doesn’t need to contain anything.
echo "rw" >/mnt/etc/cmdline.d/rw.conf
Then let’s create the EFI directory structure.
mkdir -p /mnt/efi/EFI/Linux
Now lets change the HOOKS
in /mnt/etc/mkinitcpio.conf
to look like the following:
HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole sd-encrypt block filesystems fsck)
Now lets update /mnt/etc/mkinitcpio.d/linux.preset
and linux-lts.preset
.
# mkinitcpio preset file for the 'linux' package
ALL_config="/etc/mkinitcpio.conf"
ALL_kver="/boot/vmlinuz-linux"
PRESETS=('default' 'fallback')
#default_config="/etc/mkinitcpio.conf"
#default_image="/boot/initramfs-linux.img"
default_uki="/efi/EFI/Linux/arch-linux.efi"
default_options="--splash /usr/share/systemd/bootctl/splash-arch.bmp"
#fallback_config="/etc/mkinitcpio.conf"
#fallback_image="/boot/initramfs-linux-fallback.img"
fallback_uki="/efi/EFI/Linux/arch-linux-fallback.efi"
fallback_options="-S autodetect"
And now to generate our UKIs:
arch-chroot /mnt mkinitcpio -P
If we run ls -lR /mnt/efi
we can seem our UKIs.
Enable services and boot loader and reboot into BIOS
systemctl --root /mnt enable sddm systemd-resolved systemd-timesyncd NetworkManager
systemctl --root /mnt mask systemd-networkd
arch-chroot /mnt bootctl install --esp-path=/efi
sync
systemctl reboot --firmware-setup
You can now remove your bootable USB.
In the BIOS under Secure Boot there should be an option to enter “Setup Mode”. On Framework laptops you do this by enabling “Erase all Secure Boot Settings”.
Save these settings and continue booting.
Log in when prompted.
Secure Boot with TPM2 Unlocking
Run sbctl status
. Ensure Setup Mode
is Enabled
, if it isn’t boot back into the BIOS and try again.
Create and enroll out personal Secure Boot Keys. The -m
flag includes the Microsoft vendor key. Great for not bricking your laptop.
sudo sbctl create-keys
sudo sbctl enroll-keys -m
Now let’s sign our .efi
files, the -s
flag is important because with it sbctl
will automatically resign them if we update the kernel or bootloader via pacman
.
sudo sbctl sign -s /usr/lib/systemd/boot/efi/systemd-bootx64.efi -o /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed
sudo sbctl sign -s /efi/EFI/BOOT/BOOTX64.EFI
sudo sbctl sign -s /efi/EFI/Linux/arch-linux.efi
sudo sbctl sign -s /efi/EFI/Linux/arch-linux-fallback.efi
Fwupd support
You may want to sign /usr/lib/fwupd/efi/fwupdx64.efi
as well for fwupd
support. (Which let’s you update firmware.)
sudo sbctl sign -s /usr/lib/fwupd/efi/fwupdx64.efi -o /usr/lib/fwupd/efi/fwupdx64.efi.signed
We can automatically sign this file on updates by creating a hook.
/etc/pacman.d/hooks/96-sign-fwupd-secureboot.hook
[Trigger]
Operation = Install
Operation = Upgrade
Type = Path
Target = usr/lib/fwupd/efi/fwupdx64.efi
[Action]
When = PostTransaction
Exec = /usr/bin/sbctl sign -s /usr/lib/fwupd/efi/fwupdx64.efi -o /usr/lib/fwupd/efi/fwupdx64.efi.signed
Depends = sbctl
Then set DisableShimForSecureBoot
in /etc/fwupd/fwupd.conf
/etc/fwupd/fwupd.conf
[uefi_capsule]
DisableShimForSecureBoot=true
Reinstalling the kernel is a good way to test this: sudo pacman -S linux
.
We’re almost done. Reboot into the BIOS again: systemctl reboot --firmware-setup
, this time make sure Secure Boot is enabled.
Log into your account again.
Now it’s time to configure automatic unlocking of the root filesystem. First let’s create a recovery key.
sudo systemd-cryptenroll /dev/gpt-auto-root-luks --recovery-key
Make note of this key.
Now lets add the LUKS key to TPM.
sudo systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7 /dev/gpt-auto-root-luks
Note to delete keys you can do the following List keys:
sudo systemd-cryptenroll /dev/gpt-auto-root-luks
Wipe keys:sudo systemd-cryptenroll /dev/gpt-auto-root-luks --wipe-slot=2
Reboot, and hopefully you don’t need to enter your drive encryption password anymore.
I tripped up secure boot while upgrading some case fans, and trying to reenroll the keys resulted in
Failed to unseal secret using TPM2: State not recoverable
.
FHere’s the fix
echo 5 | sudo tee /sys/class/tpm/tpm0/ppi/request
and then reboot and restart.