No alternative text provided

πŸ” Dual Booting Arch Linux & Windows with Secure Boot, TPM, and Disk Encryption

πŸ” Dual Booting Arch Linux & Windows with Secure Boot, TPM, and Disk Encryption

How I set up a seamless dual boot with Arch Linux and Windows 11 using Secure Boot, LUKS encryption, and TPM for password-less unlocks πŸš€

⚠️ Warning: We’ll be messing with bootloaders and secure boot. Windows might ask you for the Bitlocker recovery key β€” ensure it's backed up on your Microsoft account before proceeding. Write it down somewhere easily accessible just in case as well.


🧰 Preparing the Disks While Installing Arch Linux

Note: Secure Boot must be disabled to boot the Arch install USB (it's unsigned with Microsoft keys).

I have two partitions:

  • nvme0n1p6: UEFI partition (512MB, vfat)
  • nvme0n1p7: Root partition (1TB, encrypted)

From the Arch Linux USB:

1cryptsetup --use-random luksFormat /dev/nvme0n1p7
2cryptsetup luksOpen /dev/nvme0n1p7 cryptlvm

Note: replace nvme0n1p7 with your partition identifier

Then LVM setup (optional if only one partition):

1pvcreate /dev/mapper/cryptlvm
2vgcreate vg0 /dev/mapper/cryptlvm
3lvcreate -l +100%FREE vg0 --name root
4mkfs.ext4 /dev/vg0/root

Mount everything:

1mount /dev/vg0/root /mnt
2mount --mkdir /dev/nvme0n1p6 /mnt/boot/efi
3mount --mkdir /dev/nvme0n1p1 /mnt/boot/efiwin # Windows EFI

Then proceed with pacstrap and regular install steps...


🧩 Configuring Bootloader, Secure Boot & Unified Kernel Image

Install needed tools:

1pacman -S sbctl efibootmgr edk2-shell tpm2-tss

Copy UEFI shell to Windows EFI partition:

1cp /usr/share/edk2-shell/x64/Shell_Full.efi /boot/efiwin/shellx64.efi

mkinitcpio Config

Here we will configure mkinitcpi so that it created a unified kernel image (UKI).

Edit /etc/mkinitcpio.conf:

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

Edit /etc/kernel/cmdline:

1rw rd.luks.name=<UUID>=cryptlvm rd.luks.options=<UUID>=tpm2-device=auto root=/dev/vg0/root loglevel=3 quiet bgrt_disable

Replace <UUID> with your LUKS partition UUID (blkid -o list to find it).

The rd.luks.options part is to tell systemd to use tpm2 if available, otherwise it will default to password.

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

1# mkinitcpio preset file for the 'linux' package
2
3ALL_config="/etc/mkinitcpio.conf"
4ALL_kver="/boot/vmlinuz-linux"
5ALL_microcode="/boot/*-ucode.img"
6
7PRESETS=('default' 'fallback')
8
9#default_config="/etc/mkinitcpio.conf"
10default_image="/boot/initramfs-linux.img"
11default_uki="/boot/efi/EFI/Linux/arch-linux.efi"
12default_options="--splash /usr/share/systemd/bootctl/splash-arch.bmp"
13
14#fallback_config="/etc/mkinitcpio.conf"
15fallback_image="/boot/initramfs-linux-fallback.img"
16fallback_uki="/boot/efi/EFI/Linux/arch-linux-fallback.efi"
17fallback_options="-S autodetect"

Create EFI dir & generate UKI:

1mkdir -p /boot/efi/EFI/Linux
2mkinitcpio -p linux

🧱 Installing systemd-boot on Windows EFI Partition

Now that we have our unified kernel image, let's install and configure our bootloader (systemd-boot). I'm installing the bootloader on Windows' EFI partition because it breaks Bitlocker if Windows is not booted from a bootloader on the same partition as it's own bootloader. It's not a problem for Linux though, so we will chainload our UKI from Windows's EFI partition.

1bootctl --esp-path=/boot/efiwin install

/boot/efiwin/loader/loader.conf:

1timeout 3
2default @saved
3console-mode max

/boot/efiwin/loader/entries/arch.conf:

1title   Arch
2efi     /shellx64.efi
3options -nointerrupt -nomap -noversion HD0g:EFI\Linux\arch-linux.efi

HD0g corresponds to disk 0, partition 7 (g = 7th letter of the alphabet). You can also boot to the UEFI shell and issue the map command to find out what's your identifier for your luks partition.

You don’t need to manually configure Windows β€” systemd-boot detects it.

Create UEFI boot entry:

1efibootmgr --create --disk /dev/nvme0n1 --part 1 --label "Systemd-boot" --loader 'EFI\systemd\systemd-bootx.efi' --unicode

That's it, now systemd-boot is installed and configured. We now need to set up secure boot.


πŸ” Secure Boot: Creating & Enrolling Keys

1sbctl create-keys
2sbctl enroll-keys -m  # Keep Microsoft keys too

Sign boot-related binaries:

1sbctl sign -s -o /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed /usr/lib/systemd/boot/efi/systemd-bootx64.efi
2sbctl sign -s /boot/efiwin/EFI/systemd/systemd-bootx64.efi
3sbctl sign -s /boot/efi/EFI/Linux/arch-linux.efi
4sbctl sign -s /boot/efi/EFI/Linux/arch-linux-fallback.efi
5sbctl sign -s /boot/efiwin/shellx64.efi

Verify everything:

1sbctl verify

We have signed all the components of our boot chain, so we should be good to go.


🧠 Enabling TPM Unlock for Encrypted Disk

We do this so that we don't have to type a password to unlock our LUKS partition at every boot of Linux.

Check current slots:

1systemd-cryptenroll /dev/nvme0n1p7

Enroll TPM:

1systemd-cryptenroll --tpm2-device=auto /dev/nvme0n1p7 --tpm2-pcrs=7

(Optional) Enroll a recovery key:

1systemd-cryptenroll /dev/nvme0n1p7 --recovery-key

Now, Linux should be able to boot without asking us a password, unless the secure boot configuration is messed up with. If that happens, you may need to enroll tpm again. Note also that you can vary the pcrs values to change the conditions when the tpm key will be erased.


πŸ₯³ Final Tips

  • Reboot and select your Systemd-boot entry
  • You should see both Windows and Arch entries + the UEFI shell
  • Try to boot in Arch. If it fails to boot, use e to edit entry manually (e.g., fix HD0g), or boot back into your USB key to review above config.

If Arch boots, you can then try to enable Secure Boot again and to boot into Windows as well. If Windows asks for the Bitlocker key, provide it once, and it should be fine after that.

Happy dual-booting! πŸŽ‰πŸ§πŸͺŸ