Skip to content

Instantly share code, notes, and snippets.

@apsun
Last active November 21, 2023 20:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save apsun/1f7b1da40b028a9ed1e0409ca8c3b3cc to your computer and use it in GitHub Desktop.
Save apsun/1f7b1da40b028a9ed1e0409ca8c3b3cc to your computer and use it in GitHub Desktop.

Encrypted Arch Linux on UEFI

This documents how to install Arch Linux with full disk encryption under UEFI (not using secure boot, although it will be easy to enable later on if you want it). It assumes you're familiar with installing Arch Linux, but new to encryption/UEFI.

Partition the disk

Boot into the Arch Linux live USB and enter the installation environment.

Hereafter, /dev/sda refers to the disk you are installing Arch on. /dev/sda1 refers to the EFI system partition, and /dev/sda2 refers to the encrypted Linux partition.

  1. Run gdisk /dev/sda. Create the GPT (o), then create two partitions (n):
    • EFI system partition (hex code EF00, size 550MiB)
    • Linux LUKS partition (hex code 8309, fill remainder of disk)
    • Commit the changes with w when you're done
  2. Create a FAT32 filesystem on the EFI system partition (mkfs.fat -F32 /dev/sda1)
  3. Create a LUKS container on the Linux partition:
    • Encrypt the partition (cryptsetup -y -v luksFormat /dev/sda2)
    • Open the partition as "cryptroot" (cryptsetup open /dev/sda2 cryptroot)
    • Create your ext4 filesystem on top (mkfs.ext4 /dev/mapper/cryptroot)
  4. Mount the partitions
    • Linux (mount /dev/mapper/cryptroot /mnt)
    • ESP (mkdir /mnt/boot; mount /dev/sda1 /mnt/boot)

Steps 2-4 are taken from the LUKS on a partition section on the wiki.

Install the system

Follow the installation guide from the wiki. Stop after configuring the hostname.

Create a user account

This will create a new account, set its password, and enable sudo:

useradd -m -G wheel ${YOUR_UNIXNAME}
passwd ${YOUR_UNIXNAME}
visudo  # uncomment the relevant line

Configure the network

For an Ethernet connection, put this in /etc/systemd/network/20-wired.network (note the .network extension, not .conf):

[Match]
Name=en*

[Network]
DHCP=yes

[DHCPv4]
UseDNS=no
UseNTP=no

[DHCPv6]
UseDNS=no
UseNTP=no

[IPv6AcceptRA]
UseDNS=no

The DHCPv4, DHCPv6, and IPv6AcceptRA sections are optional, and are only needed if you want to use a custom DNS server instead of the router advertised value. Next, enable the systemd units:

systemctl enable systemd-networkd
systemctl enable systemd-resolved

Configure the initramfs

Edit /etc/mkinitcpio.conf and change the HOOKS=(...) line to:

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

This makes the partition decryption password prompt work. Note that we put keyboard before autodetect to ensure that all drivers are loaded. This is especially important if you have a laptop with an external keyboard.

Note that this configures your initramfs to use systemd (sd-encrypt supports echoing * when entering the password, unlike busybox). If you want the busybox-based initramfs, use this instead:

HOOKS=(base udev keyboard autodetect modconf block encrypt filesystems fsck)

You may also want to add your video driver to /etc/mkinitcpio.conf too, to enable modesetting early in boot. This prevents Xorg "no screens found" race condition errors at startup. See the early KMS start section in the wiki. tl;dr, change the MODULES=() line to:

MODULES=(amdgpu)

(replace amdgpu with the driver for your GPU).

Generate a unified kernel image

Follow the steps on the unified kernel image wiki page. For the kernel cmdline, do not copy /proc/cmdline (that will give you the cmdline of the archiso). Instead, you'll need to specify how to decrypt the root partition.

First, find the UUID of your /dev/sda2 partition (not the encrypted container):

blkid -s UUID -o value /dev/sda2

Then, add this to /etc/kernel/cmdline along with your other kernel cmdline options. For a systemd-based initramfs, that is:

luks.name=${YOUR_PARTITION_UUID}=cryptroot root=/dev/mapper/cryptroot rw quiet

If you choose to use a busybox-based initramfs, use this instead:

cryptdevice=UUID=${YOUR_PARTITION_UUID}:cryptroot root=/dev/mapper/cryptroot rw quiet

Finally, run mkinitcpio -P to generate the unified kernel image, then bootctl install to install systemd-boot. It will automatically detect the unified kernel image, so no configuration is required.

Success!

Exit the chroot, unmount everything, and reboot. You should be presented with a decryption prompt. Your system is now ready to use!

Shrinking the partition

Suppose that at a later time, you wish to shrink the encrypted partition.

Boot into the Arch Linux live USB again, and open the encrypted partition (but don't mount the filesystem):

cryptsetup open /dev/sda2 cryptroot

Determine how large you want your filesystem to be, then figure out how many sectors (512B blocks) that is. For example, a 500GiB filesystem is 500 * 1024^3 / 512 = 1048576000 sectors. Note that LUKS adds about 16MiB of overhead on top of this, so the partition will be slightly larger than the filesystem.

Next, shrink the filesystem:

e2fsck -f /dev/mapper/cryptroot
resize2fs /dev/mapper/cryptroot ${FILESYSTEM_SIZE_IN_SECTORS}s

Note the s at the end, indicating that the unit is in sectors. Once the filesystem is resized (it may take a few minutes), shrink the LUKS volume:

cryptsetup -b ${FILESYSTEM_SIZE_IN_SECTORS} resize cryptroot

Finally, follow the steps on the Arch Wiki to resize the partition. Note that the partition size is larger than the filesystem size by however much the LUKS header is (in my case, 16MiB).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment