| your Linux re-packer
kldload — your platform, your way, anywhere, free
Source
← Back to ZFS Overview

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.

Off the cuff: The OpenZFS docs tell you that ZFS runs on Linux. They don't tell you that a Fedora kernel update on a Friday afternoon can leave your root pool unmountable on Monday morning because DKMS failed silently during the upgrade. This page is the field guide — what actually happens in production, not what the README says should happen.

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:

FreeBSD (2007)
Pawel Jakub Dawidek ported ZFS to FreeBSD's kernel and it was merged into the FreeBSD source tree. This is the oldest and most mature non-Solaris port. ZFS became FreeBSD's default root filesystem.
ZFS on Linux (2010)
Brian Behlendorf at Lawrence Livermore National Laboratory led the Linux port. Because the CDDL and GPL are considered incompatible, ZFS on Linux was built as an out-of-tree kernel module. This is the engineering constraint that defines every Linux ZFS decision.
OpenZFS (2013)
The OpenZFS project unified the illumos, FreeBSD, and Linux codebases. As of OpenZFS 2.0 (2020), FreeBSD and Linux share the same source tree, same test suite, and same feature set. Differences are now in platform integration, not ZFS itself.

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.

Off the cuff: The CDDL/GPL license conflict is the single most consequential technical decision in ZFS history. If ZFS had been GPLv2 (like ext4 or XFS), it would be in the mainline Linux kernel today, and none of the DKMS/kABI complexity below would exist. But it wasn't, and here we are. Whether the licenses are actually incompatible is a legal question that lawyers disagree on. Canonical says they're compatible enough to ship together. Red Hat says they're not. The FSF says they're not. Linus Torvalds says he doesn't care. The practical result is that every Linux distro has to make its own call, and most err on the side of caution.

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
Off the cuff: If you want ZFS and you don't specifically need Linux, use FreeBSD. This isn't tribalism — it's engineering. FreeBSD's ZFS integration is in-tree, tested against every kernel commit, and has never been broken by a kernel update in its 15+ year history. Everything below this point exists because sometimes you need Linux, and that's where things get interesting.

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:

ARC integration
FreeBSD's VM subsystem cooperates with ARC. On Linux, ARC and the page cache fight over memory, with the kernel's OOM killer sometimes evicting ARC aggressively. FreeBSD's unified memory management means ARC grows and shrinks dynamically without conflict.
Boot environments
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.
NFS & ACLs
NFSv4 ACLs work natively with ZFS datasets. zfs set sharenfs=on tank/data and it just works. Linux requires additional middleware (nfs-kernel-server, exportfs) and POSIX ACL translation.
Jails + ZFS
FreeBSD jails (lightweight containers) integrate directly with ZFS. Each jail gets its own dataset, snapshots, and quotas. zfs jail delegates a dataset into a jail with full admin capabilities. No Docker storage driver indirection.
bhyve + ZFS
FreeBSD's native hypervisor, bhyve, stores VM disk images as ZFS volumes (zvols). Snapshots, clones, and replication of VMs are native ZFS operations. Provisioning a new VM is a zfs clone — instant, no disk copy.
Kernel updates
ZFS is compiled with the kernel. There is no separate module to break. freebsd-update or pkg upgrade updates everything atomically. In 15+ years, a kernel update has never broken ZFS on FreeBSD.
Secure Boot
FreeBSD does not have the Secure Boot / module signing problem because ZFS is part of the kernel binary. There is no out-of-tree module to sign. No MOK enrollment, no kext restrictions, no ceremony.
# 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.
Off the cuff: The FreeBSD ZFS experience makes the Linux ZFS experience feel like a hack. Because it is. FreeBSD treats ZFS as infrastructure. Linux treats ZFS as a guest that might get evicted. If you're building a NAS, a SAN, or any pure storage appliance, FreeBSD is the right answer unless you have a specific Linux requirement. TrueNAS CORE is built on FreeBSD for exactly this reason. (TrueNAS SCALE moved to Linux for Docker/Kubernetes support — proof that sometimes you need Linux, even when FreeBSD is technically better for storage.)

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)
Off the cuff: DKMS is not the problem. DKMS is the solution to the problem, and the problem is that the Linux kernel has no stable internal ABI. Every kernel release can (and does) change function signatures, struct layouts, and entire subsystems without warning. Linus Torvalds has explicitly stated that out-of-tree modules are not his concern. ZFS maintains compatibility shims for hundreds of kernel API changes across dozens of kernel versions. It's genuinely impressive engineering. But it's also a ticking clock — every new kernel release is a roll of the dice until the OpenZFS team patches the shims.

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:

1. Detect the change
Usually discovered when DKMS builds start failing on Fedora or Arch (the canaries). Sometimes caught in OpenZFS CI before release.
2. Write a compat shim
An autoconf check detects the kernel version, and a #ifdef block provides both the old and new API call. ZFS has hundreds of these.
3. Release a point update
The fix ships in the next OpenZFS point release (e.g., 2.2.7). Users on affected kernels must wait for this release or manually patch.
4. Distro repos update
The ZFS on Linux repo, archzfs, and distro package maintainers rebuild packages. This can take hours to weeks depending on the distro.

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.
Off the cuff: If you're running ZFS on Enterprise Linux and you're using 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
Off the cuff: Ubuntu's ZFS integration is genuinely excellent. The legal argument is a gray area, and the purists will never stop arguing about it, but the engineering result is the best ZFS experience on any Linux distribution. If you must run ZFS on Linux and you don't have an Enterprise Linux requirement, Ubuntu is the path of least resistance. The one catch: Ubuntu's ZFS module version sometimes lags behind the latest OpenZFS release by a few months. If you need bleeding-edge ZFS features (block cloning, RAIDZ expansion), you might need to wait for Canonical to update.

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.

Off the cuff: Debian + ZFS is the workhorse of the homelab world. It's what Proxmox is built on (Proxmox ships its own prebuilt ZFS module, bypassing DKMS). If you're running bare Debian with ZFS, the single most important habit is checking 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
Off the cuff: Running ZFS on Fedora in production is living dangerously. It works, and when it works it's great — you get the latest kernel features alongside ZFS. But "latest" and "stable" are different words, and Fedora chose the first one. If you run ZFS on Fedora, pin your kernel and only upgrade when the OpenZFS release notes explicitly confirm compatibility. Or better yet, use the kldload Fedora profile, which handles the kernel pinning and DKMS compilation at install time. I've personally seen Fedora ZFS systems break three times in one year from kernel updates. Each time, the fix was "wait for OpenZFS to release a patch." Not acceptable for production.

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.

Off the cuff: RHEL/Rocky with ZFS kmod is the closest Linux gets to FreeBSD's ZFS experience. Install once, forget about it for years. The kernel is boring, the ABI is stable, and the ZFS module just works. If you're building production servers and the choice is between "latest kernel features" (Fedora) and "ZFS that never breaks" (Rocky), choose Rocky every time. You can always backport specific kernel features. You can't un-break an unmountable root pool.

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:

archzfs repo
Third-party repository that provides precompiled ZFS packages pinned to specific kernel versions. The maintainer compiles new packages when kernel+ZFS compatibility is confirmed. Recommended. Add the repo and install zfs-linux (prebuilt) or zfs-linux-git (latest git). Kernel updates are held until a matching ZFS package exists.
AUR (zfs-dkms)
DKMS package from the AUR. Compiles from source on every kernel update. Higher risk: if the kernel is too new for the current ZFS release, the build fails silently and your next reboot has no ZFS. Requires linux-headers and a working compiler toolchain.
linux-lts kernel
Arch ships a 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
Off the cuff: Arch + ZFS on root is for people who enjoy risk. The archzfs repo makes it workable, but you're always one 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:

Error messages
musl's 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.
Mount handling
musl's getmntent() has slightly different parsing behavior. In rare cases, zfs mount -a may behave differently than on glibc systems, especially with complex mountpoint hierarchies.
Threading
musl's thread cancellation semantics differ from glibc. Under heavy concurrent ZFS operations (many parallel zfs send streams), you may see different behavior than on glibc-based systems.
Python tools
Some ZFS management tools (like sanoid/syncoid) use Python with ctypes bindings to libzfs. musl's dynamic linking behavior can cause import failures. Test thoroughly.
# 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
Off the cuff: Proxmox is the easiest way to get ZFS on a Linux hypervisor. The installer does everything, the web UI manages everything, and kernel updates don't break ZFS. If you're building a homelab or small-business virtualization cluster, Proxmox gives you the ZFS experience that every other Linux distro makes you work for. The trade-off is that you're locked into Proxmox's kernel and update cycle, but for a hypervisor, that's usually exactly what you want.

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:

Read-only import
Always works, regardless of feature flags. Any OpenZFS version can read-only import a pool with unsupported features. This is your escape hatch for data recovery.
Read-write import
Only works if the importing system supports all active feature flags on the pool. If the pool has draid enabled but the target system runs OpenZFS 1.x (which doesn't know draid), read-write import fails.
Compatibility property
OpenZFS 2.1+ lets you set 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.
Endianness
ZFS stores metadata in a self-describing format with endianness markers. You can move a pool from a big-endian SPARC system to a little-endian x86 system without conversion. This is a design feature from the Solaris days, and it still works.

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
Off the cuff: If you're building a portable pool that might move between FreeBSD and Linux, use the 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

FreeBSD
No issue. ZFS is part of the kernel binary. Secure Boot signs the kernel as a whole. No separate module signing needed.
Ubuntu
Canonical signs the ZFS module with their key. Works with Secure Boot out of the box. No MOK enrollment needed.
Proxmox
Proxmox signs the ZFS module with their key (as of PVE 8). Works with Secure Boot out of the box.
RHEL/Rocky (kmod)
The ZFS kmod package from zfsonlinux.org is not signed by Red Hat. You need MOK signing, or disable Secure Boot.
Debian / Fedora / Arch
DKMS modules are unsigned. Secure Boot must be disabled, or you must set up MOK signing and configure DKMS to auto-sign after each build.
# 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.
Off the cuff: MOK signing works, but it's a pain to maintain manually. The DKMS 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.

Works on any Linux host with ZFS. No special container config needed.

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.

Same ZFS storage driver, different container runtime.

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.

Incus (the successor to LXD) has first-class ZFS support built in.

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.

Cloud-native ZFS: provision storage with kubectl, backed by ZFS pools.

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.

For best performance: virtio-scsi + writeback cache + ZFS in guest.

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.

Containers share the kernel. ZFS is kernel code. Do the math.
# 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
Off the cuff: The Kubernetes ZFS CSI driver is underrated. Most people use local-path or hostPath for local storage in k8s, which gives you none of ZFS's benefits. The CSI driver gives you per-PVC snapshots, compression, and quotas — all managed through standard Kubernetes APIs. If you're running k8s on bare metal with ZFS, there's no reason not to use it.

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:

1. Compile ZFS
Build the ZFS kernel module (zfs.ko, spl.ko) from source against the exact kernel that ships in the ISO. The kernel version is known and fixed — no DKMS guessing.
2. Sign the module
Generate a MOK keypair and sign zfs.ko with it. The signed module loads on Secure Boot systems without disabling security.
3. Embed in initramfs
Use dracut to build an initramfs that includes the signed ZFS module. When the ISO boots, ZFS is available immediately — no internet, no compilation, no delay.
4. Per-distro install
When installing to the target disk, the installer uses the appropriate method for each distro: kmod RPMs for EL9/Fedora (from embedded darksite), DKMS for Debian/Ubuntu (compiled during install), archzfs for Arch (from internet).
5. Boot environment
Configure ZFSBootMenu or dracut-based ZFS boot on the target. The installed system boots from ZFS root with proper initramfs integration and module loading.
6. Darksite packaging
All ZFS packages for all supported distros (RPM kmod, Debian DKMS source + headers, Ubuntu prebuilt module) are baked into the ISO. Installs are fully offline except Arch and Alpine (rolling releases, no frozen package set).

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.
Off the cuff: The entire reason kldload exists is this page. Every platform has different ZFS integration requirements, different kernel module lifecycle management, different failure modes. Asking a sysadmin to navigate DKMS compilation, MOK signing, dracut configuration, and ZFSBootMenu setup for each distro is insane. kldload does it once, correctly, and bakes the result into an ISO. You boot. You pick your distro. You get ZFS. That's the promise. And looking at the matrix above — FreeBSD native, Ubuntu prebuilt, RHEL kmod, Debian DKMS, Fedora DKMS-with-prayer, Arch DKMS-with-more-prayer, Alpine DKMS-with-musl — you can see why a unified installer that handles all of this is worth building.

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 build failed after kernel update
All DKMS distros. Boot the previous kernel from GRUB (Advanced Options). Check 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.
modprobe: FATAL: Module zfs not found
Any Linux distro. The module isn't installed for your running kernel. Check 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 hangs or fails after OS migration
Cross-platform. Usually a feature flag issue. Try 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 pool not mounting at boot (systemd)
All systemd distros. Ensure 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 pool not mounting at boot (OpenRC)
Alpine, Gentoo. Ensure zfs-import and zfs-mount are in the boot runlevel: rc-update add zfs-import boot; rc-update add zfs-mount boot.
Secure Boot: module signature verification failed
RHEL, Debian, Fedora. Either disable Secure Boot in BIOS, or set up MOK signing (see above). On Ubuntu and Proxmox, the module is already signed — if you see this error, you've installed zfs-dkms instead of the prebuilt module.
ARC consuming too much memory (OOM kills)
Linux only. Linux's memory pressure handling fights with ARC. Set options zfs zfs_arc_max=8589934592 in /etc/modprobe.d/zfs.conf (8GB example). FreeBSD handles this automatically through VM integration.
Alpine: ZFS error messages are garbled
Alpine only. musl libc's 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.

Best for: NAS, SAN, backup targets, media servers

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.

Best for: databases, app servers, regulated environments

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.

Best for: laptops, dev machines, personal servers

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.

Best for: VM hosts, homelab hypervisors, Proxmox clusters

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.

Best for: container hosts, CI runners, Kubernetes nodes

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.

Best for: IoT, edge compute, minimal appliances

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.

Best for: homelabs, learning environments, people who enjoy debugging
There is no universal best platform for ZFS. There is only the best platform for your workload, your team's skills, and your maintenance budget. FreeBSD is the purest ZFS experience. Ubuntu is the easiest Linux path. RHEL/Rocky is the most stable Linux path. Proxmox is the best for virtualization. Fedora and Arch are for people who like living on the edge. kldload gives you the choice — one ISO, nine distros, ZFS on all of them.

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
Off the cuff: Look at the "Maintenance Burden" column. That's the real cost of ZFS on each platform. FreeBSD, Ubuntu, and Proxmox are zero because the module ships with the kernel — you never think about it. RHEL/Rocky is near-zero because kABI guarantees the module works for years. Everything else requires active management. If you're choosing a platform for production, optimize for low maintenance burden. You'll thank yourself in three years when that server is still running without a single ZFS-related incident because you chose Rocky instead of Fedora.