zfs incremental recursive replication to usb drive

Im trying to make an incremental backup of my zfs root pool from my laptop to an external usb drive as a live file system, rather like an rsync backup

im already using rsync to back up my home to a nas, and want to use zfs snapshots to back up root and child directories

In a nutshell i create a zfs pool on my usb drive and then use zfs send recursive root snapshot piped into zfs receive to the pool on the usb drive

create the zfs pool on the usb drive

create the mount point

sudo mkdir -p /mnt/usb

create the pool on the drive and set the mount point

Code:
zpool create zbackup /dev/da0
zfs set mountpoint=/mnt/usb zbackup

I have zfs on root on my laptop and this is the layout

zfs list

this is the output of zfs list

Code:
NAME                 USED  AVAIL  REFER  MOUNTPOINT
bootpool             241M  1.69G   239M  /bootpool
zroot               19.5G  79.3G    96K  /zroot
zroot/ROOT          6.79G  79.3G    96K  none
zroot/ROOT/default  6.79G  79.3G  6.75G  /
zroot/tmp           1.07M  79.3G   384K  /tmp
zroot/usr           12.7G  79.3G    96K  /usr
zroot/usr/home      10.1G  79.3G  10.0G  /usr/home
zroot/usr/ports      675M  79.3G   675M  /usr/ports
zroot/usr/src       1.96G  79.3G  1.96G  /usr/src
zroot/var           1.82M  79.3G    96K  /var
zroot/var/audit       96K  79.3G    96K  /var/audit
zroot/var/crash       96K  79.3G    96K  /var/crash
zroot/var/log       1.16M  79.3G   780K  /var/log
zroot/var/mail       120K  79.3G   120K  /var/mail
zroot/var/tmp        268K  79.3G   108K  /var/tmp

create the recursive snapshot of root

I have created the recursive snapshot of the zfs root pool with this command

zfs snapshot -r zroot@2017-04-12

i can list the snapshots with this command

zfs list -t snapshot

which outputs

Code:
NAME                            USED  AVAIL  REFER  MOUNTPOINT
bootpool@2017-04-12             184K      -   239M  -
zroot@2017-04-12                   0      -    96K  -
zroot/ROOT@2017-04-12              0      -    96K  -
zroot/ROOT/default@2017-04-12   516K      -  6.74G  -
zroot/tmp@2017-04-12            240K      -   272K  -
zroot/usr@2017-04-12               0      -    96K  -
zroot/usr/home@2017-04-12      41.5M      -  9.71G  -
zroot/usr/ports@2017-04-12         0      -   675M  -
zroot/usr/src@2017-04-12          8K      -  1.96G  -
zroot/var@2017-04-12               0      -    96K  -
zroot/var/audit@2017-04-12         0      -    96K  -
zroot/var/crash@2017-04-12         0      -    96K  -
zroot/var/log@2017-04-12        192K      -   776K  -
zroot/var/mail@2017-04-12          0      -   120K  -
zroot/var/tmp@2017-04-12         84K      -   116K  -

zfs send and receive
  • recursive receive
Using zfs send with -R for recursive piped into zfs receive with the -F option

Code:
zfs send -Rv zroot@2017-04-12 | zfs receive -vF zbackup

This doesnt work as the zfs receive -F option seems to delete the snapshots
If i omit the -F option i get an error message saying the zbackup file system exists and use the -F option to overwrite it

i have also tried using the -d and -e options as well but still get an empty snapshot directory
  • Sending a single data set
Code:
zfs send -v zroot/usr/home@2017-04-12 | zfs receive zbackup

sending a single data set without the -F option works and create the directories and files from the data set

sending incremental snapshot

create second snapshot

Code:
zfs snapshot -r zroot@2017-04-14

Sending an incremental snapshot with the -R and -I options

Code:
zfs send -Rv -I zroot@2017-04-12 zroot@2017-04-14 | zfs receive -vF zbackup

Doesnt work either the snapshot directory is empty

What am i missing ?

Do i need to manually create the pools on the receiving end to replicate the directory structure and then use zfs send to send the data set to the corresponding directory

for example create the pool directory structure

Code:
zpool create zbackup/zroot/ROOT
zpool create zbackup/zroot/ROOT/default
zpool create zbackup/zroot/tmp
zpool create zbackup/zroot/usr
zpool create zbackup/zroot/usr/home
zpool create zbackup/zroot/usr/ports
zpool create zbackup/zroot/usr/src
zpool create zbackup/zroot/var
zpool create zbackup/zroot/var/audit
zpool create zbackup/zroot/var/crash
zpool create zbackup/zroot/var/log
zpool create zbackup/zroot/var/mail
zpool create zbackup/zroot/var/tmp

