Unlock and mount several ZFS datasets on boot with single passphrase

20 Jan 2021
blurry code

Why would anyone use a single passphrase for several datasets?

I generally do not endorse reusing passwords, but when setting up a ZFS filesystem for home use, it is not unheard of to use a single (secure) passphrase across several of those. That's because the reason behind splitting up pools into multiple datasets is the granular control over their properties and not the resulting fun of having to type in multiple passphrases.

Obviously, the more usual way of going about it would be using a keystore, or simply protecting one dataset with a passphrase and unlocking all the others with the keys stored within. This method has its downsides however and for home use, I do feel more confident about having everything I need to unlock my data with inside of my head.

Script it

So I wrote a simple bash script which asks for a passphrase and proceeds to unlock all (or optionally specified) datasets and optionally mounts them. You can find it in this repo: github.com/gbytedev/zfs-multi-mount.

The script will ask for a passphrase and go dataset by dataset attempting to load the keys. As soon as it encounters a dataset the key for which cannot be loaded, it prompts for a new passphrase.

Examples of usage

Load keys of all datasets and mount them

  1. zfs-multi-mount.sh

Load keys for specific datasets and mount them

  1. zfs-multi-mount.sh pool/dataset1 pool/dataset2 pool/dataset3

Load keys without mounting the datasets

  1. zfs-multi-mount.sh --no-mount

Unlocking ZFS datasets during boot time using a systemd service

Data that is needed during system start needs to be decrypted during the boot process. An example of this is an encrypted home directory.

The script called by the following service will have to live in some unencrypted location. In this example, it is /opt/scripts.

Create the systemd service file

/etc/systemd/system/zfs-load-key.service

  1. [Unit]
  2. Description=Import keys for all datasets
  3. DefaultDependencies=no
  4. Before=zfs-mount.service
  5. Before=systemd-user-sessions.service
  6. After=zfs-import.target
  7. OnFailure=emergency.target
  8.  
  9. [Service]
  10. Type=oneshot
  11. RemainAfterExit=yes
  12.  
  13. ExecStart=/opt/scripts/zfs-multi-mount.sh --systemd --no-mount
  14.  
  15. [Install]
  16. WantedBy=zfs-mount.service

The [Unit] section tells the service to be run after ZFS pools are imported and before the datasets are mounted. If the script errors out (because of too many authentication attempts, or because the datasets cannot be found), the user will be dropped to an emergency shell.

In [Service] the service is instructed to run the script, which in turn is told to only load keys for datasets instead of mounting them (--no-mount|-n as this is taken care of by a ZFS service) and that it is being run within the systemd context (--systemd|-s).

Enabling the new service

Now all that is left is to enable the service:

  1. systemctl enable zfs-load-key.service

You can find the script in this repo: github.com/gbytedev/zfs-multi-mount. Let me know if you find it useful and how you would improve it.

Feel free to look at my other ZFS bash script that takes care of snapshotting, replication and rotation: zfsbud.

Add new comment

The content of this field is kept private and will not be shown publicly.

Restricted HTML

  • Allowed HTML tags: <a href hreflang target> <em> <strong> <cite> <blockquote cite> <pre> <ul type> <ol start type> <li> <dl> <dt> <dd> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.

Get a quote in 24 hours

Wether a huge commerce system, or a small business website, we will quote the project within 24h of you pressing the following button: Get quote