Decrypting backup datasets

My on-line datasets are encrypted and I replicated the raw datasets to backup zpools with zfs send -w. I can decrypt them but the process in the GUI seems convoluted enough that I assume I am doing something wrong. Can anyone help with how this should work? This is with 25.04.1.

What ultimately worked was: Export encryption key in JSON from the online dataset. Open in a text editor and copy the encryption key. Click to unlock the dataset tree. Choose to manually provide the key. Paste the key into every dataset. Click to unlock.

What I also tried:

  • Uploading the JSON file, with or without Force. If the dataset name in the JSON does not match the dataset to unlock this fails.

  • Uploading the JSON file with the dataset name edited to match the backup dataset, with or without Force, and with or without Unlock children set. Only the parent dataset is unlocked, not the children.

  • Manually enter the key, with Unlock children set. Only the parent dataset is unlocked, not the children.

What I expected to happen: Upload the JSON from the on-line dataset, choose force (to ignore the dataset name) and unlock children, and it just works. Also, manually entering the key once in the parent and choosing unlock children should have worked.

Thank you for any assistance!

Evan

This depends on how/what you replicated and if all datasets share the same “encryptionroot”.

Can you post the output of this on the backup server:

zfs list -t fs -r -o name,encroot,keyformat <poolname>

Hi @winnielinnie – they all look the same, with encryption root = name.

backup/tank/home/evan	name	tank/backup/tank/home/evan	-
backup/tank/home/evan	encryptionroot	tank/backup/tankt/home/evan	-
backup/tank/home/evan	keyformat	hex	-

I’m guessing the issue is the encryption root is not pointing to the parent, because the datasets were replicated using syncoid --recursive which runs individual zfs send for each dataset – or if not because of syncoid specifically, maybe because the parent dataset at the destination was not unlocked at the time the child was replicated?

Thank you!

That’s not the command.

1 Like

Mmm I took from your response that you don’t approve with syncoid. It was helpful with another issue and is maybe causing an issue here.

I think I have worked out that whatever way I do this I need to fix something after the replication. zfs send -wpR tank@backup | zfs recv -u -o readonly=on backup/tank sets encryptionroot correctly, and mountpoint needs to be fixed post-replication.

Can you post the output of this on the backup server:

zfs list -t fs -r -o name,encroot,keyformat <poolname>

Hi Winnie, for what I had originally replicated when I moved to raw backups with “syncoid --preserve-properties --sendoptions=w” this was what was replicated:

NAME                                         ENCROOT                     KEYFORMAT
backup                                       -                           none
backup/tank                                  -                           none
backup/tank/home                             backup/tank/home            hex
backup/tank/home/evan                        backup/tank/home/evan       hex

i.e. the encroot of every encrypted dataset was itself, with tank/home being the actual encryption root.

I redid the replication using “zfs send -wpR” and the result was:

NAME                                         ENCROOT                     KEYFORMAT
backup                                       -                           none
backup/tank/home                             backup/tank/home            hex
backup/tank/home/evan                        backup/tank/home            hex

i.e. the encroot of every dataset is the actual encryption root (tank/home).

The behaviour unlocking the datasets with the correct encroot is:

  • Using the .json downloaded from the on-line dataset as-is fails, with or without Force.
  • Using the .json hacked to reference the backup dataset works, and all child datasets unlock.
  • Manually entering the key only asks for the key for the encroot, and all child datasets unlock.

So, with encroot set correctly this works much much better. It would be even better (and possibly avoid a freak-out at a high-pressure moment) if the uploaded json worked as-is, maybe with “this key is for another dataset , do you want to try anyway?”. I had assumed that this was what “force” was for, to “force” using the key even if the dataset name in the JSON didn’t match, but I read the description just now and it does something completely different.

In some cases it’s possible that the provided key/passphrase is valid but the path where the dataset is supposed to be mounted after being unlocked already exists and is not empty. In this case, unlock operation would fail. This can be overridden by Force flag. When it is set, system will rename the existing directory/file path where the dataset should be mounted resulting in successful unlock of the dataset.

That’s on me for not reading the fine print. It is interesting that this particular problem, which seems fairly specific, has a UI feature to address, while every mount of every raw-replicated encrypted dataset will fail unlocking with the JSON downloaded from the on-line dataset, and has no UI support. ¯_(ツ)_/¯

My conclusion is that I will try to use zfs send -wpR where I intend to replicate an entire tree, so that encroot is set properly.

Evan