About this guide

I made this guide a few days after installing Arch Linux with ZFSBootMenu on my Laptop. However, always check the commands before entering them. You should be knowledgeable in both Linux and ZFS.

In this guide, I will go through an entire ZFS-on-Root installation process on Arch Linux, using ZFSBootMenu as the UEFI bootloader. It will basically be a mix of multiple guides, which I will link below.

In the following code blocks, every time you have to insert something into a command, I’ll use single guillemets:

command <insert something here>

Step 1 – Getting a bootable USB stick with the Arch LiveISO

I’m assuming that you are familiar with creating a bootable USB stick. If you’re not, then this guide might help you: Create the bootable media. Don’t forget to disable Secure Boot in your BIOS to boot the image.

There are two possible LiveISO images you could use:

  1. Using a normal LiveISO and installing ZFS on it afterwards
  2. Using a custom image with ZFS being preinstalled

First grab the latest image from the official Arch Linux Download site and put it on the USB Stick. Then boot from it (Don’t forget to disable Secure Boot in your BIOS beforehand) and prepare your live image. Afterwards run the script provided by eoli3n:

curl -s https://raw.githubusercontent.com/eoli3n/archiso-zfs/master/init | bash

Jump straight to Step 3.

Using a custom image

I won’t go into detail to how to make it, however the ArchWiki has a guide for it: Create an Archiso image with ZFS support. Please note that you need to have Arch Linux installed already on your system to use this method. Personally, I would recommend that you use the archzfs user repository when creating your image.

Step 2 – Prepare your live image

If you didn’t already, you must now prepare your live image.

Set the keyboard layout

Now you need to set your keyboard layout (unless you’re using the US layout). You can get a list of all available layouts with:

ls /usr/share/kbd/keymaps/**/*.map.gz

For example for using the Swiss German layout use:

loadkeys de_CH-latin1

Connect to the Internet

Use any utility you want, I will use iwctl in the following part.

Start iwctl and list your devices:

iwctl
[iwd] device list

Scan for networks:

[iwd] station <device> scan

List all available networks:

[iwd] station <device> get-networks

Connect to a network:

[iwd] station <device> connect <SSID>

Enter your network password and you’re connected to the Internet.

Step 3 – Create the ZFS pool

Generate /etc/hostid

zgenhostid

Store your pool passphrase in a file

echo '<passphrase>' > /etc/zfs/zroot.key
chmod 000 /etc/zfs/zroot.key

Partition your disk

Create an EFI partition with a size of 512 MB and a second partition on which the zpool will be. You may want to add other partitions, for example a swap partition.

Please note that if you want to use swap, you can’t use a swap file, as there are limitations with it and ZFS. You should read the wiki page in the Arch Wiki before using swap.

List your disks

ls -la /dev/disk/by-id

Save your disk path in a variable

DISK=/dev/disk/by-id/<DISK>

Apply the partition scheme

You can use any utility you want, for example fdisk or gdisk. I will use gdisk in the following commands:

sgdisk --zap-all $DISK
sgdisk -n1:1M:+512M -t1:EF00 $DISK
sgdisk -n2:0:0 -t2:BF00 $DISK

Create zroot

You can name the pool as you want, I’ll call it zroot. I’ll use the lz4 compression, however you might want to use another compression algorithm like zstd or gzip. In most cases I recommend using compression as there are no big performance issues with that.

You might also want to change ashift depending on your hard drive, as some modern SSDs perform better when using ashift=13. Your ashift value depends on the physical block size your disk uses. If it has 4k sectors, use ashift=12, if it has 8k sectors, use ashift=13, if it has smaller sectors, use a smaller ashift. You might also want to set atime=off, since you probably don’t need the file system to update the time you last accessed a file. If you want to really tune your system, I recommend reading this guide and this cheat sheet. However, if you only want a functioning file system, you can skip this tuning and use the following settings. You can change most of the settings later on (however, ashift can’t be changed later, so it might be worth researching it a bit and looking up your block size).

zpool create -f -o ashift=12 \
 -O compression=lz4 \
 -O acltype=posixacl \
 -O xattr=sa \
 -O relatime=on \
 -O encryption=aes-256-gcm \
 -O keylocation=file:///etc/zfs/zroot.key \
 -O keyformat=passphrase \
 -o autotrim=on \
 -m none zroot ${DISK}-part2

