How to Install Arch Linux with LUKS
In this guide we will see how to install a minimal Arch Linux system on a UEFI x86_64 machine with LUKS encryption. The setup uses an “almost full”
disk layout, meaning that the root partition will be encrypted while the boot partition will remain unencrypted. We will also configure the bootloader using systemd-boot.
Before proceeding, download the relevant ISO files from the Arch website and flash it on a spare USB drive.
Networking
I will assume that you already have an established Internet connection. To check whether everything is working, try to send some ICMP packets:
# ping google.com -c 4
PING google.com (142.251.110.102) 56(84) bytes of data.
64 bytes from bz-in-f102.1e100.net (142.251.110.102): icmp_seq=1 ttl=111 time=45.9 ms
64 bytes from bz-in-f102.1e100.net (142.251.110.102): icmp_seq=2 ttl=111 time=46.0 ms
64 bytes from bz-in-f102.1e100.net (142.251.110.102): icmp_seq=3 ttl=111 time=44.7 ms
64 bytes from bz-in-f102.1e100.net (142.251.110.102): icmp_seq=4 ttl=111 time=45.6 ms
--- google.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3002ms
rtt min/avg/max/mdev = 44.670/45.544/45.992/0.521 ms
Also, before proceeding, synchronize your system clock using NTP.
# timedatectl set-ntp true
Disk Partition
As mentioned earlier, we will encrypt the root partition while leaving the boot one (which will also include the bootloader) unencrypted. In other words, we want to create the following partitions:
| Name | Type | Mount Point | Size |
|---|---|---|---|
/dev/nvme0n1p1 |
EFI | /boot |
1 GiB |
/dev/nvme0n1p2 |
LUKS | n/a |
100 % |
You can create them using fdisk(8). Once created, format them with the following commands:
# mkfs.vfat -F32 /dev/nvme0n1p1
# cryptsetup luksFormat /dev/nvme0n1p2 # Create
# cryptsetup luksOpen /dev/nvme0n1p2 root # Open
# mkfs.ext4 /dev/mapper/root # Format
After that we can mount these partitions on /mnt:
# mount /dev/mapper/root /mnt
# mkdir -p /mnt/boot
# mount /dev/nvme0n1p1 /mnt/boot
Repository settings
Before bootstrapping the system, it’s advisable to update the /etc/pacman.d/mirrorlist file using a tool such as rankmirror(8). To do that,
first install the pacman-contrib package on the live system and then retrieve the fastest mirrors for your location:
# pacman -Sy pacman-contrib
# rankmirrors -v -n 5 /etc/pacman.d/mirrorlist > /tmp/mirrors
Finally, use the /tmp/mirrors file as the mirror list:
# mv /tmp/mirrors /etc/pacman.d/mirrorlist
# pacman -Sy
Bootstrapping
We are now ready to install the base system. To do that, issue the following command:
# pacstrap -i -K /mnt base linux-lts linux-firmware vim dhcpcd sudo
Once done, we need to generate an fstab file. Instead of doing it manually, we can use the following neat utility.
# genfstab -U /mnt >> /mnt/etc/fstab
Then let’s change the root directory to /mnt:
# arch-chroot /mnt
Configure the system
Let’s start by configuring the timezone:
(chroot)# ln -sf /usr/share/zoneinfo/<AREA>/<LOCATION> /etc/localtime
(chroot)# hwclock --systohc
(chroot)# timedatectl set-ntp true
Then, let’s configure localization:
(chroot)# vim /etc/locale.gen # Edit accordingly
(chroot)# locale-gen
(chroot)# echo "LANG=en_US.UTF-8" > /etc/locale.conf
Now the hostname:
(chroot)# echo "<HOSTNAME>" > /etc/hostname
(chroot)# vim /etc/hosts # Add <HOSTNAME> to 127.0.0.1
And finally the users:
(chroot)# passwd
(chroot)# useradd -m -G wheel,video,audio -s /bin/bash <USER_NAME>
(chroot)# passwd <USER_NAME>
(chroot)# EDITOR=vim visudo # Uncomment '%wheel...' part
Do not forget to enable the DHCP daemon (dhcpcd(8)) using systemctl enable dhcpcd.
Bootloader and initramfs
Let’s now move on the most delicate part of the whole guide. The outcome of this section will determine whether the system will be able to
boot or not. As stated at the begin of the post, we will use systemd-boot(7).
Let’s start by configuring the initial ram disk. This small file system includes the components needed by the kernel to unlock and mount the root partition. In our case, we will need to instruct the system to include the “encrypt” module every time this file systems gets rebuilt.
To do that, we can edit the /etc/mkinitcpio.conf file by adding the following values.
HOOKS=(base systemd autodetect microcode modconf kms keyboard keymap consolefont block sd-encrypt filesystems fsck)
That is, we need to add the systemd and the sd-encrypt (systemd-encrypt) hooks in the HOOKS array.
Arch Linux also requires you to specify the keymap in use by editing the /etc/vconsole.conf file:
KEYMAP=us
After that, generate a new initramfs file with the following command:
(chroot)# mkinitcpio -P
Then, we can procceed by configuring the bootloader. First of all, we need to install it on the /boot directory:
(chroot)# bootctl --path=/boot install
Then, let’s edit the /boot/loader/loader.conf file by adding the following content:
default arch-lts
timeout 3
editor 0
With the previous settings, the bootloader will look for a loader called arch-lts.conf, let’s create it:
(chroot)# cat /boot/loader/entries/arch-lts.conf
title Arch Linux (LTS)
linux /vmlinuz-linux-lts
initrd /initramfs-linux-lts.img
options rd.luks.name=<ROOT_UUID>=root rd.luks.options=discard root=/dev/mapper/root rw
Where the <ROOT_UUID> placeholder must be replaced with the UUID of the root partition. This value can be retrieved with:
(chroot)# lsblk -o name,fstype,uuid,mountpoints
NAME FSTYPE UUID MOUNTPOINTS
nvme0n1
├─nvme0n1p1 vfat 25TF-ARZ9 /boot
└─nvme0n1p2 crypto_LUKS f1911b3b-88b7-4470-a067-40ab9f995b8b
└─root ext4 ca985a40-96ac-43b8-8d31-3515d072596a /
In the previous example, the relevant UUID is f1911b3b-88b7-4470-a067-40ab9f995b8b (the second-to-last).
Finally, run the following command to validate the loaders:
(chroot)# bootctl status
Available Boot Loaders on ESP:
ESP: /boot
File: ├─/boot//EFI/systemd/systemd-bootx64.efi (systemd-boot 260.1-1-arch)
└─/boot//EFI/BOOT/BOOTX64.EFI (systemd-boot 260.1-1-arch)
Boot Loader Entry Locations:
ESP: /boot ($BOOT)
config: /boot//loader/loader.conf
token: arch
Default Boot Loader Entry:
type: Boot Loader Specification Type #1 (.conf)
title: Arch Linux (LTS)
id: arch-lts.conf
source: /boot//loader/entries/arch-lts.conf (on the EFI System Partition)
linux: /boot//vmlinuz-linux-lts
initrd: /boot//initramfs-linux-lts.img
options: rd.luks.name=f1911b3b-88b7-4470-a067-40ab9f995b8b=root rd.luks.options=discard root=/dev/mapper/root rw
TRIM support
The rd.luks.options=discard option of the previous section will enable TRIM support.
These flags allow the kernel to pass TRIM commands to the drive’s firmware, which are
used to perform essential maintenance operations such as garbage collection and cell wear optimization. While this feature is important for
maintaining optimal performance over time, it can potentially leak metadata, revealing unused block information that may be used to identify
the filesystem in use.
For this reason, cryptsetup developers advise against enabling such feature in all those scenarios where maximum privacy is required. In any other cases, leaving this option enabled will ensure long-term SSD health. More information about this topic can be found on the Arch wiki.
Reboot
After that we can exit from the chroot environment, umount the partitions using:
# umount -R /mnt
And then reboot the system.
That’s it. Enjoy your encrypted Arch Linux installation! 😉