Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@speedybunny
Created November 30, 2022 15:32
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save speedybunny/b5f65a4f55af03563cd05ebbb3410225 to your computer and use it in GitHub Desktop.
Save speedybunny/b5f65a4f55af03563cd05ebbb3410225 to your computer and use it in GitHub Desktop.
Arch Linux with encrypted `/boot` and detached LUKS2 header

Arch Linux with encrypted /boot and detached LUKS2 header

WARNING: backup your files before beginning!

Setup

USB stick /dev/sdb:

  • /dev/sdb1: non-encrypted EFI System Partition (ESP)
  • /dev/sdb2: LUKS2 encrypted partition that contains the /boot partition

Drive /dev/sda: entirely encrypted with LUKS2. The LUKS2 header will be detached (not stored at the beginning of the drive). Arch Linux will be installed on the first partition (formatted as Ext4 or Btrfs) and additional partitions can be added as needed.

Only the USB key passphrase will be required to unlock all the partitions. The keyfile and the LUKS2 detached header will be stored in the initramfs, which is itself stored in the /boot partition.

Boot process

Completed from the Arch Linux wiki.

  1. POST
  2. UEFI launch
  3. UEFI identifies /dev/sdb1 as an ESP and launches EFI\GRUB\grubx64.efi
  4. GRUB unlocks /dev/sdb2 with the cryptomount command and accesses the /boot partition
  5. GRUB reads /boot/grub/grub.cfg and displays the OS selection splash screen
  6. GRUB boots the kernel (vmlinux image)
  7. The kernel loads the initramfs
  8. initramfs, using the keyfiles and the LUKS2 detached header it stores, unlocks /dev/sdb2 and /dev/sda
  9. Late userspace launch: fstab mounts the /boot and Arch Linux partitions

Note: the ESP contains the GRUB EFI application while the /boot partition contains the GRUB configuration file. The ESP will be mounted on /efi (not /boot or /boot/efi).

WARNING: backup your files before beginning!

Creating the /boot partition

Securely wipe the USB stick first, even if it is new.

Create a GPT partition table and the necessary partitions:

# fdisk /dev/sdb -> g (creates a GPT partition table, required for UEFI)
                 -> n then +512M (creates partition 1 of size 512MiB)
                 -> n (creates partition 2)
                 -> t then 1 (changes the type of partition 1 to ESP)
                 -> w (writes the changes to disk)

Format the ESP /dev/sdb1 as FAT32:

# mkfs.fat -F 32 /dev/sdb1

Encrypt the /dev/sdb2 partition with LUKS2 and then format it as Ext4:

# cryptsetup --type luks2 \
             --cipher aes-xts-plain64 \
             --key-size 512 \
             --pbkdf pbkdf2 \
             --hash sha512 \
             --iter-time 5000 \
             --verify-passphrase \
             luksFormat /dev/sdb2

# cryptsetup open /dev/sdb2 boot

# mkfs.ext4 /dev/mapper/boot

N.B. : use PBKDF2 instead of Argon2 as the latter is not officially supported by GRUB 2.06 (alternatively, you can install the patched version grub-improved-luks2-git from the AUR).

Preparing the drive

Securely wipe the drive first, even if it is new.

Create a keyfile and the detached header, and encrypt the drive:

# dd if=/dev/urandom of=/root/cryptroot_key.img bs=512 count=4 iflag=fullblock

# truncate -s 16M /root/cryptroot_header.img

# cryptsetup --type luks2 --cipher aes-xts-plain64 --hash sha512 --iter-time 5000 --key-size 512 --pbkdf argon2id --use-urandom --verify-passphrase luksFormat /dev/sda --header=/root/cryptroot_header.img --key-file=/root/cryptroot_key.img

Create a partition table on the drive and a new partition for Arch Linux (Ext4 here):

# cryptsetup open /dev/sda root

# fdisk /dev/mapper/root -> g
                         -> n (repeat to create multiple partitions)
                         -> w

# mkfs.ext4 /dev/mapper/root-part1

Note: for Btrfs, follow steps 7 to 9 in this guide.

Installing the partitions

Mount the partitions then chroot:

# mount /dev/mapper/root-part1 /mnt

# mount /dev/mapper/boot /mnt/boot

# mount /dev/sdb1 /mnt/efi

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

# arch-chroot /mnt

Follow the official installation guide until Initramfs.

Setting up initramfs

Avoid asking the /boot partition passphrase twice

Corresponding section of the Arch Linux wiki

GRUB asks for the passphrase of /dev/sdb2 but does not communicate it to the initramfs. To avoid that the latter asks for it again, add a keyfile to /dev/sdb2 and store it in the initramfs:

# dd if=/dev/urandom of=/root/cryptboot_key.img bs=512 count=4 iflag=fullblock

# cryptsetup --cipher aes-xts-plain64 \
             --pbkdf argon2id \
             --hash sha512 \
             --iter-time 5000 \
             luksAddKey /dev/sdb2 /root/cryptboot_key.img

Configuring /etc/mkinitcpio.conf

Add ext4 to the module list so that the initramfs can read the keyfiles and the LUKS2 detached header from the USB stick:

MODULES=(ext4)

Store the keyfiles and the header in the initramfs:

FILES=(/root/cryptboot_key.img /root/cryptroot_key.img /root/cryptroot_header.img)

Use sd-encrypt in the hook chain:

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

Unlocking the partitions

Corresponding section of the Arch Linux wiki

Find the identifiers of /dev/sda and /dev/sdb2 with # ls -l /dev/disk/by-id, then create /etc/crypttab.initramfs with the following content:

cryptboot /dev/disk/by-id/id-of-sdb2 /root/cryptboot_key.img
cryptroot /dev/disk/by-id/id-of-sda /root/cryptroot_key.img header=/root/cryptroot_header.img

Generating the initramfs

# mkinitcpio -P

Installing GRUB >= 2.06

Note: the settings in /etc/default/grub (notably the kernel parameters) do not need to be changed.

Install the necessary packages:

# pacman -S grub efibootmgr

Install GRUB to the ESP with the modules needed to unlock /dev/sdb2, in order to access the /boot partition:

# grub-install --target=x86_64-efi --efi-directory=/efi --modules="luks2 part_gpt cryptodisk gcry_rijndael pbkdf2 gcry_sha512" --bootloader-id=GRUB

Generate the GRUB configuration file:

# grub-mkconfig -o /boot/grub/grub.cfg

Unlocking the /boot partition

Corresponding section of the Arch Linux wiki

Find the UUID identifier of /dev/sdb2 with # fdisk -l then create the file /boot/grub/grub_sdb2.conf:

cryptomount -u UUID-dev-sdb2

set prefix=(crypto0)/grub
set root=(crypto0)

insmod normal
normal

Generate the GRUB EFI image and install it to ESP:

# grub-mkimage -p '(crypto0)/grub' -O x86_64-efi -c /boot/grub/grub_sdb2.conf -o /tmp/grubx64.efi luks2 ext2 part_gpt cryptodisk gcry_rijndael pbkdf2 gcry_sha512

# install -v /tmp/grubx64.efi /efi/EFI/GRUB/grubx64.efi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment