ZFS send end receive for backups
================================

ZFS is a wonderful file system
------------------------------
ZFS is a wonderful file system with many advantages.

People write entire books about ZFS, this post only scratches the
surface.

FreeBSD has long supported ZFS, including the usage of ZFS on the root
file system, paving the way for so-called boot environments.

ZFS also runs on Linux and offers some of its advantages there too.

ZFS snapshots
-------------
A great feature of ZFS is the capability of taking snapshots.

A snapshot is like a photo of your file system, it freezes a moment in
time.

Because ZFS is a so called `Copy on Write' file system (CoW), the
creation of a snapshot is instantaneous. ZFS snapshots use space on
the same storage pool as the file system from which they are created.
A fresh snapshot consumes nearly no space, changes of the live file
system will grow the size of the snapshot.

Rolling back and cloning of snapshots
-------------------------------------
A roll-back of a ZFS snapshot restores the file system to the state at
the moment the snapshot was created. It discards all the changes made
since the specific snapshot.

Subsequent snapshots allow you to choose the point in time to go back
to. Some people for example let their system make a snapshot of their
home directory every ten minutes. Another example is making snapshots
just before changes like installing or updating packages.

A clone of a ZFS snapshot replicates the snapshot on a different
location within the ZFS file system. The creation of a clone is
instantaneous.

Snapshots and clones add a whole new dimension to the deployment of
containers like jails and virtual machines because of this.

ZFS send and receive
--------------------
ZFS send and receive moves snapshots efficiently.

ZFS send and receive can be done within the same system, but is most
used to move snapshots to other systems.

ZFS send can dispatch incremental data. In this case, the difference
between two subsequent snapshots is transported to the receiving
system. This requires the snapshots on the sending and the receiving
machines to be in sync.

The first time sending a snapshot takes considerate time. It is
best to do this from within tmux. Sending subsequent incremental
snapshots take much less time.

Daily backup using ZFS send and receive
---------------------------------------
The example script below creates a snapshot and leverages the use of
sending incremental data to efficiently send it to another machine.
This assumes that the first snapshot is send normally to the
receiving machine.

In this example:

* both systems run ZFS
* the dataset to snapshot is called `myset'
* the receiving system is called `receiver', this can be a hostname or
 an ip-address
* zstdmt is used to compress the data before sending
* zstd is used to decompress the data on the receiving system
* the user on the sending system has password-less ssh access to the
 receiving system
* the user on the sending and the receiving system has the proper
 permissions for this action

   #!/bin/sh

   mydate=$(date "+%Y-%m-%d-%H:%M")

   /sbin/zfs snapshot zroot/myset@$mydate
   previous=$(/sbin/zfs list -t snapshot | grep myset | sort -rn | head -n 2 | tail -n 1 | cut -d' ' -f 1)

   /sbin/zfs send -i $previous zroot/myset@$mydate | zstdmt | ssh receiver "zstd -d | zfs receive zroot/backups/myset@$mydate"

This script can be run from cron, for example every hour or every night.

Result
------
The data now lives on two machines.

`zfs list -t snapshot' on both the sending and the receiving system
lists the subsequent snapshots of `myset'.

When on the receiving system a mount point is set for
zroot/backups/myset the data can be access there normally.
However, be careful not to change the data on the receiving machine,
because this results the data between the two systems being out of
sync.

Working with non-root users
---------------------------
Some advantages of the ability to run the preceding script as a non-root
user on both the sending and the receiving system are:

* the user can choose any convenient moment to perform the action
* no need for root ssh access on the receiving system

Delegate permissions for a specific dataset with `zfs allow' at a fine
grained level like create, destroy, mount, snapshot, and so on.

To allow a user to create a snapshot of a specific dataset and to
send that snapshot, use the following command:

  zfs allow <user> hold,mount,send,snapshot zroot/myset

And on the receiving system:

  zfs allow <user> create,mount,receive zroot/backups

Permissions can be retracted with `zfs unallow'.

To list the current permissions use `zfs allow <dataset>' without
any options, like:

  zfs allow zroot/myset

Clean up
--------
It's not necessary to keep old snapshots. Delete old snapshots on a
regular basis to avoid wasting storage space.


Last edited: $Date: 2024/01/01 16:30:23 $