ZFS Platforms — where it runs, how it integrates, and what breaks.
ZFS was born on Solaris in 2005. It thrives on FreeBSD. It works on Linux — with effort.
Each platform integrates ZFS differently: native kernel code, out-of-tree DKMS modules,
or precompiled kABI-tracking packages. The integration method determines how stable ZFS
is across kernel updates, how much work you do at maintenance time, and whether a routine
dnf update can leave your system unbootable.
This page covers every platform OpenZFS runs on, how it gets there, and what to watch out for.
History — from Solaris to OpenZFS
Understanding where ZFS runs today requires understanding where it came from. ZFS was designed by Jeff Bonwick and Matthew Ahrens at Sun Microsystems and first shipped in Solaris 10 (2005). It was a clean-sheet design built into the Solaris kernel — no bolted-on volume manager, no separate fsck, no afterthought. The filesystem, volume manager, checksumming, and caching were all one integrated system.
When Sun open-sourced Solaris as OpenSolaris (2005-2010), ZFS came with it under the CDDL (Common Development and Distribution License). Oracle acquired Sun in 2010 and closed Solaris development. The open-source community forked the last open ZFS code into illumos (the Solaris kernel fork) and began porting ZFS to other platforms independently.
Three independent porting efforts emerged:
Oracle continues to develop a proprietary ZFS inside Solaris 11, but it has diverged significantly from OpenZFS. Features like RAIDZ expansion, block cloning, and fast dedup exist only in OpenZFS. Oracle's ZFS has features like shadow migration and sequenced resilver that OpenZFS does not. The two codebases are no longer compatible at the pool level — you cannot import a Solaris 11.4 pool on OpenZFS or vice versa without data loss risk.
Platform support matrix
OpenZFS 2.2.x is the current stable branch. OpenZFS 2.3 is in development with RAIDZ expansion and other features. The table below reflects the state of each platform as of early 2026.
| Platform | OpenZFS Version | Integration Method | Boot from ZFS | Stability | Kernel Updates |
|---|---|---|---|---|---|
| FreeBSD 14 | 2.2.x (in-tree) | Native kernel code | Native (bectl) | Excellent | Never breaks ZFS |
| Ubuntu 24.04 | 2.2.x | Kernel module (prebuilt) | Native installer | Very good | Canonical rebuilds module |
| Proxmox VE 8 | 2.2.x | Prebuilt (Proxmox kernel) | Installer option | Very good | Proxmox rebuilds module |
| RHEL / Rocky 9 | 2.2.x | kABI kmod (prebuilt) | ZFSBootMenu / dracut | Very good | Stable ABI, rare breaks |
| CentOS Stream 9 | 2.2.x | kABI kmod (prebuilt) | ZFSBootMenu / dracut | Good | Slightly ahead of RHEL |
| Debian 13 (Trixie) | 2.2.x | DKMS (contrib) | ZFSBootMenu / dracut | Good | Recompiles on update |
| Fedora 41 | 2.2.x | DKMS (ZFS repo) | ZFSBootMenu / dracut | Risky | Frequent kernel churn |
| Arch Linux | 2.2.x | DKMS (archzfs / AUR) | ZFSBootMenu / dracut | Risky | Rolling release, no delay |
| Alpine Linux | 2.2.x | DKMS (community) | Manual initramfs | Good (musl caveats) | Stable within release |
| illumos (OmniOS, SmartOS) | 2.1.x (in-tree) | Native kernel code | Native | Excellent | Never breaks ZFS |
| macOS (OpenZFS on OS X) | 2.2.x (limited) | Kernel extension (kext) | No | Poor | Apple breaks kexts regularly |
| Windows (OpenZFS) | 2.2.x (beta) | Kernel driver | No | Experimental | Not production ready |
FreeBSD — the gold standard for ZFS
FreeBSD merged ZFS into its kernel source tree in 2007 and has maintained it as a first-class citizen ever since. There is no DKMS. There is no out-of-tree module. There is no separate build step. ZFS is the filesystem, compiled alongside the kernel, tested in the same CI pipeline, released in the same binary. When you install FreeBSD, you get ZFS the way it was designed to work.
FreeBSD's ZFS advantages over Linux:
bectl is built into the base system. Create a boot environment before any upgrade, roll back in seconds if it breaks. No GRUB hacks, no ZFSBootMenu — the bootloader understands ZFS natively.zfs set sharenfs=on tank/data and it just works. Linux requires additional middleware (nfs-kernel-server, exportfs) and POSIX ACL translation.zfs jail delegates a dataset into a jail with full admin capabilities. No Docker storage driver indirection.zfs clone — instant, no disk copy.freebsd-update or pkg upgrade updates everything atomically. In 15+ years, a kernel update has never broken ZFS on FreeBSD.# FreeBSD: ZFS root install — the installer handles everything
# After install, boot environments are one command:
bectl create pre-upgrade
bectl activate pre-upgrade # rollback if upgrade breaks
# Check ZFS version
sysctl vfs.zfs.version.module
# 2.2.6
# Pool status — same zpool/zfs commands as Linux
zpool status
zfs list
# Delegate a dataset to a jail
zfs create tank/jails/webserver
zfs jail webserver tank/jails/webserver
# Inside the jail, the dataset is fully manageable
# bhyve VM on a ZFS zvol
zfs create -V 50G tank/vms/myvm
bhyve -m 4G -c 2 -s 0,hostbridge -s 1,lpc \
-s 2,virtio-blk,/dev/zvol/tank/vms/myvm \
-l com1,stdio myvm
# Snapshot a running VM's disk (crash-consistent):
zfs snapshot tank/vms/myvm@before-upgrade
# Instant. Zero I/O. No VM pause needed.
illumos — the direct descendant
illumos is the open-source continuation of the Solaris kernel. Distributions like OmniOS and SmartOS run ZFS natively, just like Solaris did. ZFS was born here. The code paths are the most battle-tested, the ARC integration is the most refined, and the DTrace observability tools for ZFS were written on this platform.
illumos uses an older branch of OpenZFS (typically 2.1.x, with backported patches) and updates more slowly than Linux or FreeBSD. This conservatism is intentional — illumos targets storage appliances and cloud infrastructure where stability matters more than features. SmartOS powers Joyent/Samsung's cloud infrastructure. OmniOS powers storage servers at enterprises that migrated from Solaris.
The trade-off: illumos has a smaller package ecosystem than FreeBSD or Linux, fewer hardware drivers, and a steeper learning curve for administrators who grew up on Linux. Unless you have a specific Solaris/illumos requirement, FreeBSD provides a similar ZFS experience with a larger community.
Linux — the out-of-tree module problem
On Linux, ZFS cannot be included in the mainline kernel. The CDDL license (ZFS) and GPL (Linux kernel) are incompatible — or at least, the Linux kernel maintainers and Canonical's lawyers disagree on whether they are. The result: ZFS on Linux is an out-of-tree kernel module that must be compiled against your exact running kernel version, every time that kernel changes.
This compilation happens via DKMS (Dynamic Kernel Module Support). When you install a new kernel package, DKMS triggers a build of the ZFS module against the new kernel headers. If the build succeeds, you reboot into the new kernel with a working ZFS module. If it fails — because the new kernel changed an internal API that ZFS depends on — you reboot into a kernel that cannot mount your ZFS pools.
The failure mode is insidious. DKMS runs during package installation, often buried in a wall of
apt upgrade output. The build can fail silently — the kernel package installs
successfully, the GRUB menu gets updated, and you don't notice the DKMS error until you reboot
and your root pool won't mount. If you're running ZFS on root, that means an unbootable system.
If you're running ZFS on data pools only, you boot fine but your data is gone until you fix the module.
# How DKMS works — the lifecycle of a ZFS kernel module
# 1. Install ZFS DKMS package (provides source)
dnf install zfs-dkms # RHEL/CentOS/Rocky/Fedora
apt install zfs-dkms # Debian
# 2. DKMS compiles the module against current kernel
dkms status
# zfs/2.2.6, 5.14.0-503.el9.x86_64, x86_64: installed
# 3. When a new kernel is installed, DKMS auto-triggers:
# dkms build zfs/2.2.6 -k 5.14.0-510.el9.x86_64
# dkms install zfs/2.2.6 -k 5.14.0-510.el9.x86_64
# 4. Check that it worked BEFORE rebooting:
dkms status | grep zfs
modinfo zfs | grep vermagic
# 5. If DKMS failed, DO NOT REBOOT. Fix the build first.
# Common failure: missing kernel headers
dnf install kernel-devel-$(uname -r) # RPM distros
apt install linux-headers-$(uname -r) # Debian/Ubuntu
# Rebuild manually:
dkms build zfs/2.2.6 -k $(uname -r)
dkms install zfs/2.2.6 -k $(uname -r)
The Linux kernel ABI problem — why this keeps breaking
To understand why ZFS on Linux is fragile, you need to understand what the Linux kernel
doesn't promise. The Linux kernel has a stable userspace ABI (system
calls don't change) but no stable kernel-internal ABI. Functions that kernel
modules call — like bio_alloc(), vfs_fsync(), or
inode_operations struct layouts — can change between any two kernel releases
without notice.
This is a deliberate design choice. Greg Kroah-Hartman, the stable kernel maintainer, has written extensively about why: a stable kernel ABI would prevent internal refactoring, calcify bad design decisions, and create a support burden for interfaces that should be free to evolve. For in-tree modules, this is fine — they get updated alongside the kernel. For out-of-tree modules like ZFS, it means constant maintenance.
The OpenZFS codebase contains a directory called config/ with hundreds of
kernel compatibility checks. Each check tests whether a specific kernel API
exists in its old or new form, and the ZFS build system selects the appropriate compatibility
shim. When a new kernel changes an API that ZFS uses, the OpenZFS team must:
#ifdef block provides both the old and new API call. ZFS has hundreds of these.The time between "new kernel lands in a distro" and "OpenZFS has a compatible release" is the danger window. On RHEL/Rocky, this window is effectively zero (kABI guarantee). On Ubuntu, it's zero (Canonical builds the module). On Fedora and Arch, it can be days to weeks.
kABI-tracking vs pure DKMS — why EL9 is different
Not all Linux distributions treat kernel updates the same way. The Enterprise Linux
family (RHEL, CentOS Stream, Rocky Linux, AlmaLinux) maintains a kernel ABI (kABI)
stability guarantee: the internal kernel interfaces that modules depend on do not change within a
major release. RHEL 9's kernel might go from 5.14.0-70 to 5.14.0-503, but
the function signatures ZFS calls remain identical.
This means that on EL9, a ZFS module compiled against 5.14.0-70 still works
on 5.14.0-503 without recompilation. The zfs-kmod package from the ZFS on Linux
repo provides precompiled, kABI-tracking modules that survive kernel updates without DKMS. This is a
massive operational advantage.
On Debian, Fedora, Arch, and Ubuntu (without Canonical's prebuilt module), there is no kABI guarantee. Every kernel update requires DKMS recompilation. If the OpenZFS team hasn't patched compatibility for the new kernel yet, you're stuck on the old kernel or you're stuck without ZFS.
Here is the critical distinction between the three module delivery methods:
| Method | Compilation | Headers Required | Breaks on Kernel Update | Used By |
|---|---|---|---|---|
| In-tree (native) | Part of kernel build | No | Never | FreeBSD, illumos, Proxmox |
| Prebuilt kmod | Precompiled RPM/deb | No | Rarely (kABI break) | RHEL, Rocky, Ubuntu, CentOS |
| DKMS | Compiled locally | Yes (kernel-devel) | On every kernel update | Debian, Fedora, Arch, Alpine |
# EL9: Use kABI-tracking kmod instead of DKMS — much safer
# The zfs-kmod package is prebuilt and kABI-tracked
dnf install https://zfsonlinux.org/epel/zfs-release-2-4.el9.noarch.rpm
dnf install zfs
# Verify it's the kmod (prebuilt), not DKMS:
rpm -qa | grep zfs
# zfs-2.2.6-1.el9.x86_64
# zfs-kmod-2.2.6-1.el9.x86_64 <-- kABI-tracked, no DKMS
# vs DKMS (compile-from-source, fragile):
# zfs-dkms-2.2.6-1.el9.noarch <-- this means you're on DKMS
# Switch from DKMS to kmod on EL9:
dnf remove zfs-dkms
dnf install zfs-kmod
# Done. No more DKMS builds. No more kernel-devel dependency.
zfs-dkms
instead of zfs-kmod, stop what you're doing and switch. The kmod package is precompiled, tested,
and guaranteed to work with every EL9 kernel. DKMS on EL is unnecessary risk for zero benefit. I've seen
production systems break because someone installed zfs-dkms instead of zfs (which
pulls in zfs-kmod by default). The package names are confusing. Always verify with rpm -qa | grep zfs.
Ubuntu 24.04 — the exception on Linux
Ubuntu is the only mainstream Linux distribution that ships ZFS as a prebuilt kernel module
in its main kernel package. Since Ubuntu 19.10, Canonical has compiled the ZFS module as part of
their kernel build process and ships it alongside every kernel update. When you run
apt upgrade and get a new kernel, the matching ZFS module comes with it. No DKMS.
No compilation. No prayer.
This is possible because Canonical's legal team concluded that shipping ZFS as a kernel module (not linked into the kernel binary) does not violate the GPL. This interpretation is contested by some in the Linux community, and the FSF disagrees. But Canonical has shipped ZFS this way since 2019 without legal challenge, and at this point, it's a settled fact of the Ubuntu ecosystem.
Ubuntu's ZFS installer support is also the best on Linux. The Ubiquity/Subiquity installer offers
ZFS on root as a checkbox option. It creates the pool, datasets, boot environment, and GRUB
configuration automatically. No manual partitioning. No command-line wizardry. Ubuntu also ships
zsys, a daemon that automatically creates ZFS snapshots before package upgrades —
giving you automatic boot environment management similar to FreeBSD's bectl.
# Ubuntu: ZFS is already there — no additional repos needed
dpkg -l | grep zfs
# ii zfsutils-linux 2.2.6-0ubuntu1 amd64 command-line tools for ZFS
# ii zfs-modules-6.8.0-45-generic ... prebuilt kernel module
# After kernel update, the new module is already installed:
apt upgrade
# The following packages will be upgraded:
# linux-image-6.8.0-48-generic zfs-modules-6.8.0-48-generic
# No DKMS, no manual build, no risk of build failure.
modinfo zfs | grep version
# version: 2.2.6
# Ubuntu-specific: zsys automatic snapshots
zsysctl show
# Shows automatic snapshots taken before each apt upgrade
# Revert to a previous state from the GRUB menu at boot
# Ubuntu also supports ZFS encryption on root (installer option):
# Creates a native ZFS encrypted dataset for the root filesystem
# Prompts for passphrase at boot via systemd-ask-password
CentOS Stream 9 — kldload's live environment
kldload uses CentOS Stream 9 as its live ISO environment. This is deliberate: CentOS Stream 9 tracks slightly ahead of RHEL 9, giving us the latest EL9 kernel with the kABI stability guarantee. The ZFS module is compiled and signed at ISO build time against the exact kernel shipping in the image, then baked into the initramfs with dracut. When the ISO boots, ZFS is already loaded — no internet, no DKMS, no runtime compilation.
For target installs (the distro you install onto the disk), CentOS Stream 9 uses the same
kABI-tracked zfs-kmod package as RHEL and Rocky. The kldload installer downloads and
installs it from the embedded RPM darksite — fully offline.
CentOS Stream 9 sits in an interesting position: it receives kernel patches before RHEL 9, making it a preview of what RHEL will ship next. This means the kABI guarantee is slightly weaker than RHEL — Red Hat occasionally introduces new kABI symbols in CentOS Stream before they land in RHEL. In practice, this has never broken ZFS, because the kmod packages track the EL9 kABI baseline, not every CentOS Stream kernel individually.
# kldload ISO boot sequence for ZFS:
# 1. Kernel loads from squashfs (CentOS Stream 9 kernel)
# 2. Dracut initramfs includes prebuilt zfs.ko, signed with MOK key
# 3. ZFS module loads immediately — no DKMS, no internet
# 4. Root pool mounts from the squashfs overlay
# Verify on a running kldload ISO:
modinfo zfs
# filename: /lib/modules/5.14.0-xxx.el9.x86_64/extra/zfs/zfs.ko
# version: 2.2.6
# license: CDDL
# sig_key: ... (kldload MOK signing key)
# CentOS Stream 9 kernel version tracking:
uname -r
# 5.14.0-503.el9.x86_64 (CentOS Stream)
# vs RHEL 9.5: 5.14.0-503.11.1.el9_5.x86_64
# Same base version, slightly different patch level
Debian 13 (Trixie) — contrib repo, DKMS required
Debian ships ZFS in the contrib repository, not main. This is a licensing
distinction, not a quality one: Debian's policy requires that packages in main contain only
DFSG-free software, and the CDDL license creates a conflict with the GPL kernel. The ZFS
userspace tools (zfsutils-linux) and DKMS source (zfs-dkms) live
in contrib.
Unlike Ubuntu, Debian does not ship a prebuilt ZFS kernel module. You must use DKMS, which compiles the module against your running kernel every time you install or upgrade a kernel package. Debian's kernel update cadence is conservative within a stable release, so DKMS breakage is rare — but it happens, especially on point releases that jump kernel minor versions.
Debian's DKMS compilation requires the linux-headers package matching your running
kernel, plus a working GCC toolchain. On minimal server installs, these may not be present.
A common failure mode: the system is installed with linux-headers-amd64 (a meta-package
that tracks the latest headers), a kernel update pulls in new headers, and the old headers
get autoremoved. If you reboot into the old kernel, DKMS can't rebuild because the headers are gone.
# Debian 13: Enable contrib and install ZFS
# Method 1: Edit sources.list
echo "deb http://deb.debian.org/debian trixie main contrib" > /etc/apt/sources.list
apt update
# Install ZFS with all dependencies
apt install linux-headers-amd64 zfs-dkms zfsutils-linux
# DKMS compiles on install — takes 2-5 minutes:
dkms status
# zfs/2.2.6, 6.12.6-amd64, x86_64: installed
# Load the module:
modprobe zfs
zpool status
# IMPORTANT: Keep headers installed for your running kernel
# Don't let apt autoremove them:
apt-mark manual linux-headers-$(uname -r)
# Verify DKMS will rebuild on next kernel update:
cat /etc/dkms/framework.conf | grep -i autoinstall
Debian's ZFS support is solid once installed, but the initial setup requires more steps than Ubuntu. The kldload installer handles all of this automatically, including the contrib repo configuration and DKMS compilation, pulling packages from the embedded Debian darksite. The darksite includes both the ZFS source packages and the kernel headers, so the entire DKMS compilation happens offline.
dkms status after every apt upgrade
and before every reboot. If it says "installed" for your target kernel, you're good. If it says "built" or
nothing, do not reboot.
Fedora — fast kernels, fragile DKMS
Fedora's rapid release cycle (every ~6 months) and aggressive kernel updates make it the highest-risk platform for ZFS among mainstream Linux distributions. Fedora ships new major kernel versions within weeks of upstream release. The OpenZFS team often needs days to weeks to add compatibility shims for new kernel APIs. During that window, DKMS builds fail.
Fedora does not ship ZFS in any official repository. You must add the ZFS on Linux repo
(zfsonlinux.org) and install DKMS packages. There is no kABI guarantee and no
prebuilt kernel module. Every kernel update is a potential breakpoint.
The concrete risk: Fedora 41 shipped with kernel 6.11 and has already moved to 6.12+ through
routine updates. Each jump can introduce API changes that break the ZFS DKMS build. If you run
dnf update without checking ZFS compatibility first, you may end up with a new kernel
installed, no ZFS module for it, and GRUB pointing at the new kernel by default. Reboot, and your
ZFS pools don't mount.
# Fedora: Install ZFS from ZFS on Linux repo
dnf install https://zfsonlinux.org/fedora/zfs-release-2-5$(rpm --eval "%{dist}").noarch.rpm
dnf install kernel-devel zfs
# CRITICAL: Pin kernel updates until ZFS compatibility is confirmed
# In /etc/dnf/dnf.conf:
# exclude=kernel* kernel-devel*
# Only upgrade the kernel when you've confirmed ZFS supports the new version:
# Check: https://github.com/openzfs/zfs/releases
# Then: dnf update --disableexcludes=all
# After kernel update, verify DKMS built successfully BEFORE rebooting:
dkms status | grep zfs
# Nuclear option: keep the last known-good kernel
# In /etc/dnf/dnf.conf:
# installonly_limit=5 (keep 5 kernels instead of default 3)
# This gives you more rollback options in GRUB
# If DKMS failed and you already rebooted into the new kernel:
# Boot the old kernel from GRUB (Advanced Options)
# Then pin that kernel and wait for a ZFS update
RHEL 9 / Rocky Linux 9 — the enterprise sweet spot
RHEL and Rocky Linux offer the best ZFS experience on Linux after Ubuntu, for a
completely different reason: kABI stability. Red Hat guarantees that the kernel ABI does not change
within a major release. RHEL 9 shipped with kernel 5.14 and will maintain the same
internal interfaces through its entire 10-year lifecycle. This means a ZFS module compiled once
works for years without recompilation.
The ZFS on Linux project ships precompiled zfs-kmod RPMs that track the EL9 kABI.
No DKMS required. No compilation. No kernel headers. Install the RPM, load the module, it works.
It will continue working through every minor RHEL 9 update until RHEL 10. Rocky Linux is a 1:1
binary-compatible rebuild of RHEL. AlmaLinux is the same. The ZFS kmod packages are identical across all three.
# RHEL 9 / Rocky 9: Install ZFS the right way (kmod, not DKMS)
dnf install https://zfsonlinux.org/epel/zfs-release-2-4.el9.noarch.rpm
dnf install zfs
# That's it. No DKMS, no kernel-devel, no compilation.
modprobe zfs
zpool status
# This module will survive every RHEL 9.x / Rocky 9.x kernel update
# without rebuilding. kABI guarantee.
# Enable ZFS module auto-load on boot:
echo "zfs" > /etc/modules-load.d/zfs.conf
systemctl enable zfs-import-cache zfs-mount zfs.target
# Verify everything is clean:
zpool status -v # check pool health
dkms status # should show nothing (no DKMS needed)
rpm -qa | grep zfs # should show zfs-kmod, not zfs-dkms
The one caveat: RHEL major releases (RHEL 10, expected 2025-2026) ship a new kernel with a new kABI baseline. The ZFS kmod will need to be recompiled for the new ABI. But this happens once per major release (every 3-5 years), and the ZFS on Linux project typically has new kmod packages ready before the RHEL release date.
Arch Linux — rolling release, rolling risk
Arch Linux is a rolling release distribution: there are no version numbers, no stable releases, no frozen kernel versions. When upstream Linux ships kernel 6.13, Arch has it in the repos within days. This makes Arch the most aggressive kernel updater of any distribution, and therefore the most dangerous platform for out-of-tree modules like ZFS.
Three options exist for ZFS on Arch:
zfs-linux (prebuilt) or zfs-linux-git (latest git). Kernel updates are held until a matching ZFS package exists.linux-headers and a working compiler toolchain.linux-lts package (currently kernel 6.6.x) alongside the mainline kernel. Using the LTS kernel reduces the risk of ZFS breakage because LTS kernels receive fewer API changes. Combine with archzfs zfs-linux-lts for best stability.# Arch: Using the archzfs repo (recommended)
# Add to /etc/pacman.conf:
# [archzfs]
# Server = https://archzfs.com/$repo/$arch
# Import the archzfs signing key:
pacman-key -r DDF7DB817396A49B2A2723F7403BD972F75D9D76
pacman-key --lsign-key DDF7DB817396A49B2A2723F7403BD972F75D9D76
pacman -Sy archzfs-linux
# CRITICAL: Lock kernel updates to archzfs-compatible versions
# Check current compatibility:
pacman -Si zfs-linux | grep "Depends On"
# SAFER: Use the LTS kernel with archzfs
pacman -S linux-lts linux-lts-headers zfs-linux-lts
# AUR alternative (DKMS, higher risk):
yay -S zfs-dkms
# Requires: linux-headers, base-devel
# Partial upgrade protection — ignore kernel in pacman.conf:
# IgnorePkg = linux linux-headers
# Then manually upgrade when archzfs has a matching package
pacman -Syu away from an incompatible kernel. The Arch
wiki's ZFS page is excellent and honest about the risks. kldload supports Arch, but without a darksite
(rolling release means no frozen package set). You need internet for Arch installs. If you insist on
Arch + ZFS, use linux-lts and the archzfs LTS packages. It's still Arch, just with a kernel
that doesn't change every week.
Alpine Linux — musl libc considerations
Alpine Linux uses musl libc instead of glibc. This matters for ZFS because the
OpenZFS userspace tools and DKMS build system were developed and tested primarily against glibc.
musl has subtle behavioral differences: different strerror() output, different
getmntent() behavior, different thread cancellation semantics. The OpenZFS project
has addressed most of these, but edge cases remain.
Alpine ships ZFS packages in its community repository. The kernel module is built as a DKMS package. Alpine's small, security-focused kernel (based on the linux-lts branch) changes infrequently within a release, so DKMS breakage is less common than on Fedora or Arch.
The musl-specific issues you'll encounter in practice:
strerror() produces different text than glibc. Scripts that parse ZFS error output by string matching (instead of exit codes) may break. Always use $? for error detection.getmntent() has slightly different parsing behavior. In rare cases, zfs mount -a may behave differently than on glibc systems, especially with complex mountpoint hierarchies.zfs send streams), you may see different behavior than on glibc-based systems.# Alpine: Enable community repo and install ZFS
echo "http://dl-cdn.alpinelinux.org/alpine/v3.21/community" >> /etc/apk/repositories
apk update
apk add zfs zfs-lts linux-lts-dev
# Load the module:
modprobe zfs
zpool status
# Alpine uses OpenRC, not systemd — different service management:
rc-update add zfs-import boot
rc-update add zfs-mount boot
rc-service zfs-import start
rc-service zfs-mount start
# Verify module version:
modinfo zfs | grep version
# Alpine-specific consideration: musl libc
# Some ZFS error messages may differ from glibc-based systems
# Shell scripts that parse ZFS output should use exit codes, not string matching
Alpine's primary use case for ZFS is container hosts and embedded appliances where the small base image (5MB) matters. For NAS or storage servers, Debian or Rocky are more thoroughly tested. kldload supports Alpine installs, but like Arch, no darksite is available — internet is required.
Proxmox VE — Debian with built-in ZFS
Proxmox VE deserves special mention because it's the most popular Linux-based virtualization platform
that ships ZFS as a first-class feature. Proxmox is based on Debian but compiles its own kernel
(pve-kernel) with the ZFS module built-in, similar to how Ubuntu does it.
You don't need DKMS. You don't need the ZFS on Linux repo. ZFS comes with the Proxmox kernel package.
The Proxmox installer offers ZFS on root as a checkbox option (RAID0, RAID1, RAIDZ1, RAIDZ2, RAIDZ3).
The web UI manages ZFS pools, datasets, snapshots, and replication natively. VM disk images live on
ZFS zvols, and container rootfs live on ZFS datasets. Backups use zfs send under the hood
when backing up to a ZFS-based Proxmox Backup Server.
# Proxmox: ZFS is built into the kernel — no additional setup
dpkg -l | grep pve-kernel
# ii pve-kernel-6.8.12-3-pve ... Proxmox kernel with ZFS built-in
# No zfs-dkms needed. The module is part of pve-kernel.
modinfo zfs
# filename: /lib/modules/6.8.12-3-pve/kernel/zfs/zfs.ko
# Proxmox CLI for ZFS management:
pvesm add zfspool tank-storage --pool tank/vm-storage
# Adds a ZFS pool as a Proxmox storage backend
# Create a mirrored root pool during Proxmox install:
# The installer handles this. After install:
zpool status rpool
# NAME STATE STATUS
# rpool ONLINE
# mirror-0 ONLINE
# sda2 ONLINE
# sdb2 ONLINE
# Proxmox + ZFS replication to another node:
pvesr create-local-job 100 --target pve2 --schedule "*/15"
# Replicates VM 100 to pve2 every 15 minutes using zfs send
macOS — OpenZFS on OS X
The OpenZFS on OS X project (O3X, now OpenZFS for macOS) provides ZFS as a kernel extension (kext). Apple has been deprecating kexts since macOS 10.15 Catalina in favor of DriverKit/SystemExtensions, and each major macOS release tightens the restrictions further. On Apple Silicon Macs, loading unsigned kexts requires reducing system security to "Permissive" in recovery mode.
The project history tells the story. The original MacZFS project was actively maintained through the mid-2010s. When Apple introduced System Integrity Protection (SIP) in El Capitan, kext loading became harder. When Apple deprecated kexts in Catalina, the writing was on the wall. When Apple shipped Apple Silicon and required reduced security for third-party kexts, the project effectively moved to life support.
The practical result: ZFS on macOS is read/write functional for data pools but not viable as a root filesystem, not suitable for production storage, and increasingly difficult to maintain. Every major macOS release risks breaking the kext, and Apple provides no stable kext ABI.
Realistic use case: Mounting ZFS pools created on Linux or FreeBSD to transfer data to a Mac. That's about it. If you need ZFS storage accessible from a Mac, export it over NFS or SMB from a FreeBSD or Linux server.
# macOS: Install OpenZFS for macOS
# Download from https://openzfsonosx.org/
# Requires: SIP partially disabled, or "Reduced Security" on Apple Silicon
# After install (Intel Mac):
sudo kextload /Library/Extensions/zfs.kext
zpool import tank
zfs list
# Apple Silicon Mac — requires additional steps:
# 1. Boot into Recovery Mode (hold Power button)
# 2. Startup Security Utility → Reduced Security
# 3. Check "Allow user management of kernel extensions"
# 4. Reboot and approve the kext in System Preferences → Security
# WARNING: Every macOS update may require re-approval of the kext
# WARNING: macOS 15+ may remove kext support entirely
Windows — OpenZFS for Windows
The OpenZFS for Windows project provides a native Windows kernel driver that implements ZFS as a Windows filesystem. It's real, it works, and it's been in active development since 2020. You can create pools, mount datasets, use snapshots, and even boot Windows from ZFS (experimentally).
However, this is not production-ready. Known limitations include: incomplete ACL mapping between ZFS and NTFS, limited testing with Windows Update (which can overwrite filesystem drivers), no Secure Boot signing (requires test mode), and performance that trails Linux and FreeBSD significantly. The project is impressive as a proof of concept, but recommending it for data you care about would be irresponsible.
Realistic use case: Same as macOS — mounting ZFS pools to access data created elsewhere. For Windows servers that need ZFS-class storage, run a FreeBSD or Linux VM with ZFS and export over SMB/iSCSI. Windows Server's native Storage Spaces Direct (S2D) provides some ZFS-like features (checksumming, erasure coding, tiering) but lacks snapshots, send/recv, inline compression, and the operational simplicity of ZFS.
# Windows: Install OpenZFS for Windows
# Download from https://github.com/openzfsonwindows/openzfs
# Requires: Test Mode enabled (bcdedit /set testsigning on)
# After install (PowerShell as Administrator):
zpool.exe import tank
zfs.exe list
# WARNING: Test Mode disables Secure Boot verification
# WARNING: Windows Update may overwrite or conflict with the driver
# WARNING: Performance is 30-60% below Linux/FreeBSD for same hardware
# Better alternative: Run ZFS in a Linux/FreeBSD VM on Hyper-V
# Share storage via SMB or iSCSI to the Windows host
OpenZFS version compatibility
OpenZFS uses feature flags instead of a single version number to track pool and
dataset capabilities. Each feature (e.g., large_blocks, encryption,
draid) can be independently enabled. A pool is compatible with any platform that
supports all of the features enabled on that pool.
| OpenZFS Version | Key Features Added | Pool Version | Min Kernel (Linux) |
|---|---|---|---|
| 0.8 | Native encryption, TRIM, device removal, persistent L2ARC | 5000 | 2.6.32+ |
| 2.0 | Unified Linux+FreeBSD codebase, project_quota, redaction bookmarks | 5000 | 3.10+ |
| 2.1 | dRAID, compatibility property, inflated_blocks_are_zero | 5000 | 3.10+ |
| 2.2 | Block cloning, RAIDZ expansion (experimental), fast dedup | 5000 | 4.18+ |
| 2.3 (dev) | RAIDZ expansion (stable), JSON output, persistent L2ARC improvements | 5000 | 4.18+ |
The pool version has been frozen at 5000 since the feature-flags system was introduced. New capabilities are added as feature flags, not version bumps. This means a pool created on OpenZFS 2.0 can be imported on OpenZFS 2.2 — and vice versa, as long as no 2.2-only features have been enabled.
Upgrading a pool to enable new features is a one-way operation. Once you run
zpool upgrade on a pool, it enables all features supported by your current
OpenZFS version. If you later need to import that pool on an older system, it may fail
because the older system doesn't know about the new features. Never run
zpool upgrade on a pool that might need to move to an older OpenZFS system.
# Check what features a pool has enabled:
zpool get all tank | grep feature@
# feature@async_destroy enabled local
# feature@encryption active local
# feature@block_cloning disabled local
# Feature states:
# "enabled" — pool supports this feature, but no data uses it yet
# "active" — data on the pool uses this feature (REQUIRES this feature for import)
# "disabled" — feature available but not enabled
# Upgrade a pool to enable all available features (ONE WAY):
zpool upgrade tank
# WARNING: This enables features that may prevent import on older systems
# Enable a specific feature without upgrading everything:
zpool set feature@block_cloning=enabled tank
# Check which version of OpenZFS you're running:
zfs version
# zfs-2.2.6-1
# zfs-kmod-2.2.6-1
Feature flags & cross-platform pool portability
ZFS pools are portable. You can physically move disks between a FreeBSD server and a Linux server,
zpool import, and your data is there. The filesystem is platform-independent —
byte order, struct layout, and on-disk format are all defined by the ZFS specification, not the
operating system. But feature flags determine whether a pool can be imported writable
on a given platform.
The rules are simple:
draid enabled but the target system runs OpenZFS 1.x (which doesn't know draid), read-write import fails.zpool create -o compatibility=openzfs-2.0-linux to restrict feature flags to a known-compatible set. Use this for pools that will move between platforms.Compatibility files — the cross-platform safety net
OpenZFS ships a set of compatibility files in /usr/share/zfs/compatibility.d/.
Each file lists the feature flags supported by a specific platform at a specific version. When you
create a pool with -o compatibility=<file>, only the features listed in that file
are enabled, ensuring the pool can be imported on that platform.
| Compatibility File | Use Case | Features Restricted |
|---|---|---|
openzfs-2.0-linux |
Pool must import on any OpenZFS 2.0+ Linux | No dRAID, no block cloning |
openzfs-2.1-linux |
Pool must import on OpenZFS 2.1+ | No block cloning, no fast dedup |
freebsd-14.0 |
Pool will move between FreeBSD 14 and Linux | FreeBSD-compatible feature set only |
openzfs-2.0-freebsd |
Maximum FreeBSD compatibility | Conservative feature set |
| (none specified) | Pool stays on one platform forever | All features enabled (best performance) |
# Create a pool with maximum cross-platform compatibility
zpool create -o ashift=12 -o compatibility=openzfs-2.1-linux \
-O compression=lz4 -O atime=off \
portable mirror /dev/sda /dev/sdb
# Check which features are active on a pool:
zpool get all tank | grep feature@
# List available compatibility files:
ls /usr/share/zfs/compatibility.d/
# freebsd-13.0 freebsd-14.0 openzfs-2.0-freebsd openzfs-2.0-linux
# openzfs-2.1-freebsd openzfs-2.1-linux openzfs-2.2-linux ...
# Import a pool from another platform (read-only if unsure):
zpool import -o readonly=on foreign-pool
zpool status foreign-pool
# If it looks good, re-import read-write:
zpool export foreign-pool
zpool import foreign-pool
# Moving a pool from Linux to FreeBSD:
# 1. On Linux: zpool export tank
# 2. Move disks to FreeBSD machine
# 3. On FreeBSD: zpool import tank
# Works if feature flags are compatible. Check with:
zpool get compatibility tank
compatibility property. If you're building a pool that stays on one platform forever,
don't bother — enable everything, get full performance. The compatibility files ship with OpenZFS and
are maintained by the project. I've moved pools between FreeBSD and Linux dozens of times. It works. The
on-disk format is genuinely portable. The only time I've had issues is with encryption
feature + key management differences between platforms. If your pool is encrypted, test the import before
you commit.
Kernel version requirements (Linux)
OpenZFS has minimum kernel version requirements. Using a kernel that's too old means missing features or outright build failures. Using a kernel that's too new (before the OpenZFS team patches compatibility) means the same thing. The sweet spot is a kernel that's been shipping for 3–6 months.
| Distro | Kernel Version | Kernel Age | ZFS Risk Level | Recommended Action |
|---|---|---|---|---|
| RHEL / Rocky 9 | 5.14 (patched) | Frozen since 2022 | Minimal | Use zfs-kmod. No action needed. |
| CentOS Stream 9 | 5.14 (patched, slightly ahead) | ~2 weeks ahead of RHEL | Low | Use zfs-kmod. Same as RHEL. |
| Ubuntu 24.04 | 6.8 | Frozen at release | Low (Canonical builds module) | No action needed. |
| Proxmox VE 8 | 6.8 (pve-kernel) | Proxmox-managed | Low | No action needed. |
| Debian 13 | 6.12 | Frozen at release | Moderate (DKMS) | Check dkms status after kernel updates. |
| Fedora 41 | 6.11–6.13+ | Updates every 2–4 weeks | High | Pin kernel. Check OpenZFS releases first. |
| Arch Linux | 6.12–6.14+ | Days behind upstream | Highest | Use linux-lts + archzfs. |
| Alpine 3.21 | 6.6 (lts) | LTS branch, stable | Moderate (musl caveats) | Test ZFS tools after each update. |
The maximum kernel version problem
Each OpenZFS release has an implicit maximum supported kernel version. The release notes list "supported kernels: 4.18 - 6.11" (or similar). If your distro ships a kernel newer than the maximum, DKMS will fail. This is the root cause of most ZFS breakage on Fedora and Arch.
# Check OpenZFS kernel compatibility before upgrading:
# 1. Find your target kernel version:
dnf list --available kernel # RPM distros
apt list --upgradable 2>/dev/null | grep linux-image # Debian/Ubuntu
# 2. Check the OpenZFS release notes:
# https://github.com/openzfs/zfs/releases
# Look for "Supported Kernels" in the release notes
# 3. If the target kernel exceeds the max, DO NOT upgrade.
# Wait for the next OpenZFS point release.
# 4. If you already upgraded and DKMS failed:
# Boot the old kernel from GRUB (Advanced Options)
# Then hold the kernel:
dnf versionlock add kernel-$(uname -r) # RPM
apt-mark hold linux-image-$(uname -r) # Debian
Signing kernel modules — Secure Boot & MOK
If Secure Boot is enabled, the kernel refuses to load unsigned modules. Since ZFS is out-of-tree, it's not signed by the distribution's kernel signing key. You have two options: disable Secure Boot (simple but reduces security), or sign the ZFS module yourself using MOK (Machine Owner Key).
MOK enrollment works by generating a keypair, enrolling the public key in UEFI firmware via
mokutil, and signing the module with the private key. The firmware then trusts modules
signed by your key in addition to the distribution key. This is a one-time setup per machine, but
the module must be re-signed every time DKMS rebuilds it.
Platform-specific Secure Boot behavior
# Generate a MOK keypair
openssl req -new -x509 -newkey rsa:2048 -keyout /root/mok.key \
-outform DER -out /root/mok.der -nodes -days 36500 \
-subj "/CN=ZFS Module Signing Key/"
# Enroll the public key in UEFI firmware
mokutil --import /root/mok.der
# Enter a one-time password. On next reboot, the UEFI MOK manager
# prompts you to confirm enrollment with this password.
# Sign the ZFS module
/usr/src/kernels/$(uname -r)/scripts/sign-file sha256 \
/root/mok.key /root/mok.der \
/lib/modules/$(uname -r)/extra/zfs/zfs.ko
# Also sign spl.ko if it exists as a separate module:
/usr/src/kernels/$(uname -r)/scripts/sign-file sha256 \
/root/mok.key /root/mok.der \
/lib/modules/$(uname -r)/extra/zfs/spl.ko
# Reboot, confirm MOK enrollment in UEFI, then verify:
modinfo zfs | grep sig
# sig_id: PKCS#7
# signer: ZFS Module Signing Key
# AUTOMATE: Configure DKMS to auto-sign after every build
# Create /etc/dkms/sign_helper.sh:
#!/bin/bash
/usr/src/kernels/${kernelver}/scripts/sign-file sha256 \
/root/mok.key /root/mok.der "$1"
# In /etc/dkms/framework.conf add:
# sign_tool="/etc/dkms/sign_helper.sh"
# Now DKMS will sign the module automatically after each rebuild.
sign_tool config above automates it, but most people just disable Secure Boot and move on.
kldload automates this at build time: the ISO build generates a MOK keypair, compiles ZFS, signs the
module, and bakes the signed key into the initramfs. On target installs, kldload enrolls the MOK
automatically during the install process. You never touch mokutil or sign-file.
That said, kldload's MOK auto-enrollment has edge cases on some UEFI implementations — some
firmware vendors don't implement the MOK manager correctly. When in doubt, disable Secure Boot in BIOS
and move on with your life.
ZFS in containers & virtual machines
ZFS is a kernel module. Containers share the host kernel. This creates specific constraints for running ZFS inside containerized or virtualized environments.
Docker ZFS storage driver
Docker can use ZFS as its storage backend. Each container layer becomes a ZFS clone,
giving you instant snapshots, efficient diffing, and native compression. Requires ZFS
on the host. Configure with "storage-driver": "zfs" in /etc/docker/daemon.json.
Layer pulls create thin clones instead of extracting tarballs — dramatically faster on slow disks.
Podman on ZFS
Podman supports the same ZFS storage driver as Docker. Configuration is in
/etc/containers/storage.conf with driver = "zfs". Podman's rootless
mode works with ZFS, though it requires zfs allow delegation to the unprivileged
user's datasets. Performance characteristics are identical to Docker.
LXC / LXD / Incus on ZFS
LXC containers on a ZFS host get the best of both worlds: each container's rootfs is a
ZFS dataset with its own snapshots, quotas, and compression. lxc copy uses ZFS
clones for instant container duplication. This is the closest Linux gets to FreeBSD's
jails-on-ZFS experience.
Kubernetes ZFS CSI driver
The openebs-zfs-csi driver provisions Kubernetes PersistentVolumes as ZFS datasets.
Each PVC gets its own dataset with configurable compression, quota, and reservation. Snapshots
and clones work through the Kubernetes VolumeSnapshot API. Works on any Linux distribution with ZFS.
ZFS inside a VM
Running ZFS inside a VM works fine. The guest sees virtual disks and runs ZFS normally. Performance depends on the hypervisor's I/O path: virtio-scsi is best, IDE is worst. The guest doesn't need the host to run ZFS — it's completely independent.
ZFS inside Docker (don't)
You cannot run ZFS inside a Docker container. ZFS is a kernel module, and containers
don't have their own kernel. The --privileged flag lets you access the host's ZFS,
but that's the host's module, not the container's. There is no container-level ZFS isolation.
Use ZFS on the host and let Docker use the ZFS storage driver.
# Docker: Configure ZFS storage driver
cat > /etc/docker/daemon.json << 'EOF'
{
"storage-driver": "zfs",
"storage-opts": [
"zfs.fsname=tank/docker"
]
}
EOF
zfs create -o mountpoint=/var/lib/docker tank/docker
systemctl restart docker
docker info | grep "Storage Driver"
# Storage Driver: zfs
# Podman: In /etc/containers/storage.conf:
# [storage]
# driver = "zfs"
# [storage.options.zfs]
# fsname = "tank/podman"
# Kubernetes: Install OpenEBS ZFS CSI driver
kubectl apply -f https://openebs.github.io/charts/zfs-operator.yaml
# Create a StorageClass backed by ZFS:
cat << 'EOF' | kubectl apply -f -
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: zfs-sc
provisioner: zfs.csi.openebs.io
parameters:
poolname: "tank/k8s"
compression: "lz4"
fstype: "zfs"
EOF
# Now PVCs using this StorageClass get ZFS datasets automatically
kldload's approach — compile, sign, and embed at build time
kldload solves the Linux ZFS integration problem at build time, not at boot time. The ISO build process runs inside a CentOS Stream 9 container and performs the following:
This approach means the live ISO always has a working, signed ZFS module regardless of what the
target distro is. The user can boot the ISO, create pools, partition disks, and run the installer
without any ZFS-related failures. The complexity of per-distro module management is hidden behind
the installer's library functions in bootstrap.sh and bootloader.sh.
# How kldload installs ZFS per distro (simplified):
# CentOS Stream 9 / RHEL / Rocky:
dnf --installroot=/mnt install zfs zfs-kmod
# Uses kABI-tracked kmod from embedded RPM darksite. No DKMS.
# Debian 13:
chroot /mnt apt install zfs-dkms zfsutils-linux linux-headers-amd64
# DKMS compiles from source. Headers come from embedded Debian darksite.
# Ubuntu 24.04:
chroot /mnt apt install zfsutils-linux
# Module ships with kernel package. Nothing else needed.
# Fedora 41:
dnf --installroot=/mnt install zfs kernel-devel
# DKMS from ZFS repo. Kernel pinned at install time.
# Arch Linux:
pacstrap /mnt zfs-linux
# From archzfs repo. Requires internet.
# Alpine Linux:
chroot /mnt apk add zfs zfs-lts
# From community repo. Requires internet.
Platform-specific troubleshooting
When ZFS breaks on a specific platform, the failure mode and recovery steps are platform-dependent. Here are the most common failures and their fixes.
dkms status. If it shows "added" (not "installed") for the new kernel, the build failed. Check /var/lib/dkms/zfs/*/build/make.log for the error. Most common cause: missing kernel-devel/headers, or kernel too new for this ZFS version.uname -r vs ls /lib/modules/ to see which kernels have ZFS. Run dkms autoinstall to rebuild for the current kernel, or install the correct kmod package.zpool import -o readonly=on poolname. If it works read-only, check zpool get all poolname | grep feature for "unsupported" features. Upgrade OpenZFS on the target to match the source.zfs-import-cache.service and zfs-mount.service are enabled. Check zpool.cache exists at /etc/zfs/zpool.cache. Regenerate with zpool set cachefile=/etc/zfs/zpool.cache tank.zfs-import and zfs-mount are in the boot runlevel: rc-update add zfs-import boot; rc-update add zfs-mount boot.options zfs zfs_arc_max=8589934592 in /etc/modprobe.d/zfs.conf (8GB example). FreeBSD handles this automatically through VM integration.strerror() returns different strings than glibc. The error codes are correct — the human-readable text may differ. Use exit codes for scripting, not string matching.# Emergency recovery: boot into a live environment with ZFS
# If your root-on-ZFS system won't boot:
# 1. Boot from kldload ISO (or any live ISO with ZFS)
# 2. Import the root pool:
zpool import -f -R /mnt rpool
# 3. Check pool health:
zpool status rpool -v
# 4. If the pool imported successfully, chroot and fix:
mount --bind /dev /mnt/dev
mount --bind /proc /mnt/proc
mount --bind /sys /mnt/sys
chroot /mnt
# Inside chroot: reinstall ZFS, rebuild initramfs, fix bootloader
# The exact commands depend on the distro (see sections above)
# 5. Exit chroot and reboot:
exit
zpool export rpool
reboot
# If the pool won't import at all:
dmesg | grep -i zfs # check for ZFS errors
lsmod | grep zfs # check module is loaded
modprobe zfs 2>&1 # if not loaded, see why
Choosing the right platform
Pure storage / NAS appliance
FreeBSD. No contest. Native ZFS, native NFS, jails for services, bhyve for VMs if needed. TrueNAS CORE is built on FreeBSD for exactly this reason. If your primary workload is serving files and managing storage, FreeBSD gives you the most stable, performant ZFS experience.
Enterprise servers with compliance requirements
RHEL or Rocky Linux with kmod. kABI stability means ZFS survives every kernel update. Red Hat support contract satisfies auditors. 10-year lifecycle means you're not upgrading the OS every 18 months. The EL9 kernel is boring, and boring is exactly what you want.
Desktop / developer workstation
Ubuntu. The prebuilt ZFS module means zero maintenance. The installer supports ZFS root. The desktop ecosystem (GNOME, Snap, PPA) is the largest on Linux. You get ZFS without thinking about it. zsys gives you automatic snapshots before every package upgrade.
Virtualization host
Proxmox VE. Debian-based with ZFS prebuilt into the kernel. Installer supports ZFS root. Web UI manages pools, snapshots, and replication. VM disks live on zvols. Container rootfs live on datasets. Rocky Linux with libvirt/KVM is the alternative for more control.
Containerized / cloud-native infrastructure
Rocky Linux or Debian with Docker/Podman ZFS storage driver. Stable kernel, stable ZFS, and the container ecosystem. For Kubernetes, add the OpenEBS ZFS CSI driver for per-PVC ZFS datasets.
Edge / embedded / minimal footprint
Alpine Linux. 5MB base image. ZFS from community repo. Ideal for IoT gateways, edge servers, and embedded appliances where disk and memory are constrained. musl libc differences are manageable with testing.
Bleeding edge / hobbyist
Arch Linux with linux-lts kernel and archzfs. You get Arch's package ecosystem and rolling updates, but with a kernel that doesn't break ZFS every week. Fedora is a second option for people who want the latest GNOME desktop with ZFS, but expect more manual kernel management.
Decision matrix — quick reference
Use this table when you need to pick a platform quickly. The "maintenance burden" column is the single most important factor for production systems — it measures how much ongoing work ZFS requires after initial setup.
| Platform | Install Difficulty | Maintenance Burden | Boot from ZFS | Best Workload |
|---|---|---|---|---|
| FreeBSD | Trivial | Zero | Native | Storage, NAS, appliances |
| Ubuntu | Trivial | Zero | Native installer | Desktop, dev, general purpose |
| Proxmox | Trivial | Zero | Native installer | Virtualization, hypervisor |
| RHEL / Rocky | Easy (add repo) | Near-zero | ZFSBootMenu | Enterprise, compliance |
| CentOS Stream | Easy (add repo) | Low | ZFSBootMenu | Dev/staging for RHEL |
| Debian | Moderate (DKMS) | Moderate | ZFSBootMenu | Servers, containers |
| Alpine | Moderate (musl) | Moderate | Manual | Edge, embedded, containers |
| Fedora | Hard (pin kernel) | High | ZFSBootMenu | Desktop (if you must) |
| Arch | Hard (manual) | High | ZFSBootMenu | Hobbyist, homelab |
| macOS | Difficult | Very high | No | Data access only |
| Windows | Experimental | Very high | No | Data access only |