Philipp's Website

Encryped Arch Linux Install Guide

After corebooting my Thinkpad T480 I wanted to increase the security of the system further by installing Arch Linux with full disk encryption and a Unified Kernel Image signed with my own keys.

Pre-Installation

Download installation image

Download the latest ISO from here. I like to verify the file hash of the image when downloading from a mirror. Download the b2sums.txt from the download page and place it in the same folder as the downloaded image. Verify the checksums with b2sum -c b2sums.txt.

b2sum -c b2sums.txt
---
archlinux-2026.04.01-x86_64.iso: OK

Write the image to the USB with dd:

sudo dd if=archlinux-2026.04.01-x86_64.iso of=/dev/sdb bs=8M status=progress

Replace sdb with the device identifier of your USB.

Boot the live system

Make sure to disable Secure Boot, as the installation image does not support it.

Set keymap

The Arch Linux installation image comes with US keymap by default. If not on a US keyboard, list the keymaps with:

localectl list-keymaps

Load a keymap (e.g. german):

loadkeys de-latin1

If on high-DPI screen, increase the font size (-d for double):

setfont -d

Configure networking

An Ethernet cable is preferred for simplicity. If you want to use WiFi, use iwd:

iwctl
[iwd] device list
[iwd] station wlan0 scan
[iwd] station wlan0 connect WIFI_NAME
# Enter your Password
# Check Connection
[iwd] station wlan0 show
[iwd] exit

Test network connectivity:

ping archlinux.org

(Optional) SSH into the live installer from a different system

If you have a second system available, you can use that to SSH into the live installer, enabling you to copy/paste commands directly and prevent typos.

  1. Run passwd to set a password for the root user.
  2. Add PermitRootLogin yes to /etc/ssh/sshd_config.
  3. Run systemctl restart sshd to apply the configuration change.
  4. Get your IP address by typing ip a.
  5. On the secondary machine, enter ssh root@<ip-address> and enter the newly created password.

Setup the system clock

The live system needs the current precise time for package verification and to prevent TLS certificate errors. Set the time with timedatectl:

timedatectl set-ntp true
timedatectl list-timezones
# Example
timedatectl set-timezone Europe/Amsterdam
# Check status
timedatectl

Partition your disk

List the available devices:

fdisk -l

In the case of my ThinkPad T480 I have /dev/nvme0n1.

Use cfdisk to format the device:

cfdisk /dev/nvme0n1

You probably already have partitions on your disk. Delete all of them so you only have Free Space available.

You will need to create the following partitions:

Mount Point Size Type
/boot 1G EFI System
/ Remainder of the device Linux Filesystem

Create the boot partition: select [Free Space], enter 1G for the size and select [Type] to change the type to EFI System.

For the root partition select [Free Space] - press Enter on the size to select the remainder of the space. The Type is Linux Filesystem by default.

Select [Write] to write the changes to disk.

You can display your created partitions with lsblk.

Format your partitions

Format the EFI partition as FAT32:

mkfs.fat -F32 /dev/nvme0n1p1

Encrypt the root partition and open it:

cryptsetup luksFormat --type luks2 /dev/nvme0n1p2
cryptsetup open /dev/nvme0n1p2 cryptroot

Create the file system:

mkfs.ext4 /dev/mapper/cryptroot

Mount the file systems

Mount the root volume to /:

mount /dev/mapper/cryptroot /mnt

Mount the EFI partition:

mount --mkdir /dev/nvme0n1p1 /mnt/boot

Check that both are mounted with lsblk.

Install the Base System

Install the base system with pacstrap:

pacstrap -K /mnt base linux linux-headers linux-firmware networkmanager cryptsetup sudo neovim base-devel efibootmgr systemd-ukify sbsigntools efitools

Generate the file system table

genfstab -U /mnt >> /mnt/etc/fstab
cat /mnt/etc/fstab

Harden the boot partition, by adding fmask=0137, dmask=0027 so only root can write, everybody else is blocked. Your fstab should look like this:

UUID=XXXX-XXXX   /boot   vfat   rw,relatime,fmask=0137,dmask=0027,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro   0 2

Chroot into the new installation

You can directly interact with the new systems tools and configurations by changing root into the root volume:

arch-chroot /mnt

Create a user and set the password:

useradd -m -G wheel -s /bin/bash user
passwd user

Set the root password:

passwd

Configure sudo for the wheel group by editing /etc/sudoers and uncommenting the following line:

%wheel ALL=(ALL:ALL) ALL

Localization

To use the correct language-specific formatting edit, edit /etc/locale.gen and uncomment the locales you want to have on your system. After doing that, run locale-gen to generate them. Edit /etc/locale.conf to set you default locale:

/etc/locale.conf
---
LANG=en_US.UTF-8

If not on a US keyboard, persist the keymap with vconsole.conf:

/etc/vconsole.conf
---
KEYMAP=de-latin1

Configure the initramfs

initramfs stands for initial RAM file system and provides the necessary tools to locate, access and mount the root file system. mkinitcpio is a script used to create the initramfs.

Edit /etc/mkinitcpio.conf and set the MODULES, FILES and HOOKS:

# Only needed if using an NVMe drive
MODULES=(nvme)

FILES=(/etc/crypttab.initramfs /etc/vconsole.conf)

HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt filesystems fsck)

To tell the initramfs where the encrypted partition is located, create the file /etc/crypttab.initramfs and add the UUID of the encrypted partition:

nvim /etc/crypttab.initramfs
---
cryptroot UUID=your-uuid-here none luks,discard

Edit the mkinitcpio kernel preset

A mkinitcpio preset is simply a list of information required to create initial ramdisk image. It is also used to automatically regenerate the image after a kernel update.

Edit /etc/mkinitcpio.d/linux.preset:

