all posts

Setting up "simple" secure boot and encryption on Arch Linux

October 9, 2025 in guides, linux

This is a guide on how I like to set up an Arch Linux install with decently strong security and encryption. There are a ton of different ways to go about it; I opt for a lot of systemd components (they come preinstalled on Arch systems) and a configuration that requires very little manual scripting/setup.

Contents

Overview

We’ll be setting up the following:

Device requirements:

Advantages:

Consequences of this setup:

You’ll find these ArchWiki pages extremely useful:

1. Installing Arch Linux

Start off by installing Arch Linux with secure boot off, following the standard installation guide, with these points in mind:

  1. You must be booting using UEFI, not legacy BIOS boot.
  2. Allocate at least 2 GB to your EFI partition—we’ll be storing our UKIs there. (The guide recommends 1 GB but I like having extra breathing room in case I need to install alternate kernels.) Make sure you format it as FAT32.
  3. Your root and swap partitions need to have the correct GPT partition types. The default “Linux filesystem” type will not work! I’d recommend using cfdisk to partition your drive instead of fdisk.
    1. Select Linux root (x86-64) (23, 4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709) for your root partition.
    2. Select Linux swap (19, 0657FD6D-A4AB-43C4-84E5-0933C84B4F4F) for your swap partition.
  4. If you’re considering installing Windows after, leave some unallocated space for an NTFS partition.
  5. Setup your root and swap partitions for LUKS encryption before formatting them (use strong passwords!):
    cryptsetup luksFormat /dev/ROOT_PARTITION
    cryptsetup luksFormat /dev/SWAP_PARTITION
    Unlock them:
    cryptsetup open /dev/ROOT_PARTITION root
    cryptsetup open /dev/SWAP_PARTITION swap
    From now on, you’ll refer to your root partition as the device /dev/mapper/root and your swap as the device /dev/mapper/swap. These are the “virtual” devices that have decrypted data inside your LUKS-encrypted physical devices /dev/nvme0n1pX or /dev/sdaX. Format them as usual:
    mkfs.ext4 /dev/mapper/root
    mkswap /dev/mapper/swap
  6. When mounting, mount /dev/mapper/root to /mnt and your EFI partition to /mnt/boot. Swapon /dev/mapper/swap.
  7. Install systemd-ukify during system installation.
  8. Don’t run genfstab; just make an empty file: touch /mnt/etc/fstab.
  9. Create /etc/crypttab.initramfs to tell mkinitcpio to unlock your swap partition at boot. This UUID is of the encrypted swap partition /dev/nvme0n1pX or /dev/sdaX.
    swap UUID=66872a6e-f4be-456a-a697-d5a3e5999178 none tpm2-device=auto

Once you’re at the end of the installation guide, you can move on to the next section.

2. UKI setup

We will setup mkinitcpio to generate UKIs and also switch to a systemd-based init (required for later).

Write your kernel cmdline to /etc/kernel/cmdline. Because we’re going to have the system automount all of our partitions, you don’t need to specify root= or resume=. If you have nothing else to put here, this will do:

rw

Now, configure any mkinitcpio presets to generate UKIs instead of the regular initramfs/kernel combo. For example, edit /etc/mkinitcpio.d/linux.preset as follows:

# mkinitcpio preset file for the 'linux' package

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

PRESETS=('default' 'fallback')

#default_config="/etc/mkinitcpio.conf"
#default_image="/boot/initramfs-linux.img"      # <--- comment out this line
default_uki="/boot/EFI/Linux/arch-linux.efi"    # <--- uncomment this line
#default_options="..."                          # <--- optionally set options

#fallback_config="/etc/mkinitcpio.conf"
#fallback_image="/boot/initramfs-linux-fallback.img"      # <--- comment out this line
fallback_uki="/boot/EFI/Linux/arch-linux-fallback.efi"    # <--- uncomment this line
fallback_options="-S autodetect"                          # <--- set fallback options

For more info, see https://wiki.archlinux.org/title/Unified_kernel_image#.preset_file.

Edit /etc/mkinitcpio.conf to switch to systemd init.

Here’s an example:

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

Make the target directory for the UKIs:

mkdir -p /boot/EFI/Linux

Generate the UKIs:

mkinitcpio -P

3. Bootloader

We’ll be using systemd-boot: it comes free with your Arch Linux install and just works for UKIs, no configuration needed. Just run:

bootctl install

If you’d like to configure systemd-boot, see https://wiki.archlinux.org/title/Systemd-boot#Loader_configuration.

You now have a fully bootable system—we can move on to setting up secure boot.

4. Secure boot setup

Reboot your system to the BIOS settings. Enable secure boot setup mode. Save your changes and boot into Arch Linux. Enter your LUKS passwords for your root and swap partitions for now (we’ll configure automatic decryption soon, don’t worry).

After logging in, install sbctl via pacman, and use it to initialize the secure boot keys.

sbctl create-keys
sbctl enroll-keys

Verify your secure boot settings have been correctly modified:

sbctl status
# Installed:	    ✓ sbctl is installed
# Owner GUID:	    b3233451-f5d6-410d-8cd7-3e2577986870
# Setup Mode:	    ✓ Disabled
# Secure Boot:	    ✘ Disabled

Now, regenerate your initramfs with mkinitcpio -P. You should see sbctl signing the UKIs as a post-processing step.

...
...
==> Unified kernel image generation successful
==> Running post hooks
  -> Running post hook: [sbctl]
Signing /boot/EFI/Linux/arch-linux.efi
✓ Signed /boot/EFI/Linux/arch-linux.efi
==> Post processing done
...
...

Run sbctl sign-all or sbctl sign -s <file> to sign the bootloader and anything sbctl might’ve missed.

