Base Arch Linux installation

Posted on Mar 21, 2024

This post is part of a series of posts about installing and configuring Arch Linux in a Slimbook Executive 14". I created them from a collection of personal notes, that I thought may be useful for others, so I published them through these series.

  1. Base Arch Linux installation
  2. Arch Linux network configuration

I installed Arch Linux in my new laptop, an Slimbook Executive 14". I followed the official installation guide, however, I had to dig through different pages to install it how I wanted.

My requirements were:

  • Encrypt the full disk with dm-crypt.
  • Use LVM to manage disk partitions.
  • Use ext4 file system.

Creating disk partitions

I’ve mostly followed dm-crypt/Encrypting an entire system, but I summarize here my process with the options that I chose.

The laptop has 1 TB of NVMe (Non-Volatile Memory Express) and I deliberately want to encrypt the full disk.

The dm-crypt scenario that I’ve chosen is LVM on LUKS with encrypted boot partition over:

I used the ancient fdisk to create in the only disk that the laptop has, which is mapped to the device /dev/nvme0n1, all the partitions indicated in the “preparing the disk” section of LVM on LUKS with encrypted boot partition. The partitions ended up as:

Disk /dev/nvme0n1: 931.51 GiB, 1000204886016 bytes, 1953525168 sectors
Disk model: Samsung SSD 980 PRO 1TB
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: <redacted>

Device           Start        End    Sectors   Size Type
/dev/nvme0n1p1    2048       4095       2048     1M BIOS boot
/dev/nvme0n1p2    4096    2101247    2097152     1G EFI System
/dev/nvme0n1p3 2101248 1953523711 1951422464 930.5G Linux filesystem

Let’s encrypt the second partition

# cyptsetup luksFormat --type luks1 /dev/nvme0n1p3

Now let’s mount it on /dev/mapper/cyrptlvm

# cryptsetup open /dev/nvme0n1p3 cryptlvm

Now we start with the LVM ceremony

First of all, I create a physical volume because I only have one hard disk

# pvcreate /dev/mapper/cryptlvm

Secondly, one logical groups because I don’t need an extra degree of isolation between volumes and it’s more storage efficient than having multiples groups

# vgcreate main /dev/mapper/cryptlvm

And last, but not least, three logical volumes, one for swap, one for the root partition, and one for the home directory

# lvcreate -L 64G main -n swap
# lvcreate -L 430G main -n root
# lvcreate -l 100%FREE main -n home

You may wonder why I’m booking 64 Gb for memory swap. It isn’t because I’m scared of running short of RAM, this laptop has exactly 64 Gb. In the past I ran into hibernating issues because the swap partition was smaller than the size of the RAM, although nowadays, the memory image for the hibernation can be store in a file and not only in a swap partition I preferred to keep it simple and use the swap partition for hibernating because I can afford to lose 64 Gb of disk from the other two partitions and, anyway, if I need to pull up that space, I could do it resizing the LVM volumes.

Time to format the partitions, for the swap partition is a snap. For the other two, I decided to be conservative and use ext4, despite of the cool features that btrfs, I went for ensuring maturity and stability over better data integrity and error recovering and I don’t need btrfs RAID, volume management, snapshots, and rollbacks because I already have LVM for them.

So the boring stuff for that is

# mkfs.ext4 /dev/main/root
# mkfs.ext4 /dev/main/home
# mkswap /dev/main/swap
# mount /dev/main/root /mnt
# mount --mkdir /dev/main/home /mnt/home
# swapon /dev/main/swap

I chose to boot in UEFI mode, so mounted the partition in /efi for compatibility with grup-install

# mkfs.fat -F32 -n EFI /dev/nvme0n1p2
# mount --mkdir /dev/nvme0n1p2 /mnt/efi

Preparation before installing

First of all, we need an internet connection. The Arch Linux installation image comes with iwd, and after I ensured that the Wi-FI network card was detected with ip link, I followed the iwctl commands in the connect to a network section.

