Zfs send a replication stream from unencrypted pool to encrypted pool

I have an unencrypted pool with several datasets and I want to copy the entire pool over to a new pool, including all the existing snapshots. The new pool has native encryption enabled. I’d like to have the same hierarchy tree on the new pool. Meaning




When I use zfs send -R tank@snap | zfs receive -Fd -x encryption new-tank i get the following error

cannot receive new filesystem stream: zfs receive -F cannot be used to destroy an encrypted filesystem or overwrite an unencrypted one with an encrypted one

I’m basically just looking to duplicate unencrypted tank to encrypted new-tank, together with all of its existing snapshots. What’s the propper way of doing this?

I’m on Scale

If I remember correctly, you can no longer have an unencrypted datasets inside an encrypted one[1].

ZFS is likely complaining you are keeping the unencrypted propriety: drop it and you should have no issues.

For these kinds of replications, using the GUI is the best way.

Encryption and replication | TrueNAS Community might be interesting.

Anyway, wait for @winnielinnie: he’s one of the most knowledgeable users about encryption I know of.

  1. It might be the other way around. ↩︎

What I’m trying to do is to have the replicated datasets be encrypted by inheriting the encryption settings of the target pool (new-tank). My understanding is that the -R option on zfs-send will preserve all properties of the datasets, so I used zfs -x encryption to prevent the encryption property from being preserved (again, because i’m trying to end up with encrypted datasets)

I did try this as part of my troubleshooting and i get the same error

I get the following error when I tried the GUI. I assume that what I’m trying to do is not supported by the GUI hence tried command line

Destination dataset 'new-tank' already exists and is its own encryption root. This configuration is not supported yet. If you want to replicate into an encrypted dataset, please, encrypt its parent dataset.

The suggestion in the error doesn’t work for me because i wan to preserve the dataset hierarchy.

Well, it’s telling you it’s not supported. :slight_smile:

This is why I use “pseudo-root” datasets.

flowchart TD

nas1root("tank\n(root dataset)")

style nas1 stroke-width:4px
style nas1root stroke-width:4px
style zroot1 stroke:green,stroke-width:4px
style zroot2 stroke:blue,stroke-width:4px
style zroot3 stroke:red,stroke-width:4px
style dsArchives stroke:green
style dsDocs stroke:green
style dsPictures stroke:green
style dsMedia stroke:blue
style dsDownloads stroke:blue
style dsStaging stroke:red
style dsTemp stroke:red

nas1 === nas1root
linkStyle 0 stroke-width:6px
nas1root --- zroot1
nas1root --- zroot2
nas1root --- zroot3
zroot1 --- dsArchives
zroot1 --- dsDocs
zroot1 --- dsPictures
zroot2 --- dsMedia
zroot2 --- dsDownloads
zroot3 --- dsStaging
zroot3 --- dsTemp

In your case, for this one-time migration, you’ll have to do a replication for each dataset that is one level below the “tank” root dataset. (The -x flag will work in that case.)

When it comes to top-level root datasets, there is zero flexibility. You cannot overwrite them; not even with another source’s root dataset.

This is another grievance I have with the original ZFS design of a pool and its root dataset. But that’s another story…


Try without the -F option on the “zfs receive” side.
Theoritically, I think it is doable to encrypt on the receive end, but it can be painful.
All you have to do is create the encrypted pool and then replicate without destroying the dataset on the remote side.
You will need to create on the remote side datasets with inheritence of the encryption (either key or passphrase) too make like easier. Then you can change the encryption details later if needed.
Breaking it down as per @winnielinnie is probably the best option.

1 Like

Thanks @winnielinnie I will give this a try later this week and report back.

If i leave off the -F option then i get an error that the target already exists. So, without -F my only option would be to create a new dataset and have the source tree recreated under the top level dataset. As @winnielinnie said, having this pseudo-root dataset seems to be unavoidable in any case.

1 Like

Another option is to use a different transfer option like rsync, keep the old pool around long enough for you to be comfortable with the new pool, establish a good track record of snapshots in the new pool, etc. and only then give the old pool the heave-ho.

That process will take a lot longer than ZFS send, though so I’d try everything to make @winnielinnie’s suggestion work first. I presume you have taken the proper steps to ensure that the new pool will not be read-only, unless that is what you intended, right?