Unofficial zfs on root installation instructions

I had some good success with setting up my system with ZFS on Root and using ZFSBootMenu as the bootloader. ZBM out of the box also enables using ZFS native dataset encryption for your data and system.

The critical trick I used that finally got me through installation issues was to ignore the ZFS-on-root support in the Calamares installer, do make the config modifications to include ZFS modules in the OS, install to a non-ZFS filesystem, set up the ZFS dataset scaffolding in a different location (according to ZFSBootMenu), then copy the installed OS to the ZFS datasets.

I will include my notes, but be warned that they are not refined, cleaned up, or guaranteed to work without some interpretation.

The rough sequence of steps are:

  1. Install ZFS in live environment
  2. Prepare Zpool disk
  3. Download ZFSBootMenu EFI and install to ESP
  4. Modify Calamares config to include zfs modules and service setup
  5. Install EOS to second disk
  6. Copy system files to Zpool disk
These are the rough notes of commands that were ran
sudo pacman -Syu --noconfirm # Takes too long but should be done in real scenario
sudo pacman -Syu zfs-dkms zfs-utils paru

# Format disk
sudo fdisk /dev/sda
	g   # Create GPT
	n   # New partition, enter +300M for size (last sector)
	t   # Change partition type, type 1 = EFI
	n   # New partition, use all default to fill rest of disk with Linux filesystem partition
	w   # Write changes and exit

sudo fdisk -l   # Verify changes

# Format partitions
sudo mkfs.fat -F 32 /dev/sda1

##### Zpool #####
# Load zfs kernel module if not already
sudo modprobe zfs
# This step has with and without compression and encryption
sudo zpool create -f -o ashift=12         \
             -O acltype=posixacl       \
             -O relatime=on            \
             -O xattr=sa               \
             -O dnodesize=legacy       \
             -O normalization=formD    \
             -O mountpoint=none        \
             -O canmount=off           \
             -O devices=off            \
             -R /mnt                   \
             -O compression=lz4        \
             -O encryption=aes-256-gcm \
             -O keyformat=passphrase   \
             -O keylocation=prompt     \
             zroot /dev/disk/by-id/_id-to-partition-partx_

sudo su
zfs create -o mountpoint=none zroot/data
zfs create -o mountpoint=none zroot/ROOT
zfs create -o mountpoint=/ -o canmount=noauto zroot/ROOT/default
zfs create -o mountpoint=/home zroot/data/home
# Simplifying by removing these
#zfs create -o mountpoint=/var -o canmount=off     zroot/var
#zfs create zroot/var/log
#zfs create -o mountpoint=/var/lib -o canmount=off zroot/var/lib
#zfs create zroot/var/lib/libvirt
#zfs create zroot/var/lib/docker

zpool set bootfs=zroot/ROOT/default zroot
# Create zpool cache
zpool set cachefile=/etc/zfs/zpool.cache zroot
# Copy cache to target system
mkdir -p /mnt/etc/zfs
cp /etc/zfs/zpool.cache /mnt/etc/zfs/zpool.cache

##### Bootloader #####
mkdir /boot
mount /dev/sda1 /boot
mkdir -p /boot/EFI/zbm

# There is a package for an EFI binary of zfsbootmenu, which I think could prevent us having to built it ourself, unless some sort of custom build options are needed in our case
# EFI package requires ESP to be mounted
paru -Sy zfsbootmenu-efi-bin
paru -Sy efibootmgr   # Creates boot entry in UEFI of mobo

efibootmgr -c -d /dev/sda -p 1 -L "ZFSBootMenu" -l '\EFI\zbm\zfsbootmenu-release-vmlinuz-x86_64.EFI'

zfs set org.zfsbootmenu:commandline="rw" zroot/ROOT

##### Initrd #####
vi /etc/dracut.conf.d/zfs.conf
# zfs is a self scrubbing and healing system, fsck is redundant and slows down boot
# no_fsck=yes
# add_dracutmodules+=" zfs "
# omit_dracutmodules+=" btrfs "
dracut --hostonly --no-hostonly-cmdline /boot/initramfs-linux.img


##### Enable auto import of pool
systemctl enable zfs.target
systemctl enable zfs-import-cache.service
systemctl enable zfs-mount.service
systemctl enable zfs-import.target
Calamares modifications

We want to add zfs support, enable the services

# modules/pacstrap.conf
<   - nano
>   - zfs-dkms

# modules/services..
   - name: "zfs.target"
     action: "enable"
   - name: "zfs-import-cache.service"
     action: "enable"
   - name: "zfs-mount.service"
     action: "enable"
   - name: "zfs-import.target"
     action: "enable"

Calamares Installation

Run installer, install to a second disk, bootloader steps can be ignored because we are using ZFSBootMenu and just copying system files.

Post Installation

Prepare ZFS destination and mount under /mnt
Mount other disk /targ
sudo rsync -aAXv --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} /targ /mnt

mount --bind /proc /mnt/proc && mount --bind /sys /mnt/sys && mount --bind /dev /mnt/dev && mount --bind /run /mnt/run
arch-chroot /mnt
vi /etc/dracut.conf.d/zfs.conf
dracut --force --hostonly --no-hostonly-cmdline /boot/initramfs-linux.img 6.5.8-arch1-1
# fallback.img was not updated
vi /etc/fstab # remove entries
1 Like