Skip to content

Installing Arch Linux with Btrfs, systemd-boot and LUKS

My preferred Arch Linux setup is with Btrfs, systemd-boot (which requires UEFI) and - at least when installing a laptop - LUKS. Not least for myself, to make the installation easier the next time, I thought that it's a good idea to document the steps.

Note

This post describes the creation and usage of a swap file, but that's optional.

Using SSH

If you have another PC, it's convenient to do the installation from this PC via SSH because then you can have browser windows with installations guides open in parallel and easily copy and paste commands. To do so, boot the PC that you want to install from the Arch Linux ISO.

Start SSH:

systemctl start sshd.service

Set a password for root:

passwd

Look up the IP address of the PC:

ip addr

Now, on the second PC, call into the first PC via SSH:

ssh root@<IP-OF-THE-FIRST-PC>

and continue with the installation.

Partitioning

Note

For the rest of this post, we assume that we install Arch Linux on an SSD with the device path /dev/nvme0n1.

Adjust the steps for your setup if necessary.

gdisk /dev/nvme0n1

Create new partition table:

Command (? for help): o

Create an EFI partition (choose size 512M and hex code EF00):

Command (? for help): n

Create a root partition (adopt the default values):

Command (? for help): n

Write the new partitions to disk:

Command (? for help): w

Encryption

Create an encrypted container for the root file system (you need to define a passphrase):

cryptsetup luksFormat /dev/nvme0n1p2

Open the container ("root" is just a placeholder, you can use a name of your choice, but remember to adopt the subsequent steps of the guide accordingly):

cryptsetup open /dev/nvme0n1p2 root

Create file systems

Format the EFI partition with FAT32 and give it the label EFI - you can choose any other label name:

mkfs.vfat -F32 -n EFI /dev/nvme0n1p1

Format the root partition with Btrfs and give it the label SYSTEM - you can choose any other label name. If you didn't open the LUKS container under the name "root" you must adjust the command accordingly:

mkfs.btrfs -L SYSTEM /dev/mapper/root

Create and mount subvolumes

Note

If you don't want to use a swap file, it is not required to create and mount the subvolume @swap.

Create subvolumes for root, home, cache, log, tmp, and snapshots (cache, log and tmp get separate subvolumes since I want to be able to create snapshots of root without all the temporary and cached data of /var/cache, /var/log and /var/tmp) :

mount /dev/mapper/root /mnt
btrfs sub create /mnt/@
btrfs sub create /mnt/@home
btrfs sub create /mnt/@cache
btrfs sub create /mnt/@log
btrfs sub create /mnt/@tmp
btrfs sub create /mnt/@snapshots
btrfs sub create /mnt/@swap
umount /mnt

Mount the subvolumes:

mount --mkdir -o noatime,compress=zstd,space_cache=v2,ssd,discard=async,subvol=@ /dev/mapper/root /mnt
mount --mkdir -o noatime,compress=zstd,space_cache=v2,ssd,discard=async,subvol=@home /dev/mapper/root /mnt/home
mount --mkdir -o noatime,compress=zstd,space_cache=v2,ssd,discard=async,subvol=@cache /dev/mapper/root /mnt/var/cache
mount --mkdir -o noatime,compress=zstd,space_cache=v2,ssd,discard=async,subvol=@log /dev/mapper/root /mnt/var/log
mount --mkdir -o noatime,compress=zstd,space_cache=v2,ssd,discard=async,subvol=@tmp /dev/mapper/root /mnt/var/tmp
mount --mkdir -o noatime,compress=zstd,space_cache=v2,ssd,discard=async,subvol=@snapshots /dev/mapper/root /mnt/.snapshots
mount --mkdir -o noatime,compress=no,space_cache=v2,ssd,discard=async,subvol=@swap /dev/mapper/root /mnt/swap

Note

If your disk is not an SSD, remove the mount options ssd and discard=async.

Mount the EFI partition

mount --mkdir /dev/nvme0n1p1 /mnt/boot

Create swap file (taken from Btrfs - Swap file and Swap file):

chattr +C /mnt/swap
fallocate -l <FILE-SIZE-IN-GiB>G /mnt/swap/swapfile
chmod 600 /mnt/swap/swapfile
mkswap /mnt/swap/swapfile
swapon /mnt/swap/swapfile

Base system and /etc/fstab

Install Arch Linux (adjust this list to your needs):

pacstrap /mnt linux linux-firmware base intel-ucode btrfs-progs efibootmgr gptfdisk dosfstools nano

Generate /etc/fstab:

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

Enable periodic trim

To enable periodic trim, execute

systemctl --root=/mnt enable fstrim.timer

Note

If your disk is not an SSD, you do not need this.

System configuration

Since I want a German system the following steps are according to that. Adjust them to your needs.

chroot into the new system:

arch-chroot /mnt/

Set host name:

echo <YOUR-HOSTNAME> > /etc/hostname

Set locale:

echo LANG=de_DE.UTF-8 > /etc/locale.conf

Uncomment the following rows of /etc/locale.gen:

#de_DE.UTF-8 UTF-8
#de_DE ISO-8859-1
#de_DE@euro ISO-8859-15

Generate locale:

locale-gen

Set keyboard layout and font:

echo KEYMAP=de-latin1 > /etc/vconsole.conf
echo FONT=lat9w-16 >> /etc/vconsole.conf

Set time zone:

ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime

Define hosts in /etc/hosts:

#<ip-address>   <hostname.domain.org>       <hostname>
127.0.0.1       <YOUR-HOSTNAME>.localdomain <YOUR-HOSTNAME>
::1             localhost.localdomain       localhost

Set root password:

passwd

Initramfs

Configure the creation of initramfs by editing /etc/mkinitcpio.conf. Change the line HOOKS=... to:

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

Note

  • Here, we are using a systemd based ram disk
  • If you don't use a swap file, leave out the resume hook.

Recreate initramfs:

mkinitcpio -p linux

Boot manager

Install systemd-boot:

bootctl --path=/boot install

Create file /boot/loader/entries/archlinux.conf and fill it with:

title Arch Linux
linux /vmlinuz-linux
initrd /initramfs-linux.img
options rd.luks.name=<UUID-OF-SYSTEM-PARTITION>=root root=/dev/mapper/root rootflags=subvol=@ rd.luks.options=discard rw resume=/dev/mapper/root resume_offset=<SWAPFILE-OFFSET>

The offset of the swap file can be calculated with this command:

filefrag -v /swap/swapfile | awk '$1=="0:" {print substr($4, 1, length($4)-2)}'

Note

If you don't use a swap file, leave out the options resume and resume_offset.

The UUID of the root partition can be determined via:

blkid -s UUID -o value /dev/nvme0n1p2

Edit file /boot/loader/loader.conf and fill it with:

default  archlinux.conf
timeout  4
console-mode max
editor   no

Final steps

Exit chroot, unmount partitions and reboot:

exit
umount -R /mnt
reboot

Have fun with your system!

References

Comments