I ensured that the system clock is accurate with timedateclt.

Installing essential packages

# pacstrap -K /mnt base linux linux-firmware

Essential configurations

I generate the fstab file from the current mounted volumes

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

Then I changed the root directory to the root mounted volume, where we are installing Arch Linux.

# arch-chroot /mnt

I installed Neovim, which is the editor that I usually use, and I need one to be able to modify and create some configuration files

# pacman -S neovim

Set the timezone

# ln -sf /usr/share/zoneinfo/Europe/Madrid /etc/localtime
# hwclock --systohc

I uncommented the ca_ES.UTF-8 UTF-8, es_ES.UTF-8 UTF-8, and en_US.UTF-8 UTF-8 from /etc/locale.gen and generated the locales with

# locale-gen

I created the file /etc/locale.conf and write inside LANG=en_US.UTF-8 to set the LANG variable accordingly.

I configured the hostname writing blacksmoke in /etc/hostname, yes the laptop is called blacksmoke.

I installed the iwd network manager

# pacman -S iwd

I’ve decided to use a systemd-based initramfs, so I changed the mkinitcpio.conf (/etc/mkinitcpio.conf) from

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

to

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

Note I swapped udev by systemd, added sd-encrypt and lvm2 and removed keymap and consolefont because I’m fine with the US console keymap and the default console font.

and I installed LVM because it’s obviously needed due to my partitions are on top of LVM volumes, besides that mkinitcpio needs is as you can see above that I added the lvm2 hook.

# pacman -S lvm2

Right after, I regenerated the initramfs running

# mkinitcpio -P

But I saw through the warnings printed in the console that Im missing a few firmwares. As commented in Mkinitcpio wiki page about “possible missing firmware for module XXXX, I had to install the Linux firmwares package

# pacman -S linux-firmware linux-firmware-qlogic

However, it wasn’t enough, and I had to install other firmwares from AUR packages, so let’s go for them.

As you may know, installing package from AUR repositories is totally different story than doing from main stream repositories, they are several tools that simplify the process by automating several manual steps, however, and I like them, but I want to decide which one to use, once I have the OS working, not at the installation time, so I installed them manually.

First, I installed the required packages to build AUR packages

# pacman -S base-devel sudo git

I authorized all the users in the wheel group creating the following file /etc/sudoers.d/00-wheel-users

%wheel ALL=(ALL:ALL) ALL

And I ensured that only root can access to it

  chmod -c 0660 /etc/sudoers.d/00-wheel-users

makepkg requires sudo, so it was the time to create my regular user and set it’s password

# useradd -c "Ivan Fraixedes" -m -U -G wheel ivan
# passwd ivan

I adjusted /etc/makepkg.conf following the tips & trics, creating /etc/makepkg.conf.d/makepkg.conf with the following content

MAKEFLAGS="-j$(nproc)"

PKGDEST=~/.local/makepkg/packages
SRCDEST=~/.local/makepkg/sources
SRCPKGDEST=~/.local/makepkg/srcpackages
LOGDEST=~/.local/makepkg/logs

I logged with my user and created the directories that I configured for makepkg

# su ivan
# cd ~
# mkdir -p .local/makepkg
# cd .local/makepkg
# mkdir logs packages sources srcpackages

I installed the following firmware from AUR doing (as ivan user)

# mkdir -p tmp/aur
# cd tmp/aur
# git clone https://aur.archlinux.org/upd72020x-fw.git
# cd upd72020x-fw
# makepkg -sirc

The same package installation call mkinitcpio and I saw that there isn’t a warning anymore for the xhci-pci firmware, yup! I repeated the same process for the following AUR firmwares ast, aic94xxx, and wd719x. Cha-ching no more warning when building the initramfs with mkinitcpio.

I installed the GRUB boot loader and the efibootmgr which is required by GRUB for UEFI systems

# pacman -S grub efibootmgr

