Skip to content

Instantly share code, notes, and snippets.

@silverhadch
Last active September 17, 2025 02:41
Show Gist options
  • Save silverhadch/98dfef35dd55f87c3557ef80fe52a59b to your computer and use it in GitHub Desktop.
Save silverhadch/98dfef35dd55f87c3557ef80fe52a59b to your computer and use it in GitHub Desktop.
✅ Arch Linux ZFS Root Install with systemd-boot + UKI (using LTS ISO)

✅ Arch Linux ZFS Root Install with systemd-boot + UKI (using LTS ISO)


Prerequisites

  • Boot Mode: UEFI
  • Bootloader: systemd-boot
  • Initramfs Tool: mkinitcpio
  • ZFS Hook: sd-zfs from AUR (mkinitcpio-sd-zfs-poscat)
  • Kernel: linux-lts + zfs-linux-lts module
  • Root Filesystem: ZFS native datasets
  • Host ID: required for proper zpool import

Step 1: Boot the Custom ISO

Boot using the ISO from:
➡️ https://github.com/r-maerz/archlinux-lts-zfs
This already includes the ZFS modules and archzfs repo.


Step 2: Network & Time

ping archlinux.org
timedatectl set-ntp true

Step 3: Partition Disk (Assuming /dev/sdX)

parted /dev/sdX -- mklabel gpt
parted /dev/sdX -- mkpart ESP fat32 1MiB 512MiB
parted /dev/sdX -- set 1 esp on
parted /dev/sdX -- mkpart primary 512MiB 100%

Step 4: Format EFI Partition

mkfs.fat -F32 /dev/sdX1

Step 5: Load ZFS Module

Should already be loaded, but if not:

modprobe zfs

Step 6: Create ZFS Pool and Datasets

📁 Prepare Mountpoints

mkdir -p /mnt/{efi,home,var/log,var/cache}

🧩 Get PARTUUID

blkid /dev/sdX2

Replace <partuuid> below with actual PARTUUID:

🧱 Create ZFS Pool

zpool create -f -o ashift=12 -o autotrim=on   -O mountpoint=none -O acltype=posixacl -O atime=off   -O relatime=off -O xattr=sa -O normalization=formD   -R /mnt rpool /dev/disk/by-partuuid/<partuuid>

📁 Create Datasets

zfs create -o compression=lz4 -o canmount=off -o mountpoint=none rpool/ROOT
zfs create -o compression=lz4 -o canmount=noauto -o mountpoint=/ rpool/ROOT/arch

zfs create -o compression=lz4 -o mountpoint=/home rpool/ROOT/arch/home
zfs create -o compression=lz4 -o mountpoint=/var/cache rpool/ROOT/arch/varcache
zfs create -o compression=lz4 -o mountpoint=/var/log rpool/ROOT/arch/varlog

📌 Mount ZFS Datasets

zfs mount rpool/ROOT/arch
zfs mount -a

📌 Mount EFI Partition

mount /dev/sdX1 /mnt/efi

Step 7: Install Base System

pacstrap -K /mnt base linux-lts zfs-linux-lts zfs-utils   linux-firmware intel-ucode sof-firmware   base-devel git neovim plymouth

Step 8: Generate fstab (Only for EFI)

genfstab -U /mnt | grep /efi >> /mnt/etc/fstab

Step 9: Chroot into System

arch-chroot /mnt

Step 10: System Configuration

Timezone and Clock

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

Locale

sed -i 's/^#de_DE.UTF-8 UTF-8/de_DE.UTF-8 UTF-8/' /etc/locale.gen
locale-gen
echo "LANG=de_DE.UTF-8" > /etc/locale.conf

Console Keymap

echo "KEYMAP=de-latin1" > /etc/vconsole.conf

Hostname & Hosts

echo "archzfs" > /etc/hostname

cat <<EOF >> /etc/hosts
127.0.0.1   localhost
::1         localhost
127.0.1.1   archzfs.localdomain archzfs
EOF

Step 11: Install systemd-boot

bootctl install

Step 12: Install mkinitcpio-sd-zfs-poscat

# Step 1: Create minimal unprivileged user (no home, no shell)
useradd -M -s /usr/bin/nologin builduser

# Step 2: Create a build directory owned by the user
mkdir -p /tmp/build-aur
chown builduser:builduser /tmp/build-aur

# Step 3: Clone and build the package as builduser
su - builduser -s /bin/sh -c "
cd /tmp/build-aur &&
git clone https://aur.archlinux.org/mkinitcpio-sd-zfs-poscat.git &&
cd mkinitcpio-sd-zfs-poscat &&
makepkg -s --noconfirm
"

# Step 4: Install the package as root
pacman -U /tmp/build-aur/mkinitcpio-sd-zfs-poscat/*.pkg.tar.zst --noconfirm

# Step 5: Set hostid for ZFS
zgenhostid $(hostid)

# Step 6: Cleanup
userdel builduser
rm -rf /tmp/build-aur

Step 13: Configure mkinitcpio

Edit /etc/mkinitcpio.conf:

MODULES=(crc32c)
HOOKS=(systemd sd-zfs autodetect microcode kms modconf block keyboard keymap consolefont plymouth filesystems)

Step 14: Edit mkinitcpio Preset for UKI (LTS Kernel Only)

Edit /etc/mkinitcpio.d/linux-lts.preset:

ALL_kver="/boot/vmlinuz-linux-lts"

PRESETS=('default' 'fallback')

default_uki="/efi/EFI/Linux/zfs-arch-linux.efi"
fallback_uki="/efi/EFI/Linux/zfs-arch-linux-fallback.efi"
fallback_options="-S autodetect"

Create kernel cmdline:

echo "root=zfs:rpool/ROOT/arch zfs_force=1 rw zswap.enabled=0 nowatchdog quiet splash loglevel=3 systemd.show_status=auto rd.udev.log_level=3" > /etc/kernel/cmdline

Step 15: Generate Initramfs and UKI

mkinitcpio -p linux-lts

Step 16: Configure systemd-boot Loader

Create /efi/loader/loader.conf:

timeout 0
console-mode keep
editor 1

➡️ The UKI entries will be auto-detected in /efi/EFI/Linux/.


Step 17: Set Root Password

passwd

Step 18: Enable Required Services

systemctl enable zfs.target
systemctl enable zfs-import.target
systemctl enable zfs-mount.service

Step 19: Postinstall – Desktop Setup

pacman -S plasma gdm sudo pipewire

systemctl enable gdm.service
systemctl enable NetworkManager.service

useradd -m -G wheel -s /bin/bash username
passwd username

echo "%wheel ALL=(ALL:ALL) ALL" >> /etc/sudoers

Step 20: Exit and Reboot

exit
umount -l -R /mnt
zfs unmount -a
zpool export rpool
reboot

🎉 Your Arch Linux system is now booting ZFS as root using systemd-boot, linux-lts, and a modern UKI setup.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment