Skip to Content

EndeavourOS with ZFS Boot Menu

written by rick on Monday, July 7, 2025

Why

  1. ZFS is the only good filesystem. Fight me
  2. Linux ZFS root is usually weird and always feels like applying the linux way to zfs rather than doing things the zfs way. ZFSBootMenu fixes this
  3. In my testing, EndeavourOS was the most pleasant experience for gaming on linux (I’m sure ubuntu is fine). You can do it on plain Arch but something is always weird. EndeavourOS just installs like a normal operating system. (NixOS was weird)
  4. I am used to NixOS generation rollback and the only way to approach this is rollback to file system snapshots in the boot menu. ZFSBootMenu does this beautifully.

It almost works (skip down for full guide)

If you have this almost working but keep getting a failure with /dev/gpt-auto-root and then dumped onto a recovery shell (which might be non-functional). Here is what to do:

  1. Reset, press Escape on the boot screen to get the full boot menu.

  2. Press Ctrl + E to edit the kernel command line

  3. Add this argument to the end of the command line rd.systemd.gpt_auto=0

  4. Once in the running system, run
    sudo zfs get org.zfsbootmenu:commandline [BOOT dataset]
    (probably something like zroot/ROOT or zroot/ROOT/eos) to get your existing kernel command line. Copy this value.

  5. Update the kernel command line by running
    sudo zfs set org.zfsbootmenu="[VALUE YOU COPIED] rd.systemd.gpt_auto=0"
    This is the same change we made in the pre-boot environment, but makes it permanent so your system will now boot automatically.

  6. Reboot, let it auto-boot to check that the change worked. If not, go back and try again to make sure you did everything correctly.

Getting Started

First you need to do all the normal installing linux stuff with a disk image and live environment. (Remember to disable secure boot)

A note on virtual machines

Arch can be kinda weird in vms. I recommend changing your graphics to SPICE or SPICE (qxl) or QXL for better compatibility

Installation

Once you’re booted into the live environment, follow this guide to hack zfs support into the calamares installer and install EndeavourOS on a zfs root with a few updates and adjustments:

The systemd configuration file at /etc/calamares/modules/services-systemd.conf no longer has changed syntax a bit so there is just one big units section. Add .service to the end of the services and .target and set action: enable instead of mandatory to match the other services in the file. It will look something like

- name: "vmtoolsd.service"
  action: "enable"
- name: "vmware-vmblock-fuse.service"
  action: "enable"
- name: "zfs.target"
  action: "enable"
- name: "zfs-import.target"
  action: "enable"
- name: "zfs-import-cache.service"
  action: "enable"
- name: "zfs-mount.service"
  action: "enable"

be careful about indentation. YAML is like that.

You can also edit /etc/calamares/modules/zfs.conf to change settings about the pool and datasets, but the defaults are find if you don’t want to. I would change the poolname, but only because the default is really long

I would do a swap partition, you can’t have a swapfile.

Follow the rest of the guide, choose online install, and do the normal install stuff. Obviously choose zfs in the partitioning menu. When it gets to selection a bootloader, choose no bootloader. When the installer completes do NOT reboot, your system is not yet bootable, now we need to install ZBM.

Configuring the zfs pool for booting

Info Gathering

We need to set two important options on the pool so that ZBM can boot it. First run sudo zpool status to verify the name of your pool. Then run sudo zfs list to view the datasets created by calamares. One of them will be called something like zpendeavouros/ROOT/eos/root and have a mountpoint like /tmp/calamares-root-[garbage]. This will become the root dataset mounted to / when you reboot. Note the dataset NAME. Now we have the information to set the options.

Setting options

bootfs

Set the bootfs flag on the pool by running sudo zpool set bootfs=[ROOT DATASET] [POOL NAME] for me this looks like sudo zpool set bootfs=zpendeavouros/ROOT/eos/root zpendeavouros. You can run sudo zpool get bootfs [POOL NAME] to verify that it worked.

kernel command line

ZBM gets the kernel command line from an attribute on the pool, so we need to set that as well. For EndeavourOS it is essential that you set rd.systemd.gpt_auto=0 or the boot will fail. You can set any other kernel command line arguments you want, other than root or rootfstype, which ZBM will handle for us. The option is org.zfsbootmenu:commandline set like
sudo zfs set org.zfsbootmenu:commandline="rd.systemd.gpt_auto=0" zpendeavouros/ROOT
ZFS attributes are inherited, so as long as you set this value on a parent of the bootfs dataset you should be good, but the guides usually set it on something like zroot/ROOT, so that’s what I did.

ZFSBootMenu installation

Re-mounting the ESP

Now that the installer has completed, we will download ZBM to the efi partition and then add an entry to the efi boot list. Calamares probably unmounted it, so we will need to remount it. It will likely be the first partition on on the disk you installed to, but you can find out for sure by running lsblk -f and looking for the drive that has zfs_member as the FSTYPE for one of the partitions. Another partition on that drive has vfat in the FSTYPE and this is your efi system partition (ESP). I’ll mount this with sudo mount --mkdir /dev/[drive] /mnt/efi, but you can put it wherever, just remember where it is.

Downloading ZBM

This basically follows the steps common to all the guides on the ZBM website.

