How to Set Up ZFS Encrypted Pool on Linux

arch linuxencryptionfilesystemszfs

I'm currently playing around and testing ZFS and I really like it. Now I am looking for the best way to use it as a replacement for my standard setup with luks-based full disk encryption.

How is the concept of encryption in ZFS, do I encrypt a whole pool or just individual datasets? My idea is to boot, enter a passphrase and the rest as usual. I do not want to enter a passphrase for every dataset in my pool, so is it possible?

I already tried using a ZFS pool inside a luks full disk encryption container, it works, but I guess this will be way less performant than using ZFS directly.

I'm using Arch Linux with the "Stable" kernel and an NVME SSD. Thanks for clarification and recommended setups!

Oh, one more: I read that you cannot encrypt existing datasets or pools, is that still the case?

Best Answer

  • Encryption was added to ZFS On Linux with the release of version 0.8. So you need at least that version.

  • In ZFS, encryption is on a per-dataset basis, not on a pool - but, as with most things in ZFS, a dataset can inherit encryption properties from its parent (or from a defined encryptionroot instead of the parent).

  • Setting encryption on a dataset in ZFS will not automatically encrypt any data already in it. As with enabling compression (or changing the compression type), only new data will be encrypted.

  • to encrypt existing data, you can rsync or zfs send it to another dataset with encryption enabled, and then replace the old dataset with the new encrypted one. This may require the system to be in single-user mode (or, at least, to temporarily shut down any programs which may write to, or have files open on, the old dataset)

I don't use encryption on any of my zpools, so that's about all I know about it. I'd strongly advise doing more research and reading the archives of the ZOL mailing lists and search for encryption related issues on the ZOL github repo.

From the Encryption section of man zfs:

Encryption

Enabling the encryption feature allows for the creation of encrypted filesystems and volumes. ZFS will encrypt file and zvol data, file attributes, ACLs, permission bits, directory listings, FUID mappings, and userused / groupused data. ZFS will not encrypt metadata related to the pool structure, including dataset and snapshot names, dataset hierarchy, properties, file size, file holes, and deduplication tables (though the deduplicated data itself is encrypted).

Key rotation is managed by ZFS. Changing the user's key (e.g. a passphrase) does not require re-encrypting the entire dataset. Datasets can be scrubbed, resilvered, renamed, and deleted without the encryption keys being loaded (see the zfs load-key subcommand for more info on key loading).

Creating an encrypted dataset requires specifying the encryption and keyformat properties at creation time, along with an optional keylocation and pbkdf2iters. After entering an encryption key, the created dataset will become an encryption root. Any descendant datasets will inherit their encryption key from the encryption root by default, meaning that loading, unloading, or changing the key for the encryption root will implicitly do the same for all inheriting datasets. If this inheritance is not desired, simply supply a keyformat when creating the child dataset or use zfs change-key to break an existing relationship, creating a new encryption root on the child.

Note that the child's keyformat may match that of the parent while still creating a new encryption root, and that changing the encryption property alone does not create a new encryption root; this would simply use a different cipher suite with the same key as its encryption root. The one exception is that clones will always use their origin's encryption key. As a result of this exception, some encryption-related properties (namely keystatus, keyformat, keylocation, and pbkdf2iters) do not inherit like other ZFS properties and instead use the value determined by their encryption root. Encryption root inheritance can be tracked via the read-only encryptionroot property.

Encryption changes the behavior of a few ZFS operations. Encryption is applied after compression so compression ratios are preserved. Normally checksums in ZFS are 256 bits long, but for encrypted data the checksum is 128 bits of the user-chosen checksum and 128 bits of MAC from the encryption suite, which provides additional protection against maliciously altered data. Deduplication is still possible with encryption enabled but for security, datasets will only dedup against themselves, their snapshots, and their clones.

There are a few limitations on encrypted datasets. Encrypted data cannot be embedded via the embedded_data feature. Encrypted datasets may not have copies=3 since the implementation stores some encryption metadata where the third copy would normally be. Since compression is applied before encryption, datasets may be vulnerable to a CRIME-like attack if applications accessing the data allow for it. Deduplication with encryption will leak information about which blocks are equivalent in a dataset and will incur an extra CPU cost per block written.