Install Arch Linux with LUKS and FIDO2 authentication
This article will guide you through a basic installation of Arch Linux using UKI, root partition encryption with LUKS while allowing drive decryption either via passphrase of a FIDO2 hardware key.
Verify following before starting!⌗
- Your computer supports SecureBoot/UEFI
- Your computer allows for enrollment of your own secureboot keys
Preparation⌗
- create a bootable USB
- Reboot to UEFI/BIOS and enable Secure Boot setup mode.
- Boot into Arch Linux USB
Network configuration⌗
Wired connections should work out of the box. You can verify connection by running:
ping archlinux.org
To connect to WiFi run:
iwctl station wlan0 connect <SSID>
Disk partitioning⌗
Using your favourite tool, create two partitions:
- 512MB size -> EFI, in my case
/dev/nvme0n1p1
- Remaining space -> LUKS encrypted root partition,
/dev/nvme0n1p2
Format EFI:
mkfs.fat -F32 /dev/nvme0n1p1
LUKS setup⌗
Create encrypted volume:
cryptsetup luksFormat --type luks2 /dev/nvme0n1p2
Decrypt created volume:
cryptsetup open --perf-no_read_workqueue --perf-no_write_workqueue --persistent /dev/nvme0n1p2 cryptlvm
--perf
options are optional and recommended for SSDs
Configuring LVM⌗
If you want a more advanced setup follow instructions on the wiki, for simplicity’s sake I’ll go with a single root volume:
pvcreate /dev/mapper/cryptlvm
vgcreate vg /dev/mapper/cryptlvm
lvcreate -l 100%FREE vg -n root
Format created volume(s):
mkfs.ext4 /dev/vg/root
Mounting drives⌗
Nothing crazy here, just mount created partitions:
mount /dev/vg/root /mnt
mkdir -p /mnt/boot/efi
mount /dev/nvme0n1p1 /mnt/boot/efi
remember to mount all other partitions when using a different partition scheme!
System bootstrapping⌗
Install core packages:
pacstrap /mnt \
base base-devel \
linux-zen linux-firmware \
man neovim git networkmanager \
lvm2 dracut efibootmgr binutils libfido2 \
sbctl sbsigntools \
intel-ucode # use amd-ucode for AMD CPUs
base-devel is technically not required for this setup but it’s required to install AUR packages
Generate fstab:
genfstab -U /mnt > /mnt/etc/fstab
Chroot⌗
Chroot into your new system:
arch-chroot /mnt
Configure timezone⌗
ln -sf /usr/share/zoneinfo/Europe/Warsaw /etc/localtime
hwclock --systohc
Replace Europe/Warsaw
with your timezone
Generate locale⌗
sed -i -e 's/#pl/pl/' -e 's/#en_US/en_US/' /etc/locale.gen
locale-gen
echo 'LANG=en_US.UTF-8' > /etc/locale.conf
Set hostname⌗
echo 'archlinux' > /etc/hostname
Create non-root user⌗
To create user run:
useradd -m <user>
passwd <user>
And to grant sudo
privileges:
echo '<user> ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/<user>
omit
NOPASSWD:
if you prefer using a password withsudo
Start NetworkManager⌗
systemctl enable NetworkManager
Pacman hooks⌗
For Unified Kernel Images to work properly we’ll need to create few scripts that will hook into pacman
:
For image creation:
/usr/local/bin/dracut-install.sh
#!/usr/bin/env bash
mkdir -p /boot/efi/EFI/Linux
while read -r line; do
if [[ "$line" == 'usr/lib/modules/'+([^/])'/pkgbase' ]]; then
kver="${line#'usr/lib/modules/'}"
kver="${kver%'/pkgbase'}"
dracut --force --uefi --kver "$kver" /boot/efi/EFI/Linux/arch-linux.efi
fi
done
And for image removal:
/usr/local/bin/dracut-remove.sh
#!/usr/bin/env bash
rm -f /boot/efi/EFI/Linux/arch-linux.efi
Remember to make scripts executable:
chmod +x /usr/local/bin/dracut-*
Now create pacman hooks:
mkdir /etc/pacman.d/hooks
Hook for install/upgrade:
/etc/pacman.d/hooks/90-dracut-install.hook
[Trigger]
Type = Path
Operation = Install
Operation = Upgrade
Target = usr/lib/modules/*/pkgbase
[Action]
Description = Updating linux EFI image
When = PostTransaction
Exec = /usr/local/bin/dracut-install.sh
Depends = dracut
NeedsTargets
And for removal:
/etc/pacman.d/hooks/60-dracut-remove.hook
[Trigger]
Type = Path
Operation = Remove
Target = usr/lib/modules/*/pkgbase
[Action]
Description = Removing linux EFI image
When = PreTransaction
Exec = /usr/local/bin/dracut-remove.sh
NeedsTargets
Dracut configuration⌗
Configure kernel parameters:
cat << EOF > /etc/dracut.conf.d/cmdline.conf
kernel_cmdline="rd.luks.uuid=luks-$(blkid -s UUID -o value /dev/nvme0n1p2) rd.luks.options=fido2-device=auto rd.lvm.lv=vg/root root=/dev/mapper/vg-root rootfstype=ext4 rootflags=rw,relatime"
EOF
Set dracut flags:
cat << EOF > /etc/dracut.conf.d/flags.conf
compress="zstd"
hostonly="no"
EOF
Enable FIDO2 support:
echo 'add_dracutmodules+=" fido2 "' > /etc/dracut.conf.d/fido2-module.conf
Build the image⌗
Now reinstalling the kernel (or installing any other kernel) should generate a proper image:
pacman -S linux-zen
Add image to UEFI⌗
First, check existing entries:
efibootmgr
Any not needed entries can be removed with:
efibootmgr -b <index> -B
To create boot entry for your image run:
efibootmgr --create --disk /dev/nvme0n1 --part 1 --label "Arch Linux" --loader 'EFI\Linux\arch-linux.efi' --unicode
Now, check which index is assigned to created boot entry and set it as default:
efibootmgr -o <index>
Now, reboot and log back in.
Secure Boot⌗
First, verify that Secure Boot
is in setup mode:
# sbctl status
Installed: ✘ Sbctl is not installed
Setup Mode: ✘ Enabled
Secure Boot: ✘ Disabled
If not, reboot to UEFI:
systemctl reboot --firmware-setup
And enable setup mode for Secure Boot
Each BIOS is different, check manual for your device for additional info
Create keys and sign binaries⌗
sbctl create-keys
sbctl sign -s /boot/efi/EFI/Linux/arch-linux.efi
Configure dracut
to use created keys:
cat << EOF > /etc/dracut.conf.d/secureboot.conf
uefi_secureboot_cert="/usr/share/secureboot/keys/db/db.pem"
uefi_secureboot_key="/usr/share/secureboot/keys/db/db.key"
EOF
Replace sbctl
’s pacman
hook:
/etc/pacman.d/hooks/zz-sbctl.hook
[Trigger]
Type = Path
Operation = Install
Operation = Upgrade
Operation = Remove
Target = boot/*
Target = efi/*
Target = usr/lib/modules/*/vmlinuz
Target = usr/lib/initcpio/*
Target = usr/lib/**/efi/*.efi*
[Action]
Description = Signing EFI binaries...
When = PostTransaction
Exec = /usr/bin/sbctl sign /boot/efi/EFI/Linux/arch-linux.efi
Enroll generated keys:
sbctl enroll-keys
If you want to dual-boot with
Windows
add--microsoft
flag
Reboot and verify Secure Boot
with sbctl
:
# sbctl status
Installed: ✓ sbctl is installed
Owner GUID: <your guid>
Setup Mode: ✓ Disabled
Secure Boot: ✓ Enabled
Adding FIDO2 key to LUKS⌗
Nothing complicated here, simply run:
systemd-cryptenroll /dev/nvme0n1p2 --fido2-device=auto
For additional settings consult the manpage
Reboot and verify that your FIDO2 key is detected.
Post-installation⌗
Congratulations, now configure your system as you see fit.
Sources⌗
This guide was heavily based on Ataraxxia’s secure-arch guide, 459below’s Debian fido2 with dracut boot and a few hours of digging through Arch Wiki.