cd to your ESP mountpoint and run sudo mkdir -p EFI/ZBM then sudo curl -o EFI/ZBM/VMLINUZ.EFI -L https://get.zfsbootmenu.org/efi. You should end up with [ESP mount]/EFI/ZBM/VMLINUZ.EFI

ZBM only supports zfs booting, so if you have other linux distros or a windows dual boot, you’ll need to install rEFInd and set it up to chain-load into ZBM. You can

Direct EFI boot (skip if using rEFInd)

We need to add ZBM to the boot menu, which we will do with efibootmgr (should be installed already). You need the information about your ESP again. If you installed to a sata drive, it’ll just be /dev/sdX (X will be a letter) for the drive and then the number that follows that is the partition number (it’s almost certainly 1, unless you’re doing something really weird). NVME drives are named differently with lots of letters and numbers. At the end, there should be a p and then a number. The number is the partition number (p for partition), and everything before the p (NOT INCLUDING THE p) is the drive name. If you want to be extra sure, you can ls -l /dev/disk/by-id.

The command is

sudo efibootmgr -c -d [ESP DISK] -p [ESP partition number] \
   -L "ZFSBootMenu"
   -l '\EFI\ZBM\VMLINUZ.EFI'

This creates and efi entry for your disk, names it ZFSBootMenu, and tells it to look for a loader at \EFI\ZBM\VMLINUZ.EFI. Make sure you use windows-style back-slashes in the path.

For my drive it looks like

sudo efibootmgr -c -d /dev/sda -p 1 \
   -L "ZFSBootMenu"
   -l '\EFI\ZBM\VMLINUZ.EFI'

For an install on an NVME disk like /dev/nvme0n1p1, it would look like

sudo efibootmgr -c -d /dev/nvme0n1 -p 1 \
   -L "ZFSBootMenu"
   -l '\EFI\ZBM\VMLINUZ.EFI'

rEFInd bootloader (skip if using direct efi boot)

First you need to install refind with sudo pacman -S refind. Double check that your ESP is still mounted and then run sudo refind-install. In the output it should say ESP was found on [ESP mountpoint] using vfat. It will also create a configuration file (probably /boot/refind_linux.conf) which is wrong and you should delete it. Create a file at [efi mount]/EFI/ZBM/refind_linux.conf with the contents (use your editor or a heredoc)

"Boot default" "quiet loglevel=0 zbm.skip"
"Boot to menu" "quiet loglevel=0 zbm.show"

It should be next to the ZBM binary.

Sanity checks

You can peek at some things on the new system just to make sure it’s working, or just skip down to Export and Reboot.

First run sudo zfs mount [ROOT DATASET] to re-mount the new system. You cannot just run sudo zfs mount -a because the root dataset has canmount=noauto set.

etc/fstab

The fstab should be configured correctly. Double check that the efi partition and swap are present but none of the zfs datasets are there. The zfs datasets are mounted by the zfs-import and zfs-mount services, not by fstab. Speaking of…

systemd targets and services

Navigate to the etc/systemd/system of the new system (not the live image), and double check that the zfs.target.wants and zfs-import.target.wants directories are present. zfs.target.wants should contain links to zfs-import.service and zfs-mount.service.zfs-import.target.wants should contain a link to zfs-import-cache.service. It’s ok if these links are broken, they’ll be correct when you reboot. If anything is missing, you can sudo arch-chroot [system mountpoint] and enable all the targets and services with systemctl enable. Do the targets first. exit to leave the chroot environment.

When you’re done, cd back to the live environment and sudo zfs umount -a.

TRIM

Assuming you are running an SSD, you need to enable trim to avoid random system slowdowns and hangs. You can trim manually by running sudo zpool trim [poolname], but it’s much better to do this automatically by setting sudo zpool set autotrim=on [poolname]. There is also an fs-trim service in the util-linux package if you want something else.

Export and reboot

The last thing you need to do is export the zpool so you don’t get an error trying to boot it. sudo zpool export [POOL NAME]. It might not export cleanly, but it should be OK anyway. If not you can reboot into the live environment and import and export it.

Post-Install

Now that it’s up and running, you should consider setting up automatic snapshots and backups. File system snapshots are one of the main reasons to use ZFS. I like [sanoid] but you could also use zfs-auto-snapshot.

Extra notes

Using ZBM

Pressing Escape at boot will get you into the full zbm menu. It has pretty good built-in help, so if your system does break, you chroot into it or boot a snapshot or rollback to a snapshot right in the pre-boot environment.

If you are using rEFInd to boot, press Tab then select Boot to menu.

Other kernels

EndeavourOS installs the mainline linux kernel by default, but you can usually swap it out or install additional kernels the usual way. Install the corresponding headers so the zfs-dkms module can build correctly. Always check that a newly installed kernel boots before deleting the old one. The kernel is stored on the main zfs dataset, so you can revert kernels rolling back to an older snapshot. Get to the boot menu then press Ctrl + K to select a kernel to boot. You can change the default kernel in that same menu.

Encryption

One big advantage of ZBM is native encrypted root instead of having to wrap it in a LUKS partition. I couldn’t quite get it working in EndeavourOS; it should be possible, but might require a manual install.

Sources and inspirations

This is mostly based on a few guides about zfs and zbm and arch and endeavour