Also available to us is ZFS compression. Let’s create a test pool for testing. We’ll turn a few options on and off so you see the syntax:
|
1 2 |
# zfs create -o mountpoint=/compressfs -o dedup=off \ > -o compression=on datapool/compressfs |
Verify that the dataset was created with all appropriate options:
|
1 2 3 4 5 6 |
# zfs get mountpoint,dedup,compression,compressratio datapool/compressfs NAME PROPERTY VALUE SOURCE datapool/compressfs mountpoint /compressfs local datapool/compressfs dedup off local datapool/compressfs compression on local datapool/compressfs compressratio 1.00x - |
Compression ratio is 1.00x, as you’d expect for an empty filesystem. Copy some stuff to it:
|
1 |
# cp -Rp /usr/bin /usr/sbin /compressfs |
Then check the compressratio variable within the dataset properties:
|
1 2 3 |
# zfs get compressratio datapool/compressfs NAME PROPERTY VALUE SOURCE datapool/compressfs compressratio 1.78x - |
So – compression has given us some benefit. It’d be worth weighing up compression/dedup/encryption of ZFS filesystems against the system resources which they consume. Nowadays I’d be pushing FOR turning all this stuff on – servers are cheap and can work hard. Put them to use.
Encryption
Filesystem encryption is another easy-to-implement feature of ZFS. ZFS root pools and other OS components (such as the /var filesystem) cannot be encrypted.
To start, I’ll create a new encrypted dataset. You will be prompted for a passphrase to use when encrypting/decrypting the filesystem. Needless to say – do not forget this passphrase! Create the dataset with the encryption=on option:
|
1 2 3 |
# zfs create -o encryption=on datapool/encryptfs Enter passphrase for 'datapool/encryptfs': Enter again: |
Verify that the operation has succeeded and that the encrypted dataset has been created:
|
1 2 3 4 5 6 |
# zfs list datapool/encryptfs NAME USED AVAIL REFER MOUNTPOINT datapool/encryptfs 33K 19.4G 33K /datapool/encryptfs # zfs get encryption datapool/encryptfs NAME PROPERTY VALUE SOURCE datapool/encryptfs encryption on local |
Encrypted ZFS datasets, when created with encryption=on and no other options, use aes-128-ccm as the default encryption algorithm.
You will see that by default, ZFS uses passphrase,prompt as the value for the keysource property:
|
1 2 3 |
# zfs get keysource datapool/encryptfs NAME PROPERTY VALUE SOURCE datapool/encryptfs keysource passphrase,prompt local |
In this configuration, the ZFS filesystem will not be automatically mounted at boot – observe. After a reboot the output of zfs mount does not contain an entry for datapool/encryptfs:
|
1 2 |
# zfs mount | grep -c encryptfs 0 |
So – any encrypted datasets, using passphrase,prompt as the value for the keysource property, require manual mount with zfs mount:
|
1 2 3 4 |
# zfs mount datapool/encryptfs Enter passphrase for 'datapool/encryptfs': # zfs mount | grep -c encryptfs 1 |
The passphrase can be placed in a file, so that it is automatically mounted on boot. Note – this is not secure nor is it recommended. It is best to use keys, and we will configure this shortly. For now, place the passphrase in a read-only file in root’s home directory:
|
1 2 |
# echo 'S3cur3phr@s3' > /root/.encryptfs-passphrase # chmod 400 /root/.encryptfs-passphrase |
Set the keysource property to include the passphrase file:///path/to/key value as below:
|
1 |
# zfs set keysource=passphrase,file:///root/.encryptfs-passphrase datapool/encryptfs |
Now, unmount the filesystem and unload the cached key (otherwise the filesystem will be remounted using the cached key and nothing will change):
|
1 2 |
# zfs unmount datapool/encryptfs # zfs key -u datapool/encryptfs |
If the filesystem is mounted now, we are not prompted for a passphrase:
|
1 2 3 |
# zfs mount datapool/encryptfs # zfs mount | grep -c encryptfs 1 |
A reboot confirms this:
|
1 2 3 |
# shutdown -y -g 0 -i 6 # zfs mount | grep -c encrypt 1 |
OK – this is all well and good, but storing the passphrase in a file is far from being best practice. A more secure method is to use pktool to create a key, then change the dataset to use this key (or indeed create the ZFS dataset in the first place using this key). Whilst this is better - it’s still only as secure as the security of the key file location. Any compromise of the key file leads to a potential compromise of the ZFS dataset. However, we’re not storing the passphrase clear-text in a file somewhere, which is positive in my book.
The conversion from using a passphrase based key to the pktool generated key is completed as follows. First, generate a key, and store in as secure a location as possible:
|
1 |
# pktool genkey keystore=file outkey=/root/.encryptfs.key keytype=aes keylen=256 |
Load the existing wrapping key for the dataset, by either mounting the dataset, or using zfs key -l. In our case, we can see that the key is already loaded, and so can ignore the warning:
|
1 2 |
# zfs key -l datapool/encryptfs cannot load key for 'datapool/encryptfs': already loaded. |
Change the wrapping key via zfs key -c:
|
1 |
# zfs key -c -o keysource=raw,file:///root/.encryptfs.key datapool/encryptfs |
To test that the change has been successfully implemented, unmount the filesystem and unload the wrapping key for the dataset:
|
1 2 |
# zfs unmount datapool/encryptfs # zfs key -u datapool/encryptfs |
Try mounting the dataset, and confirm that the operation is successful, and that no prompts/warnings are displayed:
|
1 2 3 |
# zfs mount datapool/encryptfs # zfs mount | grep -c encryptfs 1 |
As previously discussed, a ZFS filesystem with encryption=on set uses aes-128-ccm by default. We can change this when we create a new dataset, however. Observe:
|
1 2 3 4 5 6 |
# zfs create -o encryption=aes-256-ccm datapool/secretdata Enter passphrase for 'datapool/secretdata': Enter again: # zfs get encryption datapool/secretdata NAME PROPERTY VALUE SOURCE datapool/secretdata encryption aes-256-ccm local |
Our new dataset has been created using aes-256-ccm encryption.