then use zfs send to send each data set to the corresponding pool

Code:
zfs send -v zroot@2017-04-12 | zfs receive zbackup/zroot
zfs send -v zroot/ROOT@2017-04-12 | zfs receive zbackup/zroot/ROOT
zfs send -v zroot/ROOT@2017-04-12 | zfs receive zbackup/zroot/ROOT/default

and so on for each snap shot

Rollback question

Suppose i want to rollback to recover a file in my home directory, should i use the home snapshot or the parent snapshot of zroot

So would i roll back the home snapshot

Code:
zbackup/zroot/usr/home@2017-04-12

or do i need to roll back the root parent snapshot

Code:
zbackup/zroot/@2017-04-12

I have read the handbook and zfs man pages and a few books but still cant get my head around receiving recursive snapshots

Im sure im missing something obvious, if anyone could point me in the right direction would be appreciated as i seem to be going round in circles
 
I have to admit that I've never learned the proper way to use zfs send and zfs receive to make backups. There are several ZFS backup solutions available, my personal favorite being sysutils/zxfer. The first example given in the zxfer(8) man page works very similarly to rsync -aAXv --delete, only its old snapashots on the destination that are deleted rather than old files. It's also capable of using rsync to do some tasks as well, though I've never needed to use it.

As for retrieving old files from snapshots: if all you need is one file, you can just get it from the snapshot itself rather than rolling a snapshot back. (Rolling a snapshot back is basically a full recovery option, like restoring a backup that's stored on the same filesystem you're trying to restore.) ZFS snapshots are given a hidden namespace at [dataset_mountpoint]/.zfs/snapshot. So the snapshots for the myfiles dataset, mounted at /usr/home/myuser, would be at /usr/home/myuser/.zfs/snapshot.

You'll have to enter the full path to get there. By default the .zfs directory itself is hidden from all system utilities, so things like ls(1) and du(1) won't show it at all. In my experience even ZSH shell completion won't see it there.

EDIT: Fixed the absolute path in my example.
 
Code:
zfs send -Rv zroot@2017-04-12 | zfs receive -vF zbackup

This doesnt work as the zfs receive -F option seems to delete the snapshots
If i omit the -F option i get an error message saying the zbackup file system exists and use the -F option to overwrite it

i have also tried using the -d and -e options as well but still get an empty snapshot directory

This looks about right. But I'm wondering if you're running into problems since you're receiving without -u -- all the new filesystems will try to be mounted over the old ones. Since this layout has explicit mountpoint settings (rather than just inherited), this will try to mount over / and at that point things get very confusing (or just stop working.)

For my backups (especially when they are on a removable drive, e.g. one that isn't expected to be mounted on every reboot) I find it easiest to import the backup pool with an altroot ( zpool import -o altroot=/tmp/backup) option. This will protect you from trying to mount over root (and anything else) if you forget to receive without the -u. I sill go through and change the mountpoints on the backup (potentially just have them all inherit) as soon as possible in case I ever forget the altroot on import. I also use zfs set readonly=on zbackup to make sure I don't change them accidentally. You can zfs recv into a readonly=on filesystem. With this setup, you should never need -F after the initial full send/recv (and you should avoid it for incrementals, or be very aware of everything it implies.)

Assuming you are past that, what do you mean an empty snapshot directory? What does zfs get -r used return? You should see all your filesystems, volumes, and snapshots reported from both source and destination after a successful send/recv. If you're getting all of the status messages (and a clean exit) from your recv indicating that things are working, but then the snapshots don't show up, something has really gone sideways.
 
Rollback question

Suppose i want to rollback to recover a file in my home directory, should i use the home snapshot or the parent snapshot of zroot

So would i roll back the home snapshot

Code:
zbackup/zroot/usr/home@2017-04-12

or do i need to roll back the root parent snapshot

Code:
zbackup/zroot/@2017-04-12

Snapshots and rollbacks are independent to each filesystem [1] so you don't need to rollback the parent to rollback the child.

That said, most of the time you just want to restore one or two files, and not rollback the entire filesystem. You can try my (shameless plug, but it's free ;)) https://github.com/eborisch/zfs_versions script to show the old versions or diffs (and full paths to them) of a file. You can then use the paths listed to copy out the one you want.

[1] If you're doing recursive incremental backups, you will want to be careful not to rollback beyond your most recently backed-up snapshot, or you'll need to take care extra on your next update.
 
Back
Top