Create the datasets

Create a dataset for our root system under zroot/ROOT and a dataset for /home, because in that way you’re able to later add other root datasets (for example for other distributions) while still using the same /home. Thanks to ZFSBootMenu you’ll be able to boot into the other root dataset with no problems.

Note: It’s important to set the canmount=noauto property on all file systems with mountpoint=/, because else it will try to boot all systems at /, which will prevent the system from booting.

zfs create -o mountpoint=none zroot/ROOT
zfs create -o mountpoint=/ -o canmount=noauto zroot/ROOT/arch
zfs create -o mountpoint=/home zroot/home

Test the pool by exporting and importing it

zpool export zroot
zpool import -N -R /mnt zroot
zfs load-key -L prompt zroot # Enter your pool passphrase after that command
zfs mount zroot/ROOT/arch
zfs mount zroot/home

Check whether the pool is mounted correctly

mount | grep mnt

This should return something like that:

zroot/ROOT/arch on /mnt type zfs (rw,relatime,xattr,posixacl)
zroot/home on /mnt/home type zfs (rw,relatime,xattr,posixacl)

Create and mount the EFI partition

mkfs.vfat -F 32 -n EFI $DISK-part1
mkdir /mnt/efi
mount $DISK-part1 /mnt/efi

Step 4 – Install Arch Linux

Install the packages with pacstrap

In the following steps you’ll install the first packages with pacstrap.

Install base packages

The following packages are absolutely needed. However, you’ll most likely want to install more packages, for example man for manual pages or networkmanager for the ability to easily connect to Wi-Fi. However, I would only install a few packages in this step and all desktop environments like gnome, browsers like firefox etc. after the full installation is done.

You may also want to choose another kernel than linux-lts, for example linux if you don’t want the Long Term Support kernel or linux-zen for the Zen kernel. when doing so, you must also install the respective -headers package, so change linux-lts-headers to <kernel name>-headers.

Personally, I recommend using the Long Term Support kernel:

pacstrap /mnt base linux-lts linux-firmware linux-lts-headers wget nano efibootmgr

Install the zfs module

You have multiple ways to choose from when installing the zfs module. One way is to install zfs-linux-lts (or zfs-linux for the non-LTS kernel or zfs-linux-zen for the Zen kernel). However, I recommend to use the DKMS variant, as it will automatically rebuild the module each time the kernel gets an update, so you won’t have to wait until the zfs-linux-lts package is updated. Additionally, you can use this package for any chosen kernel. Therefore I’ll install this one:

pacstrap /mnt zfs-dkms

Copy the files to the new system

In this step you’ll copy all important files to the new system.

cp /etc/hostid /mnt/etc
cp /etc/resolv.conf /mnt/etc
mkdir /mnt/etc/zfs # it may already exist, but this isn't a problem
cp /etc/zfs/zroot.key /mnt/etc/zfs
cp /etc/pacman.conf /mnt/etc/pacman.conf

Generate /etc/fstab

Now you’ll generate /etc/fstab:

genfstab /mnt > /mnt/etc/fstab

However, you’ll have to modify it as zfs doesn’t need an entry in /etc/fstab:

nano /mnt/etc/fstab

And delete all lines but the one containing /efi.

Chroot into the new system

arch-chroot /mnt

Set the time zone

ln -sf /usr/share/zoneinfo/<Region>/<City> /etc/localtime

Additionally run this to generate /etc/adjtime:

hwclock --systohc

Generate your locales

Edit /etc/locale.gen:

nano /etc/locale.gen

Uncomment all locales you need, for example en_US.UTF-8 UTF-8.

Afterwards run this to generate the locales:

locale-gen

Then set the LANG variable accordingly by writing LANG=<Your local> to /etc/locale.conf, for example LANG=en_US.UTF-8:

echo 'LANG=en_US.UTF-8' > /etc/locale.conf

You may also want to set the keyboard layout by setting KEYMAP according to the keyboard layout you chose earlier by writing KEYMAP=<Keyboard layout> to /etc/vconsole.conf, for example KEYMAP=de_CH-latin1:

echo 'KEYMAP=de_CH-latin1' > /etc/vconsole.conf

Network configuration

Set your hostname by writing it to /etc/hostname:

