Sunday, August 4, 2024

Arch Linux UEFI with dm-crypt and UKI

Arch Linux allows a decent level of customization and the configuration of LUKS 2 and LVM is straightforward.

Encrypting boot requires the Grub 2 bootloader. However, UEFI by itself or in conjunction with systemd-boot can be used for booting a Unified Kernel Image (UKI) via the EFI system partition (ESP).

The root file system can be encrypted using LUKS 2 and the UKI can be verified via hardware secure boot.  A UKI can be built and placed in the ESP, which can then be loaded directly via UEFI.

The root filesystem resides on a logical volume and is encrypted using dm-crypt. A detached LUKS header on a microSD card or similar medium should be used for enhanced security. GPG can be used to encrypt the LUKS header on the external medium. After booting an Arch ISO from a boot medium, the following instructions can be used for configuring Arch.

# timedatectl set-ntp true
# wipefs --all /dev/nvme0n1
# sgdisk /dev/nvme0n1 -n 1::+512MiB -t 1:EF00
# sgdisk /dev/nvme0n1 -n 2 -t 2:8300
# cryptsetup luksFormat --cipher aes-xts-plain64 --keyslot-cipher \
serpent-xts-plain --keyslot-key-size 512 --use-random -S 0 -h sha512 \ 
-i 4000 /dev/nvme0n1p2
# cryptsetup open /dev/nvme0n1p2 root
# mkfs.ext4 /dev/mapper/root # mount /dev/mapper/root /mnt # mkfs.fat -F32 /dev/nvme0n1p1 # mount --mkdir /dev/nvme0n1p1 /mnt/efi
# dd if=/dev/zero of=/mnt/swapfile bs=1M count=8000 status=progress
# chmod 600 /mnt/swapfile
# mkswap /mnt/swapfile
# swapon /mnt/swapfile
# pacstrap -K /mnt base base-devel linux linux-hardened linux-hardened-headers \
linux-firmware apparmor mesa xf86-video-intel vulkan-intel git vi vim ukify
# genfstab -U /mnt >> /mnt/etc/fstab
# arch-chroot /mnt
# ln -sf /usr/share/zoneinfo/UTC /etc/localtime
# hwclock --systohc
# sed -i 's/#'"en_US.UTF-8"' UTF-8/'"en_US.UTF-8"' UTF-8/g' /etc/locale.gen
# locale-gen
# echo 'LANG=en_US.UTF-8' > /etc/locale.conf
# echo "KEYMAP=us" > /etc/vconsole.conf
# echo myhostname > /etc/hostname
# cat <> /etc/hosts
127.0.0.1 myhostname
::1 localhost
127.0.1.1 myhostname.localdomain myhostname
EOT

# sed -i 's/HOOKS.*/HOOKS=(base udev autodetect modconf kms keyboard keymap \
consolefont block encrypt filesystems resume fsck)/' /etc/mkinitcpio.conf
# mkinitcpio -P
# bootctl install
# passwd
# pacman -S intel-ucode efibootmgr
# swapoffset=`filefrag -v /swapfile | awk '/\s+0:/ {print $4}' | sed -e 's/\.\.$//'`
# blkid -s UUID -o value /dev/nvme0n1p2
# efibootmgr --disk /dev/nvme0n1p1 --part 1 --create --label "Linux" --loader \
/vmlinuz-linux --unicode "cryptdevice=UUID=<UUID OF CRYPTDEVICE>:root \
root=/dev/mapper/root resume=/dev/mapper/root resume_offset=$swapoffset \
rw initrd=\intel-ucode.img initrd=\initramfs-linux.img" --verbose

# cat <> /etc/mkinitcpio.d/linux.preset
ALL_kver="/boot/vmlinuz-linux"
ALL_microcode=(/boot/*-ucode.img)
PRESETS=('default' 'fallback')
default_uki="/efi/EFI/Linux/arch-linux.efi"
default_options="--splash /usr/share/systemd/bootctl/splash-arch.bmp"
fallback_uki="/efi/EFI/Linux/arch-linux-fallback.efi"
fallback_options="-S autodetect"
EOT

# mkdir -p /efi/EFI/Linux

# cat <> /etc/kernel/cmdline
cryptdevice=UUID=<UUID OF CRYPTDEVICE>:root root=/dev/mapper/root resume=/dev/mapper/root resume_offset=51347456 rw
EOT

# mkinitcpio -p linux
# echo "layout=uki" >> /etc/kernel/install.conf

# cat <> /etc/systemd/network/nic0.network
[Match]
Name=nic0
[Network]
DHCP=yes
EOT

# pacman -Syu
# pacman -S xorg xfce4 xfce4-goodies lightdm lightdm-gtk-greeter libva-intel-driver mesa xorg-server xorg-xinit sudo
# systemctl enable lightdm
# systemctl start lightdm
# systemctl enable systemd-resolved.service
# systemctl enable systemd-networkd.service
# systemctl start systemd-resolved.service
# systemctl start systemd-networkd.service
# useradd -m -g wheel -s /bin/bash myusername