I have a local FreeNAS system and want to use ZFS snapshots for backups.
FreeNAS has the built-in Replication Tasks which use

zfs send snapshot_name

to send a snapshot to a remote system. But this needs a system with ZFS on the other end.

I want to send the snapshot to a a file and send this compressed and encrypted file to the remote machine.

This is possible with

zfs send snapshot_name | gzip | openssl enc -aes-256-cbc -a -salt > file.gz.ssl

Everyday I make a snapshot of the storage pool and keep every snapshot for 30 days.
With every snapshot taken I'll pipe this snapshot to a file.
- snapshot_file 1 has every file in it (let's say 2GB)
- snapshot_file 2 only has the changes to snapshot_file 1 (let's say 5MB)
- snapshot_file 3 holds the changes to snapshot_file 2; and so on.

On day 31 snapshot_file 1 is getting deleted (because I only want the changes from the last 30 days)

Therefore snapshot_file 2 needs to hold every file (2GB of snapshot_file 1 + 5MB changes)

But with this approach everyday (from day 31 on) a new 2GB file has to be created and send to a remote system. This is too much overhead.

What would be the best approach to use snapshots piped to a file as a backup strategy with a history of X days?

P.S.: I know there are a lot of backup software out there (rdiff-backup for example), which I could use. But I am curious how this could be done.

  • Why don't you use zfs recv on the other end (on a pool with zfs set compression=gzip-9 for instance). Storing snapshot files sounds very inefficient to me. Commented Feb 5, 2014 at 20:23
  • 2
    @StephaneChazelas because I do not have a ZFS file system on the other end. My remote system is a gentoo box with ext4 (I know I could install zfsonlinux, but I rather not) Commented Feb 5, 2014 at 20:31

1 Answer 1


If you store the snapshots in files, as opposed to in the file system (e.g. with zfs receive), I'm afraid, this is not possible.

ZFS on the receiving side

If you use ZFS on the sending and on the receiving side you can avoid having to transfer the whole snapshot and only transfer the differences of the snapshot compared to the previous one:

ssh myserver 'zfs send -i pool/dataset@2014-02-04 pool/dataset@2014-02-05' | \
  zfs receive

ZFS knows about the snapshots and stores mutual blocks only once. Having the file system understand the snapshots enables you to delete the old ones without problems.

Other file system on the receiving side

In your case you store the snapshots in individual files, and your file system is unaware of the snapshots. As you already noticed, this breaks rotation. You either have to transmit entire snapshots, which will waste bandwidth and storage space, but enables you to delete individual snapshots. They don't depend on each other. You can do incremental snapshots like this:

ssh myserver 'zfs send -i pool/dataset@2014-02-04 pool/dataset@2014-02-05' \
  > incremental-2014-02-04:05

To restore an incremental snapshot you need the previous snapshots as well. This means you can't delete the old incrementals.

Possible solutions

You could do incrementals as shown in my last example and do a new non-incremental every month. The new incrementals depend on this non-incremental and you're free to delete the old snapshots.

Or you could look into other backup solutions. There is rsnapshot, which uses rsync and hard links. It does a very good job at rotation and is very bandwidth efficient, since it requires a full backup only once.

Then there is bareos. It does incrementals, which are bandwith- and space-saving. It has a very nice feature; it can calculate a full backup from a set of incrementals. This enables you to delete old incrementals. But it's a rather complex system and intended for larger setups.

The best solution, however, is to use ZFS on the receiving side. It will be bandwidth efficient, storage efficient and much faster than the other solutions. The only really drawback I can think of is that you should have a minimum of 8 GiB ECC memory on that box (you might be fine with 4 GiB if you don't run any services and only use it to zfs receive).

  • yes this I know. But what if I delete (because I only want to have a history of 30 days) the file dataset@2014-02-04? Then I only have the changes made after the Feb, 4th, but not every file. Commented Feb 5, 2014 at 21:19
  • 2
    @MartinGrohmann I see what you mean now. Well that's the beauty of ZFS, you can delete the old snapshots on ZFS without problems. On other filesystems you have to keep the old ones. Maybe you're better off with something like rsnapshot then. Or you could start a new non-incremental after one month and then delete the previous incrementals.
    – Marco
    Commented Feb 5, 2014 at 21:24
  • thank you for your help; I just found duplicity That's probably the way to go with the ability of encryption. Commented Feb 5, 2014 at 21:27
  • 2
    @MartinGrohmann Duplicity is a nice program, but it suffers from the same problem. If you only do incrementals your space keeps growing. You can't reclaim space without wasting bandwidth and doing a new full backup. Either go ZFS on both sides or have a look at bareos, it can calculate a new full backup from incrementals. That enables you to delete old incrementals without re-transferring everything.
    – Marco
    Commented Feb 5, 2014 at 21:33
  • If bandwidth from your source is the problem, a potential solution (which I'm implementing for my home ZFS NAS now) is to always only send incrementals to your remote storage, but once a month spin up a remote freeBSD VPS (e.g., on digital ocean) which can then open the last full snapshot, zfs recv the some # of incrementals into it, then store the result as a new snapshot. The VPS only needs to be around long enough to create the new base backup. Digital ocean has an API allowing easy creation / destruction of their VPSes. And your local system need only send incremental backups.
    – stuckj
    Commented Nov 6, 2016 at 2:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .