Building a NAS: part 3 - ZFS
In the previous post in this series I covered installing Ubuntu server and encrypting the OS disk. In this post I'm going to go over setting up an encrypted ZFS storage pool and file system for the NAS.
Installing ZFS utils
Unlike many Linux distributions, ZFS is available directly from the Ubuntu
repositories, and can easily be installed with apt
:
sudo apt-get update
sudo apt-get install zfsutils-linux
If everything goes well the zfs
and zpool
commands should be available to
setup and manage a new storage pool:
$ zfs version
zfs-0.8.3-1ubuntu12
zfs-kmod-0.8.3-1ubuntu12
Creating a new pool
All data in ZFS is allocated from a storage pool. The pool is made up of one or more vdevs, in this instance the vdev is backed by a single disk. Datasets such as ZFS file systems or volumes are then created from the storage pool:
Note: there are additional vdev types such as raidz, mirrors, and cache; the OpenZFS docs have more info if you're curious.
A storage pool can be created with the following steps:
-
Identify the disk you want to back the pool with:
lsblk
-
Create a new storage pool using the block device:
zpool create -o feature@encryption=enabled mypool /dev/sdc
Note: features such as encryption can be enabled using the -o
option.
Creating an encrypted ZFS file system
Once a storage pool has been set up it should be online, this can be verified
by running zpool list
:
$ zpool list
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
mypool 3.62T 996K 3.62T - - 0% 0% 1.00x ONLINE -
An encrypted ZFS file system can then be created with the following steps:
-
Create a directory to store the encryption key:
mkdir /root/zfs chmod 700 /root/zfs
-
Generate a new key for the dataset:
openssl rand -out /root/zfs/mydataset 32 chmod 400 /root/zfs/mydataset
-
Create a new dataset using the key:
zfs create -o encryption=on -o keyformat=raw \ -o keylocation=file:///root/zfs/mydataset mypool/mydataset
If everything goes well the new file system should now be mounted:
$ mountpoint /mypool/mydataset/
/mypool/mydataset/ is a mountpoint
$ zfs list
NAME USED AVAIL REFER MOUNTPOINT
mypool 660K 3.51T 96K /mypool
mypool/mydataset 192K 3.51T 192K /mypool/mydataset
Mounting automatically during boot
Unfortunately after rebooting my NAS I found the file system wasn't mounted!
After a bit of investigation it turned out the encryption keys were not loaded
when the zfs-mount.service
unit file is run. To get around this I created a
new unit file to call zfs load-key -a
$ cat /etc/systemd/system/zfs-load-keys.service
[Unit]
Description=Load ZFS encryption keys
DefaultDependencies=no
Before=zfs-mount.service
After=zfs-import.service zfs-load-module.service zfs-import.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/bash -c '/usr/sbin/zfs load-key -a'
[Install]
WantedBy=zfs-mount.service
Finally I enabled the service and restarted to make sure everything mounted correctly:
$ systemctl enable zfs-load-keys.service
Created symlink /etc/systemd/system/zfs-mount.service.wants/zfs-load-keys.service → /etc/systemd/system/zfs-load-keys.service.
$ systemctl reboot
Note: I suspect I could have used ZFS mount generator as an alternative to creating a new ZFS service