How to Install Arch/Artix Linux with LUKS

In this guide we will see how to install a minimal Arch or Artix 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. On Arch Linux, we will also configure the system using systemd-boot while on Artix Linux, we will use GRUB2. The Artix parts of this tutorial will assume the OpenRC init system, but we can just as easily choose an alternative one such as dinit, runit, or s6.

Before proceeding, download the relevant ISO files from either Arch website or from Artix 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. On Arch, that is:

# timedatectl set-ntp true

While on Artix:

# rc-service ntpd start

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

Artix settings

Artix does a great job of mirroring a lot of software found on the Arch repository without the systemd. However, some packages might not be available on the world repository. In order to prevent this, we can enable Arch’s extra repository AFTER the standard Artix repositories. In order to do that, follow these steps:

  1. Install the artix-archlinux-support package, which includes the Arch Linux signing keys and some dummy packages;
  2. Add the following fields on the /etc/pacman.conf file AFTER the Artix repositories:
#
# Artix
#
[system]
Include = /etc/pacman.d/mirrorlist

#[world-gremlins]
#Include = /etc/pacman.d/mirrorlist

[world]
Include = /etc/pacman.d/mirrorlist

#[galaxy-gremlins]
#Include = /etc/pacman.d/mirrorlist

[galaxy]
Include = /etc/pacman.d/mirrorlist

# If you want to run 32 bit applications on your x86_64 system,
# enable the lib32 repositories as required here.

#[lib32-gremlins]
#Include = /etc/pacman.d/mirrorlist

#[lib32]
#Include = /etc/pacman.d/mirrorlist

#
# Arch <-- Add this
#
[extra]
Include = /etc/pacman.d/mirrorlist-arch
  1. Download an updated Arch mirrorlist:
# wget https://archlinux.org/mirrorlist/all/ -O /etc/pacman.d/mirrorlist-arch
  1. Populate the Arch Linux keyring with pacman-key --populate archlinux;
  2. Synchronize the repositories with: pacman -Sy.

Keep in mind that Artix developers don’t officially support Arch repository, so you are choosing to use them at your own risk. Keep also in mind that this same procedure must be repeated once the system has been bootstrapped.

Bootstrapping

We are now ready to install the base system. If you are running Arch, issue the following command:

# pacstrap -K /mnt base linux-lts linux-firmware vim dhcpcd sudo

On Artix Linux, instead, issue the following command:

# basestrap -i /mnt base openrc elogind-openrc linux-lts linux-firmware vim ntp ntp-openrc dhcpcd dhcpcd-openrc grub efibootmgr sudo cryptsetup

The -i flag will wait for your input before proceeding. This is very useful when using Arch repositories on an Artix installation (although if you have respected the suggested order, Artix repositories should take precedence over Arch ones).

Once done, we need to generate an fstab file. Instead of doing it manually, we can use the following neat utility.

On Arch:

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

On Artix:

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

Then let’s change the root directory to /mnt. On Arch, that is:

# arch-chroot /mnt

On Artix, instead:

# artix-chroot /mnt

Configure the system

The rest of this section is about the same for both Arch and Artix. The only difference is the command used to enable daemons at boot. On Arch that is systemctl enable <DAEMON> while on Artix that is rc-update add <DAEMON> default.

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 # on Arch
(chroot)# rc-update add ntpd # on Artix

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

Now it’s also the right time to reconfigure the Arch Linux repositories (on Artix) if you’ve chosen to enable them as described on this part of the guide.

Do not forget to enable the DHCP daemon (dhcpcd(8)) using distro-specific commands.

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 highlight two different paths according to the chosen distribution. On Arch Linux, we will use systemd-boot(7) while on Artix Linux we will use GRUB.

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.

On Arch:

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

On Artix:

HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt filesystems fsck)

That is, we need to either add the systemd and the sd-encrypt (systemd-encrypt) hooks or the udev and the encrypt hooks on the HOOKS array.

On Arch Linux you also have 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. Let’s start with systemd-boot.

Arch Linux

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

Artix Linux

We will now replicate the same setup using GRUB. Let’s edit the /etc/default/grub file by adding the following two lines:

[...]
GRUB_CMDLINE_LINUX_DEFAULT="cryptdevice=UUID=<ROOT_UUID>:root:allow-discards"
GRUB_ENABLE_CRYPTODISK=y
[...]

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).

Then let’s install GRUB on the boot partition using the following command:

(chroot)# grub-install --target=x86_64-efi --efi-directory=/boot --recheck
(chroot)# grub-mkconfig -o /boot/grub/grub.cfg

TRIM support

The rd.luks.options=discard option and the allow-discards 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/Artix installation! 😉