| pick your distro, get ZFS on root
kldload — your platform, your way, free
Source

Secure Boot and Encryption

kldload supports Secure Boot via MOK (Machine Owner Key) enrollment and ZFS native encryption (AES-256-GCM). Works on all supported distros.

This is the hands-on guide. For the conceptual explanation of why the boot chain matters, what attack scenarios look like, and how the three verification layers work together, read Secure Boot & the Boot Chain. This page is about doing it — configuring encryption, signing modules, enrolling keys, and recovering when things go wrong.


ZFS encryption

Enable during install

Set KLDLOAD_ZFS_ENCRYPT=1 in the answers file or select encryption in the web UI. The installer creates the pool with:

  • encryption=aes-256-gcm
  • keyformat=passphrase
  • keylocation=prompt

You’ll enter a passphrase at every boot.

Verify encryption status

zfs get encryption,keystatus rpool
NAME   PROPERTY     VALUE
rpool  encryption   aes-256-gcm
rpool  keystatus    available

Encrypt individual datasets (on an unencrypted pool)

You don’t have to encrypt the whole pool. Encrypt only sensitive data:

# Create an encrypted dataset
zfs create -o encryption=aes-256-gcm \
           -o keyformat=passphrase \
           rpool/srv/secrets
# Enter passphrase when prompted

# Create with a key file instead of passphrase
dd if=/dev/urandom of=/root/.zfs-key bs=32 count=1
chmod 600 /root/.zfs-key
zfs create -o encryption=aes-256-gcm \
           -o keyformat=raw \
           -o keylocation=file:///root/.zfs-key \
           rpool/srv/automated-secrets

Per-dataset encryption is the feature that changes how you think about data protection.

LUKS encrypts the whole disk with one key. Unlock it at boot and everything is exposed — every file, every user, every secret. All or nothing. ZFS encryption is per-dataset. /home/alice has Alice's key. /srv/secrets has a hardware token. /srv/customer-data has its own passphrase. Lock one dataset and the rest stay accessible. A compromise of one key doesn't expose everything else.

For the quantum bridge contract: every customer gets their own encrypted dataset with their own key. Offboard a customer? zfs unload-key — their data is ciphertext on disk. Root can't read it. The admin can't read it. The backup server storing the replica can't read it. The key never left the customer's hands.

Lock and unlock

# Lock (unmount and unload key)
zfs unmount rpool/srv/secrets
zfs unload-key rpool/srv/secrets

# Unlock
zfs load-key rpool/srv/secrets     # prompts for passphrase
zfs mount rpool/srv/secrets

Change passphrase

zfs change-key rpool
# Enter current passphrase, then new passphrase

Secure Boot with MOK

kldload ISOs boot with Secure Boot via the shim bootloader (same chain as Fedora/Ubuntu). After install, DKMS kernel modules (ZFS, NVIDIA) need signing.

How it works

  1. kldload installs the shim EFI binary (BOOTX64.EFI) which is signed by Microsoft’s UEFI CA
  2. Shim loads GRUB2 or ZFSBootMenu
  3. The kernel is signed by the distro vendor (CentOS/Debian)
  4. Third-party kernel modules (ZFS, NVIDIA) are signed with a MOK key that kldload generates during install

Check Secure Boot status

mokutil --sb-state
# SecureBoot enabled/disabled

# List enrolled MOK keys
mokutil --list-enrolled

Build-time vs runtime signing — the key distinction.

kldload compiles and signs modules at image build time, not on the target. Each build generates a unique MOK keypair. The signed modules ship in the image alongside the kernel — a matched pair. No compiler on the target. No DKMS in the boot path. If the machine boots, the modules are loaded and verified.

After deployment, DKMS is still on the machine for kernel updates. When you run kupgrade, it rebuilds the module, re-signs it with the MOK key, and verifies it loaded. If signing fails, kupgrade warns you and the pre-upgrade boot environment is one reboot away. The build-time signing covers the initial deploy. The MOK key on the target covers post-deploy kernel updates. Both are automatic.

The MOK key

kldload stores the MOK key pair at:

/var/lib/kldload/mok/MOK.priv    # private key (600 permissions)
/var/lib/kldload/mok/MOK.der     # public certificate (enrolled in firmware)

Sign a kernel module manually

If you install a new DKMS module (or the automatic signing fails):

# Find the module
modinfo -n zfs
# /lib/modules/5.14.0-xxx/extra/zfs.ko.xz