echo '<hostname>' > /etc/hostname

Then edit /etc/hosts, where <hostname> is your previously chosen hostname:

127.0.0.1   localhost
::1         localhost
127.0.1.1   <hostname>

Generate your initramfs

Then edit /etc/mkinitcpio.conf:

nano /etc/mkinitcpio.conf

Change the FILES line to:

FILES=(/etc/zfs/zroot.key)

This will save the key file in the initramfs, because else we’d have to type in the key two times each time we boot.

And change the HOOKS line to:

HOOKS=(base udev autodetect modconf block keyboard zfs filesystems)

This will load the zfs module, which you need to use ZFS.

Afterwards generate a new initramfs:

mkinitcpio -P

Set a root password

passwd

Set a cachefile for zfs

Set a cachefile for ZFS to boot from:

zpool set cachefile=/etc/zfs/zpool.cache zroot

Set your bootfs

Set your bootfs for ZFS, so that ZFSBootMenu knows which dataset to boot from:

zpool set bootfs=zroot/ROOT/arch zroot

Enable all needed daemons

systemctl enable zfs-import-cache zfs-import.target zfs-mount zfs-zed zfs.target

Step 5 – Install ZFSBootMenu

Install ZFSBootMenu by getting the pre-built binary from their release page.

Create an efi subfolder

mkdir -p /efi/EFI/zbm

Get the latest release

wget https://get.zfsbootmenu.org/latest.EFI -O /efi/EFI/zbm/zfsbootmenu.EFI

Add an entry to your boot menu

In the following comment <disk> is the disk you installed the EFI partition on earlier.

efibootmgr --disk <disk> --part 1 --create --label "ZFSBootMenu" --loader '\EFI\zbm\zfsbootmenu.EFI' --unicode "spl_hostid=$(hostid) zbm.timeout=3 zbm.prefer=zroot zbm.import_policy=hostid" --verbose

Use the BIOS

Some manufacturers offer the possibility to add a boot entry graphically in the BIOS. However you must check your manufacturer’s manual to see whether it’s possible and how to do it.

Use another bootloader

You could use another bootloader like rEFInd or GRUB to boot into ZFSBootMenu. This is especially useful when you want to dual boot with Windows or MacOS (if you want to dual boot with another Linux distribution you will most likely be able to do it through ZFSBootMenu by putting the distribution root directory on another dataset in zroot).

Set the kernel parameters

zfs set org.zfsbootmenu:commandline="noresume init_on_alloc=0 rw spl.spl_hostid=$(hostid)" zroot/ROOT

Step 6 – Reboot and enjoy

Exit the chroot

exit

Unmount the EFI partition

umount /mnt/efi

Export the zpool and reboot

zpool export zroot
reboot

Log in and continue with further installation steps

Now you should boot first info ZFSBootMenu and afterwards into Arch Linux. If everything works, you should continue with the General recommendations after installing.

Notes

Moving to another system

If you move your ZFS disks to another system and they aren’t detected as bootable, you may try to reinstall ZFSBootMenu, regenerate the hostid and copying the new /etc/hostid to your disk. Thanks to Johannes in the comments for this note!

Debugging

If you have to debug the system for any reason, be it immediately after installing it or some time later, you have to import zroot the following way (See also Step 3):

zpool import -N -R /mnt zroot

The reason is that the normal mountpoint for zroot/ROOT/arch is / (as set in Step 3), and for it to mount to /mnt we have to set a temporary mountpoint, which we do with the -R flag.

References

Full Guides

Other References

List of updates to this article

List of Updates

Update - 2024-02-07

Added some information about moving the ZFS disks to another system.

Update - 2024-02-03

Added some new information in the section Create zroot about some tuning options.

Update - 2024-01-14

Changed the recommended kernel from linux to linux-lts as it will give you less problems when updating your kernel. For more information click here.

Update – 2022-10-27

In an earlier version I forgot to mention that you must copy /etc/pacman.conf from the live system to the newly installed system or else the new system won’t upgrade the zfs modules. I’m sorry for the inconvenience.

If you installed it without copying the file, you can fix this by adding the following to the end of /etc/pacman.conf:

[archzfs]
Server = http://archzfs.com/$repo/x86_64
SigLevel = Optional TrustAll

Just run sudo pacman -Syu afterwards.

Comments