sbctl sign-all
# File has already been signed /boot/EFI/Linux/arch-linux-fallback.efi
# File has already been signed /boot/EFI/Linux/arch-linux-lts-fallback.efi
# File has already been signed /boot/EFI/Linux/arch-linux-lts.efi
# File has already been signed /boot/EFI/Linux/arch-linux.efi
# File has already been signed /boot/EFI/systemd/systemd-bootx64.efi
# File has already been signed /boot/vmlinuz-linux
# File has already been signed /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed
# File has already been signed /boot/EFI/BOOT/BOOTX64.EFI
# File has already been signed /boot/vmlinuz-linux-lts

Finally, reboot to UEFI firmware settings and enable secure boot. Fingers crossed, everything worked and you can boot without errors!

5. Encryption setup

We’ll now setup passwordless decryption for our root and swap partitions using the TPM.

First, generate the PCR keypair using ukify:

ukify genkey \
	--pcr-private-key=/etc/systemd/tpm2-pcr-private-key.pem \
	--pcr-public-key=/etc/systemd/tpm2-pcr-public-key.pem

Configure ukify to add PCR signatures during UKI generation in /etc/kernel/uki.conf:

[UKI]
# leave this section blank: sbctl signs the UKI
# for us, so we won't tell ukify to sign it.

[PCRSignature:initrd]
Phases=enter-initrd
PCRPrivateKey=/etc/systemd/tpm2-pcr-private-key.pem
PCRPublicKey=/etc/systemd/tpm2-pcr-public-key.pem

Regenerate UKIs with mkinitcpio -P. The output should look like this:

...
...
==> Creating unified kernel image: '/boot/EFI/Linux/arch-linux.efi'
  -> Using ukify to build UKI
  -> Using cmdline file: '/etc/kernel/cmdline'
Using config file: /etc/kernel/uki.conf
+ /usr/lib/systemd/systemd-measure sign --osrel=/tmp/mkinitcpio.VUn4Fq --cmdline=/tmp/mkinitcpio.sEy0Ec --uname=/tmp/tmp.unamesb2ky2s6 --pcrpkey=/etc/systemd/tpm2-pcr-public-key.pem --linux=/boot/vmlinuz-linux --initrd=/tmp/mkinitcpio.p4bPKn --sbat=/tmp/tmp.sbat20yh3m_f --private-key=/etc/systemd/tpm2-pcr-private-key.pem --public-key=/etc/systemd/tpm2-pcr-public-key.pem --phase=enter-initrd
Wrote unsigned /boot/EFI/Linux/arch-linux.efi
==> Unified kernel image generation successful
==> Running post hooks
  -> Running post hook: [sbctl]
Signing /boot/EFI/Linux/arch-linux.efi
✓ Signed /boot/EFI/Linux/arch-linux.efi
==> Post processing done
...
...

Verify the image has a PCR signature by running: ukify inspect /boot/EFI/Linux/arch-linux.efi. Check for a .pcrsig section.

Now, using systemd-cryptenroll, generate a recovery key:

systemd-cryptenroll /dev/ROOT_PARTITION --recovery-key

SAVE THE RECOVERY KEY SAFELY! If something messes with the TPM or PCRs and you can’t authenticate via password, you risk losing all data in your root partition.

Add TPM slots to your partitions. We set --tpm2-pcrs to an empty string to avoid binding to the raw value of PCR 7, which is bound by default. Optionally, add --tpm2-with-pin=true to your root partition for extra security - you’ll have to enter a PIN during startup to release the LUKS keys.

systemd-cryptenroll /dev/ROOT_PARTITION --tpm2-device=auto --tpm2-pcrs=""
systemd-cryptenroll /dev/SWAP_PARTITION --tpm2-device=auto

Optionally, delete the password slots to make the TPM and recovery key the only options to decrypt the partitions. I usually do this for the swap partition only. If you decide to keep the slots, make sure your passwords are strong!

systemd-cryptenroll /dev/ROOT_PARTITION --wipe-slot=password
systemd-cryptenroll /dev/SWAP_PARTITION --wipe-slot=password

Verify the slots for each device:

systemd-cryptenroll /dev/ROOT_PARTITION
# SLOT TYPE
#    0 password
#    1 recovery
#    2 tpm2

systemd-cryptenroll /dev/SWAP_PARTITION
# SLOT TYPE
#    1 tpm2

Reboot, and you should no longer be prompted to enter passwords to decrypt your data.

6. systemd-homed setup

systemd-homed enables encrypting your home directory on top of the root partition encryption we just set up for extra security. You can skip this section and use a traditional UNIX user if you’d prefer.

To begin, start and enable systemd-homed.service.

Create your user with LUKS encryption:

homectl create {username} --storage=luks --luks-discard=true --luks-offline-discard=true --shell=/bin/SHELL --member-of=GROUP1,GROUP2

If desired, don’t forget to give your new user sudo privileges via group or visudo.

Your home directory will now be encrypted at rest and decrypted when you login.

Rescuing home directories

If you need to decrypt your home directory from a live ISO or another machine, use these commands:

losetup -fP --show {username}.home
cryptsetup open /dev/loopXpY {mappername}
mount /dev/mapper/{mappername} {mountpoint}

7. Optional: Install Windows

Now is a good time to install Windows if you’re going to be dual booting. Keep in mind, Windows can mess with the TPM and PCRs, preventing automatic decryption. Keep an Arch Linux installer handy to rescue your system if needed.

Don’t forget the usual suspects:

You’re done!

You made it to the end! You can set up your user/desktop how you would normally now.

Remember, you can always refer to the ArchWiki for further information or help.

Thanks for reading! Happy computering!