/etc/mkinitcpio.d/linux.preset
---
ALL_config="/etc/mkinitcpio.conf"
ALL_kver="/boot/vmlinuz-linux"

PRESETS=('default' 'fallback')
# If you want a splash screen image uncomment this line:
# default_options="--splash /usr/share/systemd/bootctl/splash-arch.bmp"

default_uki="/boot/EFI/Linux/arch-linux.efi"

fallback_uki="/boot/EFI/Linux/arch-linux-fallback.efi"
fallback_options="-S autodetect"

Install the bootloader and set up the UKI

The next part is going to cover the setup of the Unified Kernel Image, as well as the install of the systemd-boot bootloader.

Setup the kernel cmdline

First you need to configure the kernel cmdline to be able to look up and unlock the enrcrypted cryptroot partition.

Save the UUID of the partition with blkid and save it to a temporary file:

blkid /dev/nvme0n1p2 > /tmp/uuid.txt

Add the following line to /etc/kernel/cmdline:

nvim /etc/kernel/cmdline
---
rd.luks.name=your-uuid-here=cryptroot root=/dev/mapper/cryptroot rw quiet

Configure the UKI

Copy the default configuration to /etc/kernel/uki.conf and edit it:

cp /usr/lib/kernel/uki.conf /etc/kernel/uki.conf

Uncomment the following to configure the location of the secure boot certificate and signing key:

nvim /etc/kernel/uki.conf
---
[UKI]
SecureBootPrivateKey=/etc/kernel/secure-boot-private-key.pem
SecureBootCertificate=/etc/kernel/secure-boot-certificate.pem
SignKernel=yes

Generate the certificate and key:

ukify genkey --config /etc/kernel/uki.conf

Build the UKI

Create the directory for the UKI and build the image:

mkdir -p /boot/EFI/Linux
mkinitcpio -P

Verify the build:

ls /boot/EFI/Linux/
---
# should show:
arch-linux.efi  arch-linux-fallback.efi

Install the systemd-boot

Use bootctl to install systemd-boot to the EFI system partition (/boot):

bootctl install

Lock down the permissions:

chmod 700 /boot
chmod 600 /boot/loader/random-seed

Configure the options of systemd-boot in /boot/loader/loader.conf:

nvim /boot/loader/loader.conf
---
timeout 4
console-mode auto
auto-entries 1
secure-boot-enroll force

Verify the bootloader status:

bootctl status

Sign the bootloader and prepare enrollment

Sign the bootloader EFI binary:

/usr/lib/systemd/systemd-sbsign sign \
  --private-key /etc/kernel/secure-boot-private-key.pem \
  --certificate /etc/kernel/secure-boot-certificate.pem \
  --output /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed \
  /usr/lib/systemd/boot/efi/systemd-bootx64.efi

Install the keys for auto-enrollment:

bootctl install \
  --secure-boot-auto-enroll yes \
  --certificate /etc/kernel/secure-boot-certificate.pem \
  --private-key /etc/kernel/secure-boot-private-key.pem

Verify the .auth files are available:

ls /boot/loader/keys/auto/
---
KEK.auth  PK.auth  db.auth

Fix the boot partition permissions:

chmod 700 /boot

That’s everything done from inside the live system. For networking to work after reboot, enable NetworkManager. Exit the chroot environment, unmount the partitions and close the encrypted partition before reboot.

systemctl enable NetworkManager
exit
umount /mnt/boot
umount /mnt
cryptsetup close cryptroot
reboot

Enroll the Secure Boot keys

Auto-Enrollment

For automatic enrollment to work you need to delete the Secure Boot Platform Key (PK) in the firmware interface (UEFI) of your device. This will enter Setup Mode.

In my Tianocore firmware menu the process is as follows:

  1. Boot into the UEFI firmware interface (Esc or F2 during startup)
  2. Go to Secure Boot Configuration
  3. Change Secure Boot Mode to Custom Mode
  4. In Custom Secure Boot Options, remove the PK entry (this will enter Setup Mode)
  5. Reboot - systemd-boot will display a timer and automatically enroll your keys
  6. After sucessfull enrollment Reboot again and turn on Secure Boot

After rebooting one more you can check the bootloader status with:

bootctl status | grep -i secure
# should include `Secure Boot: enabled (user)`

Manual enrollment

In case the auto-enroll does not work (as it did for me the first time I flashed a T480), you can enroll the certificates manually.

Create a temporary directory and generate the required files:

mkdir -p ~/secureboot

Convert the secure boot certificate to DER format:

sudo openssl x509 -in /etc/kernel/secure-boot-certificate.pem -out ~/secureboot/db.cer -outform DER

Convert to the signature list as well:

cert-to-efi-sig-list /etc/kernel/secure-boot-certificate.pem ~/secureboot/db.esl

Sign the list:

sudo sign-efi-sig-list \
  -k /etc/kernel/secure-boot-private-key.pem \
  -c /etc/kernel/secure-boot-certificate.pem \
  db ~/secureboot/db.esl ~/secureboot/db.auth

Copy the files to the EFI system partition:

sudo cp ~/secureboot/db.cer /boot/db.cer
sudo cp ~/secureboot/db.auth /boot/db.auth

Reboot and enter the Tianocore firmware menu.

Navigate to Device Manager → Secure Boot Configuration → Custom Secure Boot Options → DB Options → Enroll Signature → Enroll Signature Using File - Choose db.cer.

Provide a valid GUID when asked (in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).

Make sure Secure Boot is enabled, commit the changes and reboot once more.

After the reboot, check the bootloader status with:

bootctl status | grep -i secure
# should include `Secure Boot: enabled (user)`

After sucessfull enrollment you can delete the enrollment files:

sudo rm /boot/db.cer /boot/db.auth