Blog

Install Arch with encrypted root + swap and UKI

December 3, 2025
Soroush Alinia
Install Arch with encrypted root + swap and UKI

I wanted an Arch setup where both root and swap stay encrypted, resume works, and systemd-boot loads a unified kernel image (UKI). This is the exact flow I used on a blank NVMe drive.

Layout used below: /dev/nvme0n1p1 (EFI, 512M), /dev/nvme0n1p2 (LUKS swap), /dev/nvme0n1p3 (LUKS root, Btrfs). Swap lives on its own LUKS volume so hibernation resumes from encrypted space.1

Partition, encrypt, and mount

Create three GPT partitions with cfdisk or parted. For the EFI slice, set the partition type to EFI System (GUID type EF00) and toggle the esp/boot flag; formatting alone is not enough.2 Then format it:

mkfs.fat -F32 -n EFI /dev/nvme0n1p1

Encrypt swap and root, then open them:3

cryptsetup luksFormat /dev/nvme0n1p2           # swap
cryptsetup luksFormat /dev/nvme0n1p3           # root
cryptsetup open /dev/nvme0n1p2 cryptswap
cryptsetup open /dev/nvme0n1p3 cryptroot

Remember that the password for root and swap must be same especially if you want to use hibernate.

Format and mount:

mkswap /dev/mapper/cryptswap
swapon /dev/mapper/cryptswap

mkfs.btrfs /dev/mapper/cryptroot
mount /dev/mapper/cryptroot /mnt
btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home
umount /mnt

mount -o noatime,ssd,compress=zstd,space_cache=v2,discard=async,subvol=@ /dev/mapper/cryptroot /mnt
mkdir -p /mnt/{home,boot,efi}
mount -o noatime,ssd,compress=zstd,space_cache=v2,discard=async,subvol=@home /dev/mapper/cryptroot /mnt/home
mount /dev/nvme0n1p1 /mnt/efi

Base system

pacstrap -K /mnt base base-devel linux linux-firmware btrfs-progs sudo vim networkmanager plymouth  
genfstab -U /mnt >> /mnt/etc/fstab
arch-chroot /mnt

Drop plymouth if you don't want a splash

Inside the chroot, set time, locale, hostname, and users:

ln -sf /usr/share/zoneinfo/Region/City /etc/localtime
hwclock --systohc
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
locale-gen
echo "LANG=en_US.UTF-8" > /etc/locale.conf
echo "nexus" > /etc/hostname
passwd
useradd -m -G wheel xero && passwd xero
EDITOR=vim visudo   # enable wheel sudo
systemctl enable NetworkManager

systemd-boot and UKI

Install systemd-boot to the EFI partition we mounted at /efi:

bootctl install --esp-path=/efi

Use systemd-style hooks for mkinitcpio so the initramfs aligns with UKI boot:

sed -i 's/^HOOKS=.*/HOOKS=(base systemd plymouth autodetect microcode modconf kms keyboard keymap sd-vconsole block sd-encrypt filesystems fsck)/' /etc/mkinitcpio.conf 

Again drop plymouth if you don't want splash screen

Preset to emit a UKI (edit /etc/mkinitcpio.d/linux.preset):

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

PRESETS=('default')

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

Write the kernel command line to /etc/kernel/cmdline with your own UUIDs from blkid:4

rd.luks.name=root-uuid=cryptroot root=/dev/mapper/cryptroot rd.luks.name=swap-uuid=cryptswap rootflags=subvol=@ rw resume=/dev/mapper/cryptswap

Plymouth splash (optional but works with UKI)

Inside the chroot, add quiet splash to /etc/kernel/cmdline next to your LUKS/resume args. The hook order above already puts plymouth before sd-encrypt; just regenerate initramfs when you change the cmdline:

mkinitcpio -P
bootctl update

Zswap (optional)

If RAM is tight or you want compressed swap, add these to /etc/kernel/cmdline on the same line as the LUKS/resume args (spaces between each item):

zswap.enabled=1 zswap.shrinker_enabled=1 zswap.compressor=lz4 zswap.max_pool_percent=30 zswap.zpool=zsmalloc rd.luks.name=swap-uuid=cryptswap

Build and keep entries fresh:

mkinitcpio -P
bootctl update
systemctl enable systemd-boot-update.service

Verify and reboot

  • bootctl list shows the UKI entry (and kernel version) you expect.
  • /efi/EFI/Linux/arch-linux.efi exists with a fresh timestamp.
  • Reboot: enter the LUKS passphrase, watch Plymouth if enabled, land on @, and check that hibernate/resume works from the encrypted swap by using this command:
sudo systemctl hibernate

Footnotes

  1. Arch Wiki: Swap

  2. Arch Wiki: EFI system partition

  3. Arch Wiki: Dm-crypt/Encrypting an entire system

  4. Arch Wiki: Power management/Suspend and hibernate