Note: This is not an install guide. Purely personal notes.

Two partition: gdisk /dev/nvme0n1

  • EFI system partition (ESP)
    • 512M
    • GPT GUID: EF00
  • System partition
    • all available disk
    • GPT GUID: 8304

Important to remember GPT GUIDs since we are using systemd initramfs and discoverable partitions for booting. Relevant for the initramfs section.

  • mkfs.vfat -F32 /dev/nvme0n1p1
  • cryptsetup luksFormat /dev/nvme0n1p2
  • cryptsetup open /dev/nvme0n1p2 root
  • cryptsetup --perf-no_read_workqueue --perf-no_write_workqueue --allow-discards --persistent refresh root
  • mkfs.btrfs /dev/mapper/root

We also add support

btrfs subvolumes

This list is currently inspired by the opensuse BTRFS setup.

  • /@root
  • /home@home
  • /srv@srv
  • /var@var

Note that we are adding @root-snapshots and @home-snapshots for snapper. But later.

Now we are making all the subvolumes. I like doing them on a pivot partitions. We don't care about access time and rest of the flags should be applied by btrfs automatically.

  • mkdir /mnt_tmp
  • mount -o noatime,compress=zstd /dev/mapper/root /mnt_tmp
  • btrfs subvolume create /mnt_tmp/@root

Create for each partition under /mnt_tmp, then umount /mnt_tmp. We also use btrfs subvolume set-default 256 / for systemd initramfs to specify the root subvolume.

Later if we DO need to mount the actual root we need to specify the subvolid 5 which is a magic number: mount -osubvolid=5 /dev/mapper/root /var/btrfs

Then mount each respective directory to /mnt. Don't forget to mount /dev/nvme0n1p1 to /efi.

  • mount -o noatime,compress=zstd,subvol=@root /dev/mapper/root /mnt
  • mount -o noatime,compress=zstd,subvol=@var /dev/mapper/root /mnt/var
  • mount -o noatime,compress=zstd,subvol=@srv /dev/mapper/root /mnt/srv
  • mkdir /mnt/efi
  • mount /dev/nvme0n1p1 /mnt/efi

We mount /dev/nvme0n1p1 to /mnt/efi because we are using the new UEFI stub system for mkinitcpio. See next section :)

This is the base packages. Rest are pulled inn by my system packages.

pacstrap /mnt base base-devel linux linux-firmware btrfs-progs

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

initramfs - systemd

We do the systemd enabled initramfs. This allows us to simplify boot with discoverable partitions as we used the proper GPT GUIDs during partitioning earlier.

--- /etc/mkinitcpio.conf	2021-08-12 14:54:44.835669088 +0200
+++ /etc/mkinitcpio.conf	2021-07-22 20:30:18.593193125 +0200
@@ -49,7 +49,7 @@
 ##   NOTE: If you have /usr on a separate partition, you MUST include the
 #    usr, fsck and shutdown hooks.
-HOOKS=(base udev autodetect modconf block filesystems keyboard fsck)
+HOOKS=(base systemd autodetect modconf block keyboard sd-encrypt filesystems)

 # Use this to compress the initramfs image. By default, zstd compression

Changes to /etc/mkinitcpio.d/linux.preset. Note this requires the new mkinitcpio with UEFI stub generation! The package can be fetched from my local repo.

Note: This is all part of the mkinitcpio 31 release.

--- /etc/mkinitcpio.d/linux.preset	2021-08-13 18:54:44.835669088 +0200
+++ /etc/mkinitcpio.d/linux.preset	2021-07-22 20:30:18.593193125 +0200
@@ -2,13 +2,10 @@


- PRESETS=('default' 'fallback')
+ PRESETS=('default')

+default_options="--splash /usr/share/systemd/bootctl/splash-arch.bmp"

For the kernel cmdline options we are using /etc/kernel/cmdline as that is what mkinitcpio will be using to read from to create our boot entry.

$ cat /etc/kernel/cmdline
rw quiet acpi_osi= acpi_backlight=thinkpad_screen acpi.ec_no_wakeup=1 nowatchdog

Those options are for my thinkpad. Your mileage might differ. Note that we do not specify disk UUIDs because systemd is going to figure out that for us automagically.

Regenerate the linux iniramfs with mkinitcpio so we get our options mkinitcpio -P. The important part is to have the UEFI stub generation.

==> Starting build: 5.13.10-arch1-1
  -> Running build hook: [base]
  -> Running build hook: [systemd]
  -> Running build hook: [autodetect]
  -> Running build hook: [modconf]
  -> Running build hook: [block]
  -> Running build hook: [keyboard]
  -> Running build hook: [sd-encrypt]
  -> Running build hook: [filesystems]
==> Generating module dependencies
==> Creating zstd-compressed initcpio image: /boot/initramfs-linux.img
==> Image generation successful
==> Creating UEFI executable: /efi/EFI/Linux/arch-linux.efi
  -> Using UEFI stub: /usr/lib/systemd/boot/efi/linuxx64.efi.stub
  -> Using kernel image: /lib/modules/5.13.10-arch1-1/vmlinuz
  -> Using os-release file /etc/os-release
==> UEFI executable generation successful


# bootctl install
Created "/efi/loader/entries".
Copied "/usr/lib/systemd/boot/efi/systemd-bootx64.efi" to "/efi/EFI/systemd/systemd-bootx64.efi".
Copied "/usr/lib/systemd/boot/efi/systemd-bootx64.efi" to "/efi/EFI/BOOT/BOOTX64.EFI".
Created "/efi/60a1f123aa5f451f8af104e458838efb".
Random seed file /efi/loader/random-seed successfully written (512 bytes).
Created EFI boot entry "Linux Boot Manager".
# efibootmgr -v // verify it works
BootCurrent: 0000
Timeout: 0 seconds
BootOrder: 0000
Boot0000* Linux Boot Manager	HD(1,GPT,d78d8c94-d277-4635-a73c-a68cd6ddb6ab,0x800,0xff801)/File(\EFI\systemd\systemd-bootx64.efi)


Tips and Tricks

Run makepkg as sudo

Never actually use this: env EUID=1000 makepkg -srcf

Disable work queues for cryptsetup

cryptsetup sector size

λ ~ » sudo blockdev --getpbsz /dev/nvme0n1
λ ~ » sudo nvme id-ns -H /dev/nvme0n1
LBA Format  0 : Metadata Size: 0   bytes - Data Size: 512 bytes - Relative Performance: 0 Best (in use)
                                                      ^^^^^^^^^ sector size
λ ~ » sudo cryptsetup luksDump /dev/nvme0n1p2 | grep sector
	sector: 512 [bytes]

This should be autoselected with new cryptsetup. But not sure if this applies to NVME? Note for the future: Get a NVME which supports sector size 4096?


Test package for /etc/kernel/cmdline.d for laptop specific settings

misc stuff

xdg-mime default org.pwmt.zathura.desktop application/pdf
xdg-settings set default-web-browser org.qutebrowser.qutebrowser.desktop