Skip to content

ZFS Encryption

Native ZFS dataset-level encryption on pve1-media. The pool itself (zpool0) is not encrypted — only specific datasets and their children are. This allows the system to boot fully while keeping sensitive data locked.


Encrypted Datasets

zpool0/family

All child datasets inherit encryption.

Unlock policy: Manually unlocked at boot over SSH. Services that depend on family data are not started until after the unlock — they must be brought up manually after the dataset is mounted.

Sensitivity: Family data — photos, documents, backups, app data.

zpool0/vault

All child datasets inherit encryption.

Unlock policy: Kept locked at all times. Unlocked on demand only when a file needs to be added or retrieved, then locked again immediately after.

Sensitivity: High — ID documents, legal, finances, personal archives, keys.


zfs-util Script

/usr/local/bin/zfs-util on pve1-media wraps the unlock/lock workflow into a single command.

zfs-util <unlock|lock> <dataset>

Examples:

zfs-util unlock zpool0/family
zfs-util lock zpool0/vault

The script handles key loading, mounting all children in order on unlock, and unmounting in reverse order before unloading the key on lock.


Unlock Workflow

Boot sequence (family)

  1. System boots — zpool0 imports, encrypted datasets remain locked.
  2. SSH into pve1-media.
  3. zfs-util unlock zpool0/family
  4. Start dependent services (LXC containers, etc.) that bind-mount from zpool0/family.

On-demand access (vault)

zfs-util unlock zpool0/vault
# ... access files ...
zfs-util lock zpool0/vault

Manual fallback (if zfs-util unavailable)

# Unlock
zfs load-key <dataset>
zfs list -H -t filesystem -o name -r <dataset> | xargs -n1 zfs mount

# Lock
zfs list -H -t filesystem -o name -r <dataset> | tac | xargs -n1 zfs unmount
zfs unload-key <dataset>

Notes

  • zpool0/games, zpool0/media, zpool0/pve, and zpool0/pve-backup are not encrypted — available immediately at boot without intervention.
  • Services on pve1-media that depend on encrypted data will fail to start on their own after a reboot until the dataset is manually unlocked.