# Sign it
/usr/src/kernels/$(uname -r)/scripts/sign-file sha256 \
  /var/lib/kldload/mok/MOK.priv \
  /var/lib/kldload/mok/MOK.der \
  /lib/modules/$(uname -r)/extra/zfs.ko.xz

# Verify the signature
modinfo zfs | grep signer

Enroll a new MOK key

If you generated a new key and need to enroll it in the firmware:

# Stage the key for enrollment
mokutil --import /var/lib/kldload/mok/MOK.der
# Enter a one-time password

# Reboot — the shim MOK manager will prompt you to enroll the key
reboot

At the blue MOK Manager screen: 1. Select “Enroll MOK” 2. Select “Continue” 3. Enter the one-time password you set 4. Select “Reboot”

DKMS auto-signing

The honest truth about DKMS + Secure Boot

DKMS modules on kernel upgrades are historically fragile on Linux. Auto-signing can fail silently — the kernel upgrades, DKMS rebuilds the module, but the signing step fails and you don’t know until the module won’t load on reboot.

kldload mitigates this in three ways:

  • Boot environmentsksnap before every kupgrade. If the kernel upgrade breaks ZFS module loading, reboot into the previous boot environment. 30 seconds to recover.
  • DKMS sign-tool — kldload installs a signing script at /var/lib/dkms/mok-signing.sh that DKMS calls automatically. If it fails, kupgrade warns you before reboot.
  • Verificationkupgrade runs dkms status after every kernel upgrade and checks that the ZFS module is built and signed for the new kernel. If not, it blocks the reboot and tells you.
DKMS is fragile. Boot environments make it survivable. That’s the real answer — not pretending auto-signing is bulletproof, but making sure you can always roll back when it isn’t.
# Check DKMS module status
dkms status

# Rebuild and sign for current kernel
dkms autoinstall

# Verify the module is signed
modinfo -F signer zfs
# Should show: kldload Secure Boot MOK

# If signing failed — roll back
kbe activate before-upgrade && reboot

Full disk encryption + Secure Boot together

This is the most secure configuration — encrypted data at rest with verified boot chain:

  1. Install with KLDLOAD_ZFS_ENCRYPT=1 and Secure Boot enabled in firmware
  2. kldload generates MOK key, creates encrypted pool, signs ZFS module
  3. At boot: firmware verifies shim → shim verifies GRUB → GRUB loads kernel → ZFS prompts for passphrase

Automating unlock with Clevis (TPM2)

To avoid typing the passphrase at every boot, bind the encryption key to the TPM:

# CentOS/RHEL
dnf install -y clevis clevis-luks clevis-tpm2

# Debian
apt install -y clevis clevis-tpm2

Note: ZFS native encryption doesn’t integrate directly with Clevis the way LUKS does. The kldload firstboot service stages the passphrase at /etc/kldload/zfs-passphrase for potential Clevis sealing. This is an area of active development.


The three layers working together:

Layer 1 — Verified boot:     Firmware → shim → kernel → signed modules
                              (tampered binary = refused to load)

Layer 2 — Encrypted storage:  AES-256-GCM per dataset, key never on disk
                              (stolen disk = ciphertext)

Layer 3 — Checksummed I/O:    Every block verified on every read
                              (bit rot / tampering = detected + repaired)

Combined: the system boots verified, stores data encrypted, and
verifies every read. An attacker needs to compromise the firmware,
steal the encryption key, AND bypass block checksums. Each layer
is independent. Breaking one doesn't break the others.

No single security tool on ext4 gives you all three. You'd need Secure Boot + LUKS + AIDE/Tripwire, each configured separately, each with its own failure modes. On ZFS, layers 2 and 3 are properties of the filesystem. Layer 1 is the boot chain kldload configures for you.

Troubleshooting

# Module won't load — signature issue
dmesg | grep -i "module verification failed"
# Fix: re-sign the module (see above)

# MOK key not enrolled
mokutil --test-key /var/lib/kldload/mok/MOK.der
# "is not enrolled" → need to run mokutil --import and reboot

# Encrypted pool won't import
zpool import -a    # prompts for passphrase
zfs load-key -a    # load all keys
zfs mount -a       # mount everything

# Forgot the passphrase
# No recovery possible with ZFS native encryption.
# If you have a backup (zfs send), restore from that.
# This is why boot environment snapshots matter — they're part of the encrypted pool.