Create a keyfile encrypted ZFS volume in Ubuntu 22.04


For the first time in nearly a decade I assembled a new desktop workstation to support a growing interest in learning about Artificial Intelligence and Machine Learning from "first principles". This is a departure for me, having been a creature of laptops for many years. To make things more interesting a ZFS pool will be used in place of the usual 'RAID' array for my large storage disks.

This post walks through how to create an encrypted ZFS pool / dataset (still adjusting to the terminology) which is auto-mounted on system boot

References

Volume Setup

  1. First, identify your drives using fdisk -l
    • In my case the 2 drives which I wanted to add to my zfs were /dev/sda and /dev/sdb
  2. Next, create an encryption file
    • Place it in a directory that will be available on boot
    • Ensure the directory and file permissions are setup to prevent other users from viewing or altering your secret
    • For example, it could be stored in /cfg/zfs.enc (or anywhere that makes sense for your system setup
    • I ensured that the permissions were set to 0400
  3. Then, Identify where you want the ZFS dataset to be mounted
    • In my case I elected to mount it under /mnt/bigdisk
  4. Now you can use this command to setup a zfs mirror ( be sure to adjust it based on your needs! You may not want a 'mirror'...)
sudo zpool create -o encryption=on -o encryption=aes-256-gcm -o keyformat=raw -o keylocation=file:///cfg/zfs.enc -m /mnt/bigdisk bigdisk mirror /dev/sda /dev/sdb

Auto-unlock on Boot

(Updated 2024): Edit the systemd configuration for zfs-mount to ensure that the zfs volume will unlock on boot and persist the configuration across system updates/upgrades. My 'original' version below just performs a raw-edit of the systemd service... and I found that I regularly had to go back in and 're-edit' the service configuration, which is non-optimal...

  • sudo systemd edit zfs-mount
  • Add this line to the configuration:
    • ExecStart=/sbin/zfs mount -a -l

At this point the zfs volume should auto-unlock on boot using your encryption keyfile.


(original) Now the only configuration remains is to setup the system so it unlocks the volume on boot:

  • vim /usr/lib/systemd/zfs-mount.service
    • This is the file which controls the zfs mount configuration
  • Add the -l parameter to the zfs mount command. On my system the final configuration looked like this:
[Unit]
Description=Mount ZFS filesystems
Documentation=man:zfs(8)
DefaultDependencies=no
After=systemd-udev-settle.service
After=zfs-import.target
After=systemd-remount-fs.service
After=zfs-load-module.service
Before=local-fs.target
ConditionPathIsDirectory=/sys/module/zfs

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/sbin/zfs mount -a -l

[Install]
WantedBy=zfs.target

At this point in my testing the ZFS volume would unlock on boot/reboot! This compliments the ZFS encryption which was setup at install time on the NVMe drive.

Final Words

ZFS is supposed to be the best thing since sliced bread. With this workstation configuration I'll put it to the test!

As an aside / reference to my future self, this is the system configuration & specs:

  • RTX 4090 FE
  • Ryzen 9 7950X3D
  • Gigabyte X670 AORUS Elite AX (rev. 1.0)
    • Firmware F9a
  • Cosair Vengeance 192GB DDR5 (CMK192GX5M4B5200C38)
  • Samsung 990 Pro 2TB NVMe
  • 2x WD Red Pro WD181KFGX 18TB drives
  • Seasonic PRIME TX-1600 (SSR-1600TR)
  • Fractal Torrent case