Zfs send and receive with unencrypted dataset to encrypted dataset

I am doing some tests to figure out how to migrate an unencrypted dataset to an encrypted dataset. “Gamak_Base/test_of_zfs_receive” is the unecrypted dataset.

“Gamak_Base/test_of_zfs_receive_encrypted/encrypted_file_system” is my string to create the new encrypted data set. This dataset is the child of an encrypted Dataset called, “test_of_zfs_receive_encrypted.”

When I run the below command, the new dataset gets created, but is created unencrypted.

zfs send -R --raw Gamak_Base/test_of_zfs_receive@manual-2025-05-11_12-58 |zfs receive -F Gamak_Base/test_of_zfs_receive_encrypted/encrypted_file_system

I’ve looked at a couple of threads on this matter, but I’m not sure what I am doing wrong.

Assistance would be appreciated.

Don’t use -w (--raw) for this. A raw stream sends (and preserves) the properties from the source dataset.

If the target parent (“test_of_zfs_receive_encrypted”) is encrypted, and you want zfs recv to have the target (“encrypted_file_system”) inherit this parent’s encryption, you need to add -x encryption to the zfs recv side:

zfs send -R Gamak_Base/test_of_zfs_receive@manual-2025-05-11_12-58 | zfs receive -F -x encryption Gamak_Base/test_of_zfs_receive_encrypted/encrypted_file_system
1 Like

So -x removes the encryption property? Does that in practice mean that the data will be encrypted with the key of the new parent or just have the encryption bit set by the new parent? I admit I am nowhere near being a zfs expert, so if this question seems dumb, I apologize.

-x encryption on the receive side means: “Ignore the sending source’s encryption properties, and create this new dataset so that it inherits this property from its new parent.”

EDIT: Even though the source is unencrypted, it still has an encryption property. encryption=off is the property’s value. Just because something is not encrypted, doesn’t mean it lacks the property.

The caveat about the property encryption is that it cannot be changed after creation, whether done manually or received through a send/recv. It is set (forever) upon creation.

I ran into another weird anomaly while testing this. I tried using mv to directly move data between two datasets. The data is 10tb in size and the pool is 16tb. The strange part is that about 85% of the way through the move, the pool runs out of space. I’m a bit confused as to way that would be the case?

Why?


Because snapshots hold onto “deleted” data blocks. The mv command basically deletes the source files after a successful copy to the destination.

Since you did this across datasets (filesystems), you’re creating a copy of the file on the new dataset, while deleting it from the source. You don’t reclaim that space because snapshots are still referencing those deleted files.

So how does one reclaim the space? Delete the old snapshots and dataset?

Do you need to keep the dataset?

Deleting the snapshot should suffice.

It’s unclear. What are you trying to accomplish?

In this case I was moving data from an unencrypted dataset to an encrypted dataset. Is is my secondary TrueNAS. I actually started this MV before I found the information on zfs send/receive that you helped me with above. I wasn’t sure that ending the move with ctrl-c was a good idea, so I decided to let it run it’s course and ran into this space issue.

Is this important data or just to test?

It’s not highly important. I have it on my other Truenas and backed up on an external USB Drive.

I’m not sure what the status of your pool is, but it’s possible to delete the new dataset (that you mv'ed your files to) and then “rollback” to the most recent snapshot on your original dataset. This assumes that the snapshot has everything you need. (i.e, it was created right before you did all of these steps.)

I may just redo the pool and try to replicate it back over from my other TrueNas. Is there an equivalent of the “-x encryption” switch in the zfs replicate job options?

Not really, but what you can do is tick the “Encryption” box. Use passphrase encryption.

After the replication completes, you can “unlock” the dataset on the new location, and then change its “Encryption” property to “inherit” from its parent.[1]

It’s an extra step, but it will result with the same outcome.


  1. :warning: Don’t forget that this means your replicated dataset will no longer use your temporary passphrase, but will instead be unlocked with its “encryptionroot” (its parent). If you cannot unlock the parent, then you cannot access the data inside the child dataset. Don’t forget this. ↩︎

I rolled back to the snapshot and strangely TrueNAS shows 16Tb used of 20TB even though the dataset that I originally used MV on is 10Tb. Is there any way to figure out what is causing that?

zfs list -r -t filesystem,volume -o space Gamak_Base

Seems to be a lot of strangeness going on.

I deleted the GamakBaseBackup/GamakBackup dataset. However now if I try to make a dataset using the same name “GamakBackup” I get a middleware error from the TrueNAS wizard.

At this point, with all this strangeness I may have to just reinstall this TrueNAS.

I’m seeing that zfs send/receive is really a copy of the dataset, as a result it takes double the amount of space at the end of a copy to a new data set on the same TrueNAS. Is there a way to perform an actual move of data to a new dataset?

That’s not the issue.

You were saving files directly inside your root dataset “GamakBaseBackup”.

You should never do this. I’m not even sure how you were able to, since TrueNAS has safeguards that try to prevent saving files directly inside the root dataset’s filesystem.

What likely happened is that you created/mounted the dataset “GamakBackup” over a folder of the same name.

I setup a replication task from the encrypted dataset on my backup trueNAS to replicate back to the primary TrueNAS. When I run the task, it says there are no matching snapshots. I have looked and I have snapshots for the dataset.

The error is below:

[2025/05/21 07:49:21] INFO     [Thread-20] [zettarepl.paramiko.replication_task__task_2] Connected (version 2.0, client OpenSSH_9.2p1)
[2025/05/21 07:49:21] INFO     [Thread-20] [zettarepl.paramiko.replication_task__task_2] Authentication (publickey) successful!
[2025/05/21 07:49:21] INFO     [replication_task__task_2] [zettarepl.replication.pre_retention] Pre-retention destroying snapshots: []
[2025/05/21 07:49:21] INFO     [replication_task__task_2] [zettarepl.replication.run] No snapshots to send for replication task 'task_2' on dataset 'GamakBaseBackup/Gamak_Base_Backup_Enc'
[2025/05/21 07:49:21] ERROR    [replication_task__task_2] [zettarepl.replication.run] For task 'task_2' non-recoverable replication error ReplicationError("Dataset 'GamakBaseBackup/Gamak_Base_Backup_Enc' does not have any matching snapshots to replicate")

Am I missing a step?