This is one way to have a host standbyhost mirror a directory tree on livehost. It has root@standbyhost initiate the copy by asking copier@livehost, via rsync, to supply livehost's data.

With the right authorized_keys options, we can make sure that supplying data is all that copier@livehost is able to do. Since the receiver of the data is root, we can preserve the copied files' owners, groups, permissions and modification times.

On standbyhost

As root, generate an ssh key pair having no passphrase.
# ssh-keygen -t rsa -f ~/.ssh/id_rsa_pull -C 'For backups from remote copiers.'
Create a config in ~root/.ssh/config pointing to livehost.
# cat ~/.ssh/config
Host pull-livehost
   BatchMode yes
   Compression yes
   ForwardAgent no
   ForwardX11 no
   HostName livehost.ourlan
   IdentityFile /root/.ssh/id_rsa_pull
   User copier
Create a script to copy a directory tree from livehost. For brevity, this omits such things as a lockfile, logging and looping over a directory list.
# cat /usr/local/sbin/rsync-pull
#!/bin/bash
set -o errexit

rsync \
   --bwlimit=1000 \
   --cvs-exclude \
   --delete \
   --owner \
   --group \
   --links \
   --perms \
   --recursive \
   --safe-links \
   --times \
   pull-livehost:/home/nick /var/local/backups

exit 0

On livehost

Create the user whose job it is to copy data for standbyhost.
# adduser --system \
  --shell "/bin/bash" --home /var/lib/copier \
  --gecos "rsync-push user,,," copier
Create the script that copier will run to provide the data.
# cat /usr/local/sbin/rsync-push
#!/bin/bash
set -o errexit
set -o nounset

declare -r \
    CMD="rsync --server --sender -logtprCe.if --bwlimit=1000 --safe-links . "

# Extract the directory to copy.
declare -r SOURCE_DIR="${SSH_ORIGINAL_COMMAND##$CMD}"

if [ -d "$SOURCE_DIR" ]; then
    $CMD "$SOURCE_DIR"
fi

exit 0
A potential snag here is that the value of CMD must exactly match the leading portion of the command sent by the rsync-pull script. If there's any doubt about it, have rsync-push log the value of SSH_ORIGINAL_COMMAND so you can compare. You'll likely need to do that if you decide on some other combination of rsync options than the ones I put into the rsync-pull script above.

To give copier the ability to run rsync-push for data it can't otherwise see, run visudo to add these entries.

Defaults:copier env_keep += SSH_ORIGINAL_COMMAND
...
copier    ALL=NOPASSWD: /usr/local/sbin/rsync-push
The copier user also has to accept the ssh connection from standbyhost, so it needs an authorized_keys file like this:
# cat ~copier/.ssh/authorized_keys
command="sudo /usr/local/sbin/rsync-push",from="standbyhost.ourlan",no-port-forwarding,no-X11-forwarding ssh-rsa AA...XVmf For backups from remote copiers.
The latter portion of authorized_keys, from 'ssh-rsa AA...' onwards, is the contents of id_rsa_pull.pub. The leading portion of authorized_keys contains the options designed to keep copier on the straight and narrow. In particular, the command option ensures that running rsync-push is all that copier can do over ssh.

Back on standbyhost

To get livehost into root's known_hosts file, make an ssh connection to pull-livehost. You'll need to temporarily comment out 'BatchMode yes' from ~root/.ssh/config. Then the ssh session should go something like this,
# ssh pull-livehost
The authenticity of host 'livehost.ourlan (10.0.0.3)' can't be established.
RSA key fingerprint is b5:bf:43:2b:c5:9d:01:c6:ec:e3:09:a5:c8:ba:55:53.
Are you sure you want to continue connecting (yes/no)? yes

Warning: Permanently added 'livehost.ourlan,10.0.0.3' (RSA) to the list of known hosts.
/usr/local/sbin/rsync-push: line 23: SSH_ORIGINAL_COMMAND: unbound variable
Connection to livehost.ourlan closed.
The error about SSH_ORIGINAL_COMMAND is fine, we didn't invoke the command that copier's config expects. But now we will:
# /usr/local/sbin/rsync-pull
If it works, you'll see the directory tree from livehost start to appear on standbyhost's filesystem. At this point you could add a cron entry to run the copy every hour, or whatever you think suitable, though probably with a lockfile to prevent successive jobs running concurrently.

In this setup, copier can supply a file from anywere on livehost's filesystem. It might be sufficient (and safer) to add copier to whatever groups will give it read access to the necessary files, then you don't need to use sudo.

Of course, mirroring generally won't protect you from one of the most likely sources of disaster, an accidental deletion. One option is to make periodic offsite copies.

Words

Pictures

Updated 2010-11-30 01:53 GMT