This casual guide serves as an archive for my future self, who will inevitably install Arch Linux again and might need some guidance from the past on how to get a fully encrypted LUKS root partition working with an external USB keyfile.
First, you will need a live USB containing the Arch Linux ISO. I decided to partition a 64 GB USB drive into two partitions. The first partition contains the installation ISO, which can be written using:
dd if=arch-linux.iso of=/dev/sda1 bs=4M status=progress conv=fsync oflag=direct
The second partition can be formatted as either EXT4 or FAT32:
mkfs.ext4 /dev/sda2
Next, mount it and create the keyfile:
mount /dev/sda2 /mnt/key --mkdir
dd if=/dev/urandom of=/mnt/key/root.key bs=512 count=8
chmod 000 /mnt/key/root.key
chown root:root /mnt/key/root.key
Now you can follow the Arch Linux Installation Guide (obviously). Here are some important considerations.
Securely wipe the SSD. In my case, it is an NVMe drive, so I can use nvme-cli, which is included in the Arch Linux ISO:
nvme format /dev/nvme0n1 --ses=<1,2>
Depending on the device, it may support either User Data Erase (1) or Cryptographic Erase (2).
Create the following partitions:
Mount Device Size Format
/boot /dev/nvme0n1p1 1G mkfs.fat -F 32
/ /dev/nvme0n1p2 461G
[SWAP] /dev/nvme0n1p3 15G mkswap
For the root (/) partition, initialize the LUKS container and create the filesystem:
cryptsetup -v luksFormat /dev/nvme0n1p2
cryptsetup open /dev/nvme0n1p2 root
mkfs.ext4 /dev/mapper/root
Assuming the USB partition is mounted under /mnt/key and you have already entered the installation with arch-chroot, add the keyfile (and optionally another backup passphrase):
cryptsetup luksAddKey /dev/nvme0n1p2 /mnt/key/root.key
Proceed with the rest of the installation. For the bootloader, I use GRUB with UEFI:
pacman -S grub efibootmgr
grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=ARCH
Before generating the GRUB configuration, add the following kernel parameters to /etc/default/grub:
GRUB_CMDLINE_LINUX="rd.luks.name=<root-UUID(encrypted)>=root root=/dev/mapper/root rd.retry=10"
Then generate the configuration:
grub-mkconfig -o /boot/grub/grub.cfg
We also need to configure mkinitcpio by editing /etc/mkinitcpio.conf:
MODULES=(... vfat ext4 usb_storage uas xhci_pci ehci_pci)
...
HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt filesystems fsck)
Next, configure /etc/crypttab.initramfs:
root UUID=<root-UUID(encrypted)> root.key:UUID=<usb-UUID> keyfile-timeout=10s
Finally, regenerate the initramfs:
mkinitcpio -P
At boot, the system will attempt to load root.key from the USB drive. If it is not found, it will fall back to prompting for the LUKS passphrase.
Other Configurations
Create a user:
useradd -mG wheel <user>
Remember to enable the wheel group in /etc/sudoers.
Useful packages:
Microcode: intel-ucode
Power management: tlp (configure `/etc/tlp.conf` and run `tlp start`)
Audio: alsa-utils pipewire pipewire-alsa pipewire-pulse wireplumber
Audio firmware: sof-firmware alsa-firmware alsa-ucm-conf (reboot, then test with `alsamixer` and `speaker-test`)
Fonts: terminus-font (configure `/etc/vconsole.conf`)
Bluetooth: bluez bluez-utils
Hyprland: hyprland kitty hyprlauncher firefox
Yazi: ffmpeg 7zip jq poppler fd ripgrep fzf zoxide imagemagick yazi
NVIDIA: nvidia-dkms nvidia-utils egl-wayland
Enable the required services:
systemctl enable --now NetworkManager
systemctl enable --now tlp
systemctl enable --now alsa-state.service
systemctl enable --now alsa-restore.service
systemctl --user enable --now pipewire.service
systemctl --user enable --now pipewire-pulse.service
systemctl --user enable --now wireplumber.service
systemctl enable --now bluetooth.service
If using NVIDIA with Hyprland, include the following modules in mkinitcpio.conf:
MODULES=(i915 nvidia nvidia_modeset nvidia_uvm nvidia_drm ...)
Then regenerate the initramfs:
mkinitcpio -P