This is a tool to simplify and automate ZFS file system replication, both local
and remote. It uses an ordinary user together with sudo to avoid having to use
"root" and enable "root" ssh for remote replication.

Each file system you want to replicate is typed into a job-file that are stored
in "/usr/local/etc/replicatejobs". There you fill in all the parameters that is
needed to determine where and how you want that file system to be replicated. If
you have more than one file system that you want to replicate, you "cp job1
job2", fill in the parameters and watch the magic happen. Next time you "cp job2
job3", and so on. One cool thing about this is that you can have job1 filled in
with e.g. "pool/very_secure" to do local replication towards a secondary pool in
the same machine, and then you fill in job2 for the same "pool/very_secure" file
system to do remote replication towards a completely different system; it is very
dynamic in that sense. You can have as many job files- and replicate as many file
systems as you like. You also type in if you want a job to be recursive or not.

Every time a job is run, replicate looks for a baseline snapshot. If there is
none, it makes a baseline replication. The next time it runs, it finds a base,
and instead makes an incremental replication, automatically.

The job-files can be called just about anything, it isn't that important. It has
however been made so that if you call them something starting with "sample_" or
"noauto_" they won't run scheduled in cron. In case you have a very big file
system that wouldn't complete in one hour that you want to have sufficient time
to manually initialize a baseline of. When the baseline is complete, you simply
rename the job to be included among the scheduled, like: "mv noauto_job1 job7".
Or maybe you have this file system that you can set up in cron with a less
frequent execution, e.g.:
10 0 1 * * root /usr/local/bin/replicate noauto_job1

Security-wise, this approach is better than having "root" do it. That said; it is
far from foolproof. If you are only doing local replication, it is completely
safe, because "root" tells "replicator" exactly what it is allowed to do for each
job, and then revokes it again. But for remote replication, you have to allow
"replicator" to do everything it is supposed to be able to do on the target:

replicator ALL=(ALL) NOPASSWD: /sbin/zfs recv *
replicator ALL=(ALL) NOPASSWD: /sbin/zfs destroy *@remote_replicate.base
replicator ALL=(ALL) NOPASSWD: /sbin/zfs rename *@remote_replicate.delta *@remote_replicate.base
replicator ALL=(ALL) NOPASSWD: /sbin/zfs destroy pool/*
replicator ALL=(ALL) NOPASSWD: /sbin/zfs destroy * pool/*
replicator ALL=(ALL) NOPASSWD: !/sbin/zfs destroy pool/root*
replicator ALL=(ALL) NOPASSWD: !/sbin/zfs destroy * pool/root*

Change the name of the pool accordingly! Worst case, this allows replicator to
destroy EVERYTHING it has replicated into the target, with the root(/) file system
as an exception, so that the target system itself never is at risk, only what has
been replicated into it, which can always be replicated back again, in case of a
breach. And in case that happens, these commands are the only ones that an
attacker has access to, which are plenty dangerous, but still far less commands
than if you were "root". And because the root(/) file system is excluded, you will
never loose any uptime, it is just going to take a while to replicate everything
back in again.

Each operative ZFS-command is followed by an errorcheck that halts current job,
tails the last two lines of output into replicate.log, tails that into
/var/log/messages, and then goes on with the next job. So just because one of
your jobs experiences an error, doesn't mean they all stop- just that one, and
you can see what went wrong by reading the logs.

When remote replicating, there has to be a filesystem matching the source
hostname on the target. E.g. source has hostname "frodo". On target there has to
be a "pool/frodo" filesystem in place.

### Examples ###

# replicate 
Makes it process all the job-files one by one.

# replicate noauto_job1
Makes it only process "noauto_job1"

# replicate -c
Makes it clean all file systems in every job-file, starting over from scratch

# replicate -c job3
Makes it clean only "job3". In case something has gone wrong and that job needs a
reboot.

# replicate -c auto
Makes it clean all snapshots with the word "auto" in them, taken with e.g.
"sysutils/zfsnap"
