ZFS with LUKS – Workstation Power At Home – Part 11

This is a quick follow-up post to the previous one in which I’ve written about how straight forward it is to use ZFS to combine several physical SSDs or disk drives to use the combined capacity for a file system. The one thing I left out in the description was how to encrypt the setup. While ZFS encryption is said to have a good performance starting with version 0.8.4, Ubuntu 20.04 I use at the time of writing is still using 0.8.3. The advice of ‘the Internet’ is thus to use LUKS as an encryption layer below ZFS.

So here’s the procedure how to configure ZFS to use two drives in combination with LUKS. I’ve marked the difference to the procedure in the previous post in blue:

  • Create a partition on each drive to use with ZFS
  • Initialize each partition to be used with LUKS encryption (luksFormat)
  • Create the mapping from the partition to the LUKS encrypted virtual partition (luksOpen)
  • Create the the ZFS pool. Instead of referencing the raw partitions, reference the LUKS encrypted partitions
  • Create the file system(s)

In short, the procedure is the same as before from a ZFS point of view with the only difference being that the encrypted LUKS partitions are used for the ZFS pool instead of the raw partitions. In practice, the commands to do the above look as follows:

# Use fdisk to create /dev/sdb1 in /dev/sdb
# Use fdisk to create /dev/sdc1 in /dev/sdc

# The LUKS setup for the first drive
sudo dd if=/dev/urandom bs=1M count=8 of=/dev/sdb1
sudo cryptsetup luksFormat -c aes-xts-plain64 -s 512 \
     -h sha512 -y /dev/sdb1
sudo cryptsetup luksOpen --allow-discards /dev/sdb1 lukssdb1

# Run the same commands for the second drive to get from
# /dev/sdc1 to lukssdc1

# Now create the ZFS pool
sudo zpool create -o ashift=13 -f zfs-pool-1 /dev/mapper/lukssdb1 /dev/mapper/lukssdc1

# And now create a ZFS file system (= ZFS dataset)
sudo zfs create zfs-pool-1/data
sudo chown -R martin:martin /zfs-pool-1/data

While ZFS auto-mounts a configuration on boot if the partitions are available, this is not possible with a LUKS setup. Instead this has and must be done manually by typing in the password for the encrypted partitions, as storing the password on the boot partition would make encryption meaningless. And here’s how to do that with a little bash script after booting and logging in:

echo 'Mounting and starting ZFS'
sudo cryptsetup luksOpen --allow-discards /dev/sdb1 lukssdb1
sudo cryptsetup luksOpen --allow-discards /dev/sdc1 lukssdc1
sudo zpool import -d /dev/mapper/lukssdb1 zfs-pool-1

And that’s already it.