Ubuntu 20.04: Install Ubuntu with ZFS and encryption

Ubuntu 20.04 offers installing ZFS as the default filesystem. This has lots of advantages. My favourite is being able to revert the system and home partitions (simultaneously or individually) to a previous state through the boot menu.

One major drawback for me is the lack of an option to encrypt the filesystem during the installation.

You have the option to use LUKS and ext4 but there isn’t an encryption option in the installer for ZFS.

Some people have used LUKS and ZFS in the past, but that solution didn’t quite work for me. The tutorials I saw were using LUKS1 instead of LUKS2 and it also felt that the approach was cumbersome now that ZFS on Linux supports native encryption.

The more you deviate from a standard installation the more complicated it will be to do any troubleshooting if anything breaks in the future. Keep it simple.

The ZFS on Linux version included with the 20.04 installer is 0.8.3.

The installation of Ubuntu 20.04 on ZFS will create two pools: bpool and rpool.

bpool contains the boot partition and rpool all the other mountpoints in several datasets.

In a very security minded world both pools should be encrypted, but I prefer not encrypt the boot partition. Adding that extra layer of security might make a system recovery that much more difficult or impossible.

The default partitioning during the install creates four partitions and two ZFS pools, using all the storage in the installation disk:

/boot/efi 512MiB EFI System Partition (vfat)
SWAP 2GiB Linux Swap Partition (swap)
bpool 2GiB ZFS/Solaris boot partition (zfs)
rpool all remaining space ZFS/Solaris root partition (zfs)

To encrypt the rpool we will need to edit the installation script.

Steps

  • Click the “Try Ubuntu” button.
  • Open a terminal window.
  • Edit /usr/share/ubiquity/zsys-setup
# vim /usr/share/ubiquity/zsys-setup

This script is responsible for setting up ZFS. We can modify the default options for rpool.

  • Edit the rpool section from this:
# Pools
        # rpool
        zpool create -f \
                -o ashift=12 \
                -O compression=lz4 \
                -O acltype=posixacl \
                -O xattr=sa \
                -O relatime=on \
                -O normalization=formD \
                -O mountpoint=/ \
                -O canmount=off \
                -O dnodesize=auto \
                -O sync=disabled \
                -O mountpoint=/ -R "${target}" rpool "${partrpool}"

to this:

# Pools
        # rpool
        echo PASSWORD | zpool create -f \
                -o ashift=12 \
                -O compression=lz4 \
                -O acltype=posixacl \
                -O xattr=sa \
                -O relatime=on \
                -O normalization=formD \
                -O mountpoint=/ \
                -O canmount=off \
                -O dnodesize=auto \
                -O sync=disabled \
                -O recordsize=1M \
                -O encryption=aes-256-gcm \
                -O keylocation=prompt \
                -O keyformat=passphrase \
                -O mountpoint=/ -R "${target}" rpool "${partrpool}"
  • Replace PASSWORD with the encryption password you want to use. You will be prompted to type this at boot time.
  • Save the changes to the file and exit.
  • Launch the installer:
# ubiquity
  • Install Ubuntu as you would.
    In the storage section:
  • Select “Use entire disk”
  • Select ZFS (Experimental)

The system will be installed with the encryption options set on the script and on boot it will prompt you with the password you setup.


Some comments on the options for reference:

-o ashift=12
This is the default setting that means that your disk’s block size is 4,096 bytes (2^12=4,096). Valid values are:

0 for autodetect sector size
9 for 512 bytes
10 for 1,024 bytes
11 for 2,048
12 for 4,096
13 for 8,192
14 for 16,384
15 for 32,768
16 for 65,536

You can output the physical sector size with lsblk -t, although values of 512 might be simulated. You should check the specifications if the drive is SSD.

Alternative ways to retrieve physical sector sizes are:

$ cat /sys/block/sd*/queue/physical_block_size
# hdparm -I /dev/sda | grep Sector

A value of 12 will work just fine, even on 512 sector drives and likely being the reason for Canonical setting up as the default.

If set too low this can have a huge and negative impact on performance.

-O recordsize=1M
Other tutorials suggest creating this entry. According to Oracle’s documentation this parameter is used for databases and I have read that it can also be used for certain types of VMs.

The default value is 128k. You can tune it for your individual use by changing the record size of an existing pool. Any new files created will use the new record size value. You can cp/rm files to force them to be rewritten with the new value.

You can change this value later on with:

# zfs set recordsize=128k rpool

or

# zfs set recordsize=128k rpool/filesystem

-O encryption=aes-256-gcm
AES with key lengths of 128, 192 and 256 bits in CCM and GCM operation modes are supported natively.
0.8.4 comes with a fix that improves performance with AES-GCM and should hopefully be included in an update to Ubuntu soon.

-O keylocation=prompt
Valid options are prompt or file:// </absolute/file/path>

Prompt will ask you to type the password, in this case during boot.
File will point to the location of the decryption key, but on a portable system it would defy its purpose.

-O keyformat=passphrase
Options are raw, hex or passphrase.
When using passphrase the password can be between 8 and 512 bytes in length.


Additional information

Reference sites
Debian ZFS site
Ubuntu ZFS reference
FreeBSD ZFS reference

ZFS on Linux website / Admin documentation
ZFS on Linux manpage
OpenZFS System Administration
OpenZFS FAQ

Oracle ZFS Admin guide (not necessarily in line with ZFS on Linux)
Archlinux ZFS wiki
Alpine Linux with root on ZFS with native encryption wiki

Ars Technica intro to ZFS

Interesting articles on ZFS tuning:
Tuning ZFS recordsize (Oracle blog)
ZFS record size (Joyent blog)
OpenZFS performance tuning wiki