And configure it (/etc/default/grub) to allow booting from /boot on the encrypted partition and set the kernel parameters to allow initramfs to unlock the encrypted root partition using the sd-encrypt mkinitcpio’s hook. Note these lines may not be together, some may be commented, and some may have other values that you may need to keep, in any case they will ended up with these values in a different machine (e.g. the disk UUID won’t be the same), hence, check the configuring GRUB section.

GRUB_ENABLE_CRYPTODISK=y
GRUB_CMDLINE_LINUX="rd.luks.name=a199a1d7-acc0-4910-babb-e0059dec293b=cryptlvm"

What disk UUID should you add in the above GRUB’s configuration? I think that’s quite obvious, but I didn’t think that much at that moment and I set to the UUID of the wrong one and, for obvious reasons, GRUB wasn’t able to decrypt the volumen and boot the OS :(. It took me several hours to find out my mistake and with a lot of rebooting to try to see if I was fixing the issues for every change that I was making in mkinitcpio.conf, grub, etc., so pay attention and don’t waste marvelous hours with this stupid mistake.

It has to be the UUID of the LUKS partition where the /boot is placed, NOT the LVM one! In my case is /dev/nvme0n1p3 and to find out UUID, you can do ls -l /dev/disk/by-uuid and the link name that points to it is the UUID.

I installed GRUB to be mounted ESP for UEFI booting and generated the GRUB’s configuration file

# grub-install --target=x86_64-efi --efi-directory=/efi --bootloader-id=GRUB --recheck
# grub-mkconfig -o /boot/grub/grub.cfg

OK, at this point, I rebooted the computer and yes, after booting from its disk, it asked me for the LUKS password, then GRUB menu showed up, and, after selecting boot Arch, it asked me again for LUKS password. Brilliant, everything finally worked.

Last, but not least and before finishing this blog post, I want to include here 2 things as an initial setup.

I did a couple of more things which I consider that they are part of the base installation:

  1. Set a password for the root user, otherwise you cannot login with it. Yes, I want a password for it, I found sometimes useful in the past to be able to login as root rather than my regular user.
  2. Add a keyfile to the LUKS partition, so it can be used to decrypted automatically by GRUB and not having to type the LUKS passphrase twice.

After booting up, I login with my regular user ivan and then, I access as root and change its password.

# sudo su
# passwd

Using the root login, I set up the keyfile for the LUKS volume following the “With a keyfile embedded in the initramfs” section of “dm-crypt/Device encryption” page.

First, I created the keyfile

# dd bs=512 count=4 if=/dev/random of=/root/cryptlvm.keyfile iflag=fullblock
# chmod 000 /root/cryptlvm.keyfile
# cryptsetup -v luksAddKey /dev/nvme0n1p3 /root/cryptlvm.keyfile

I added the keyfile to the initramfs image, that’s just updating the /etc/mkinicpio.conf, adding the file path to the FILES list, in my case, FILES was empty, so it changed from

FILES=()

to

FILES=(/root/cryptlvm.keyfile)

Recreate the initramfs

# mkinitcpio -P

Secure the access to the embedded keyfile

# chmod 600 /boot/initramfs-linux*

Update GRUB’s configuration (i.e. /etc/default/grub) to point to the keyfile. Remember, that in my case, I’m using systemd-based initramfs (i.e. sd-encrypt hook). I my case, I added rd.luks.key=a199a1d7-acc0-4910-babb-e0059dec293b=/root/cryptlvm.key to the GRUB_CMDLINE_LINUX, so it changed from

GRUB_CMDLINE_LINUX="rd.luks.name=a199a1d7-acc0-4910-babb-e0059dec293b=cryptlvm"

to

GRUB_CMDLINE_LINUX="rd.luks.name=a199a1d7-acc0-4910-babb-e0059dec293b=cryptlvm rd.luks.key=a199a1d7-acc0-4910-babb-e0059dec293b=/root/cryptlvm.key"

And regenerate the GRUB’s configuration

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

That’s it for today, in future posts, I will cover what tools I’m installing and certain configurations that I tweaked to make my machine more comfortably usable.