Following up the previous post on creating rolling ZFS snapshots with systemd units & timers, this entry will cover continuous replication of these snapshots to another pool on the same host, using the same strategy.
unit file
The unit file relies on snapshots having a consistent naming scheme. The names here are the ones defined in the the previous post:
1 | autosnapshot-7-days-ago |
Unlike the autosnapshot unit file however, this is not initialized with the pool name as an instance variable. This is because there are 2 variables: the source pool and the target pool, which would necessitate some implicit functionality - they are both defined as environment variables in the unit file instead:
1 | [Service] |
This unit file handles rotating the snapshots on the replication target. This could be adjusted to save a different number of snapshots, but for consistency, it will match the strategy used in the autosnapshot unit file.
Lastly, the replication command needs to be wrapped in a /usr/bin/sh -c "..."
statement since the ZFS CLI requires a unix pipe to send/receive and has no alternative. The systemd Exec* directives do not support pipes, so running it in a subshell is hacky but officially recommended (COMMAND LINES
section in the systemd.service(5)
manpage).
1 | [Service] |
The filename format of the unit file is:
1 | zfs-autoreplication-<dataset name>-<number of retained snapshots>-<frequency>.service |
zfs-autoreplication-dataset2-7-daily.service
1 | [Unit] |
timer file
The timer is very simple. The OnCalendar
directive is set to 5 minutes after midnight, allowing the autosnapshot service plenty of time to complete first.
zfs-autoreplication-dataset2-7-daily.timer
1 | [Unit] |
enabling the service
Unlike the autosnapshot service, the autoreplication service requires some manual preliminary setup.
First, the entire ZFS pool+dataset hierarchy needs to be created beforehand, except for the actual dataset to be replicated. In this example, pool-1/dataset2
is being replicated to pool-2/backups/pool-1/dataset2
, so the path to create is pool-2/backups/pool-1
:
1 | sudo zfs create -p pool-2/backups/pool-1 |
Next, send over the very first snapshot. In this case the dataset is encrypted, so the --raw
and --props
flags are used to send over the dataset exactly as it exists on disk with all of its custom properties:
1 | sudo zfs send --raw --props pool-1/dataset2@autosnapshot-1-day-ago | zfs receive -Fv pool-2/backups/pool-1/dataset2@autosnapshot-1-day-ago |
The reason for manually running this command is because it does not include the previous snapshot as an option (-i
) - something the unit file relies on.
Finally, the autoreplication service + timer can be started:
1 | sudo systemctl enable --now zfs-autoreplication-dataset2-7-daily.timer |