Skip to content

Instantly share code, notes, and snippets.

@jensmeindertsma
Last active February 26, 2026 12:13
Show Gist options
  • Select an option

  • Save jensmeindertsma/b145741b446427285e19d16e0f834878 to your computer and use it in GitHub Desktop.

Select an option

Save jensmeindertsma/b145741b446427285e19d16e0f834878 to your computer and use it in GitHub Desktop.
Arch Linux LUKS BTRFS setup
  1. Note the available block devices
$ lsblk -o name,size,fstype,label
NAME          SIZE FSTYPE      LABEL
nvme1n1     465.8G
├─nvme1n1p1     1G vfat        LINUX
└─nvme1n1p2 464.8G
  1. Create an encrypted LUKS container for the BTRFS filesystem
$ cryptsetup luksFormat /dev/nvme1n1p2
$ cryptsetup open /dev/nvme1n1p2 root
$ mkfs.btrfs /dev/mapper/root
$ lsblk -o name,size,fstype,label
NAME          SIZE FSTYPE      LABEL
nvme1n1     465.8G
├─nvme1n1p1     1G vfat        LINUX
└─nvme1n1p2 464.8G crypto_LUKS
  └─root    464.7G btrfs
  1. Create BTRFS subvolumes
$ mount /dev/mapper/root /mnt
$ btrfs subvolume create /mnt/@
$ btrfs subvolume create /mnt/@home
$ btrfs subvolume create /mnt/@snapshots
$ btrfs subvolume create /mnt/@cache
$ btrfs subvolume create /mnt/@log
$ btrfs subvolume create /mnt/@swap
$ umount /mnt
  1. Mount the BTRFS subvolumes
$ mount -o rw,noatime,compress=zstd,ssd,space_cache=v2,subvol=@ /dev/mapper/root /mnt

$ mkdir -p /mnt/home /mnt/.snapshots /mnt/var/cache /mnt/var/log /mnt/swap

$ mount -o rw,noatime,compress=zstd,ssd,space_cache=v2,subvol=@home /dev/mapper/root /mnt/home
$ mount -o rw,noatime,compress=zstd,ssd,space_cache=v2,subvol=@snapshots /dev/mapper/root /mnt/.snapshots
$ mount -o rw,noatime,compress=zstd,ssd,space_cache=v2,subvol=@cache /dev/mapper/root /mnt/var/cache
$ mount -o rw,noatime,compress=zstd,ssd,space_cache=v2,subvol=@log /dev/mapper/root /mnt/var/log
$ mount -o rw,nodatacow,subvol=@swap /dev/mapper/root /mnt/swap
  1. Mount the boot partition
$ mkdir -p /mnt/boot
$ mount -o rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro -L LINUX /mnt/boot
  1. Create a swapfile large enough for hibernation
$ chattr +C /mnt/swap
$ dd if=/dev/zero of=/mnt/swap/swapfile bs=1M count=32768 status=progress
$ chmod 600 /mnt/swap/swapfile
$ mkswap /mnt/swap/swapfile
$ swapon /mnt/swap/swapfile
  1. Fill out the /mnt/etc/fstab file
# Static information about the filesystems.
# See fstab(5) for details.

# Static information about the filesystems.
# See fstab(5) for details.

# <file system> <dir> <type> <options> <dump> <pass>
LABEL=LINUX		    /boot		vfat      rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro 0 2

/dev/mapper/root / btrfs rw,noatime,compress=zstd:3,ssd,space_cache=v2,subvol=@ 0 0
/dev/mapper/root /home btrfs rw,noatime,compress=zstd:3,ssd,space_cache=v2,subvol=@home 0 0
/dev/mapper/root /.snapshots btrfs rw,noatime,compress=zstd:3,ssd,space_cache=v2,subvol=@snapshots 0 0
/dev/mapper/root /var/cache	btrfs	rw,noatime,compress=zstd:3,ssd,space_cache=v2,subvol=@cache 0 0
/dev/mapper/root /var/log btrfs rw,noatime,compress=zstd:3,ssd,space_cache=v2,subvol=@log 0 0
/dev/mapper/root /swap btrfs rw,nodatacow,ssd,space_cache=v2,subvol=@swap 0 0

/swap/swapfile none swap defaults 0 0
  1. Specify the default subvolume, which will be mounted by the initramfs before /etc/fstab can be read
