Native ZFS Encryption on Linux: Current Support Status & Secure zfs send Alternatives


2 views

As of ZoL 2.1.0 (released in 2021), native ZFS encryption is fully supported and production-ready. This includes both dataset-level encryption and the critical zfs send -w functionality for encrypted replication streams.

The encryption stack supports:

  • AES-256-GCM (default) and AES-256-CCM
  • PBKDF2 key derivation with 350,000 iterations
  • Both passphrase and key file authentication
# Creating an encrypted dataset
zfs create -o encryption=on -o keyformat=passphrase tank/secure_data

# Sending encrypted stream
zfs snapshot tank/secure_data@backup1
zfs send -w tank/secure_data@backup1 | ssh backup-server "zfs recv pool/backups"

Native encryption adds minimal overhead (typically 5-15%) compared to LUKS solutions because:

  • Encryption happens at the ZFS layer alongside compression
  • No separate block device mapping required

For systems running older ZoL versions without native encryption:

# Option 1: Upgrade to ZoL 2.1+ and migrate data
sudo apt install zfs-2.1
zfs create -o encryption=on tank/new_encrypted
rsync -a /tank/unencrypted/ /tank/new_encrypted/

# Option 2: Temporary workaround with zvols
zfs create -V 10G tank/encrypted_vol
cryptsetup luksFormat /dev/zvol/tank/encrypted_vol
mkfs.ext4 /dev/mapper/encrypted_vol
  • Always use keylocation=file:// for production systems
  • Rotate encryption keys periodically with zfs change-key
  • Combine with ZFS redundancy (raidz/mirror) for data protection

As of 2023, ZFS on Linux (ZoL) fully supports native encryption through the OpenZFS 2.0+ implementation. This capability was introduced in ZoL 0.8.0 and has matured significantly. Unlike LUKS-based solutions, native ZFS encryption provides:

  • Per-dataset encryption granularity
  • Transparent encryption during zfs send/receive operations
  • Key rotation without re-encrypting data
  • Inheritable encryption properties

For users still on older ZoL versions without encryption support, the traditional workaround was:

# Suboptimal zVol approach (avoid if possible)
zfs create -V 10G pool/encrypted_vol
cryptsetup luksFormat /dev/zvol/pool/encrypted_vol
mkfs.ext4 /dev/mapper/encrypted_backup

The native ZFS encryption approach is superior because:

  1. Maintains ZFS features (compression, checksums, snapshots)
  2. Allows encrypted raw sends: zfs send -w pool/encrypted@snap
  3. Supports multiple encryption algorithms (aes-256-gcm preferred)

Creating an encrypted dataset for secure backups:

# Create encrypted dataset with passphrase
zfs create -o encryption=aes-256-gcm -o keyformat=passphrase \
    -o keylocation=prompt pool/secure_backups

# Verify encryption status
zfs get encryption,keylocation,keyformat pool/secure_backups

# Send encrypted snapshot to untrusted backup server
zfs snapshot pool/secure_backups@initial
zfs send -w pool/secure_backups@initial | ssh backup-server "zfs recv backup_pool/restored"

For production environments, consider these robust approaches:

# Using keyfiles instead of passphrases
dd if=/dev/urandom of=/etc/zfs/keys/backup.key bs=32 count=1
chmod 400 /etc/zfs/keys/backup.key

zfs create -o encryption=aes-256-gcm -o keyformat=raw \
    -o keylocation=file:///etc/zfs/keys/backup.key pool/prod_data

For automated systems, implement PKCS#11 token integration via:

zfs set keylocation=pkcs11:token=backup_token;object=zfs_key pool/prod_data

Common issues and solutions:

  • Error: "cannot receive encrypted filesystem unencrypted" - Add -o encryption=off to zfs receive for decrypted targets
  • Permission denied on keyfiles - Ensure zfs-import-cache.service has access to /etc/zfs/keys
  • Performance overhead - Use aes-gcm instead of cbc modes for modern CPUs