$ btrfs subvolume list /mnt
ID 256 gen 48 top level 5 path @
ID 257 gen 9 top level 5 path @home
ID 258 gen 10 top level 5 path @snapshots
ID 259 gen 29 top level 5 path @cache
ID 260 gen 30 top level 5 path @log
ID 261 gen 29 top level 5 path @swap

Here the @ subvolume that we want to mount as root has ID 256

$ btrfs subvolume set-default 256 /mnt
  1. Install the kernel, firmware and basic packages
$ pacstrap -K /mnt base linux linux-firmware amd-ucode networkmanager vim man-db man-pages texinfo
  1. Change root into /mnt
$ arch-chroot /mnt
  1. Configure the timezone
$ ln -sf /usr/share/zoneinfo/Europe/Amsterdam /etc/localtime
$ hwclock --systohc
  1. Modify /etc/systemd/timesyncd.conf:
[Time]
NTP=0.arch.pool.ntp.org 1.arch.pool.ntp.org 2.arch.pool.ntp.org 3.arch.pool.ntp.org
FallbackNTP=0.pool.ntp.org 1.pool.ntp.org 0.fr.pool.ntp.org
  1. Enable network-based time synchronization
$ systemctl enable systemd-timesyncd
  1. Enable NetworkManager
$ systemctl enable NetworkManager
  1. Edit /etc/locale.gen and un-comment en_US.UTF-8 UTF-8

  2. Generate the locale

$ locale-gen
  1. Set the locale in /etc/locale.conf
LANG=en_US.UTF-8
  1. Set the keymap in /etc/vconsole.conf
KEYMAP=us
  1. Set a hostname in /etc/hostname
isac
  1. Set a password for the root user
$ passwd
  1. Modify the initramfs to include the sd-encrypt hook in /etc/mkinitcpio.conf
HOOKS=(base systemd autodetect microcode modconf kms keyboard keymap sd-vconsole block sd-encrypt filesystems fsck)
  1. Regenerate the initramfs
$ mkinitcpio -P
  1. Set up a boot loader
  • You can use rEFInd, systemd-boot, or anything you prefer

  • The initramfs and the kernel are located in the /boot directory

  • Important is that the kernel parameters rd.luks.name=XXXX=root root=/dev/mapper/root rw are set where XXXX should be replaced with the UUID of the partition holding LUKS container:

    $ s /dev/disk/by-uuid -l
    total 0
    lrwxrwxrwx 1 root root 15 Feb 26 10:05 27788325-6c54-43bb-8d73-c9c378086382 -> ../../nvme1n1p2
    lrwxrwxrwx 1 root root 15 Feb 26 10:03 8A33-4270 -> ../../nvme1n1p1
    

    In my case the right UUID is 27788325-6c54-43bb-8d73-c9c378086382 because I created the LUKS container on the /dev/nvme1n1p2 partition (see step 2). The kernel parameters thus become rd.luks.name=27788325-6c54-43bb-8d73-c9c378086382=root root=/dev/mapper/root rw

    TODO

    add user

    pacman -S sudo
    EDITOR=vim visudo
    uncomment wheel line
    useradd -m -G wheel <name>
    

    secure boot

    put firmware into setup mode

$ sudo pacman -S sbctl

$ sbctl status 
Installed:	✗ sbctl is not installed 
Setup Mode:	✗ Enabled 
Secure Boot:	✗ Disabled
Vendor Keys:	none

$ sbctl create-keys
✓
Secure boot keys created!

$ sudo sbctl enroll-keys -m
Enrolling keys to EFI variables...
With vendor keys from microsoft...✓
Enrolled keys to the EFI variables!

$ sbctl status
Installed:	✓ sbctl is installed
Owner GUID:	xxxxx
Setup Mode:	✗ Enabled
Secure Boot:	✗ Disabled
Vendor Keys:	microsoft

$ sudo sbctl verify
Verifying file database and EFI images in /boot...
✗ /boot/EFI/refind/refind_x64.efi is not signed
✗ /boot/vmlinuz-linux is not signed

$ sudo sbctl sign -s /boot/vmlinuz-linux
✓ Signed /boot/vmlinuz-linux

$ sudo sbctl sign -s /boot/EFI/refind/refind_x64.efi
✓ Signed /boot/EFI/refind/refind_x64.efi 
$ sudo sbctl verify
Verifying file database and EFI images in /boot...
✓ /boot/EFI/refind/refind_x64.efi is signed
✓ /boot/vmlinuz-linux is signed
  • Plymouth
  • systemd-boot
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment