I have the following scenario: A couple of Mac computers push their hourly/daily backups to a timecapsule device using timemachine (actually, pushing to a samba share would do equally well, see this older post of mine). One of the benefits is that my work group has total control over this timecapsule, it is always accessible to us. On the other hand, in case of fire or burglary, not only our workstations might be lost, but also our backup device.
So, the easiest workaround to this problem is to make frequent backups of the contents of the backup device, it would seem. This way I do not need to reconfigure many individual Mac computers which users usually prefer to administer themselves. Also, there is the advantage of having two redundant copies of the same data in two geographically distinct places.
The possibly easiest way to proceed is to run rsync on my local machine to copy all the data accross the network. Catch is, this slows down my network connection and that of the group. Also, I don't want to run rsync during business hours, but, say, before I go home, and ideally not on my laptop but on some stationary office machine.
To automate all that, I need to store passwords for accessing the timecapsule as well as a network storage (which is a samba share in our case) somehow. Leaving those passwords in plaintext in a script file is a dumb idea, coming up with some type of your own purpose built cryptography would be reinventing the wheel and might actually only provide a very weak security measure.
But there's hope: Mac OS knows a command line command named security which allows to access secrets stored in a keychain. That is the place, where Mac OS likes to store passwords. And if Mac OS can do it, why shouldn't I?
Below you see a shell script that I run (by hand) regularly on a remote machine (encapsulated in the fantastic screen command) to move around our precious backups. The script accesses passwords stored in a custom built keychain file located in the current directory. It mounts the network shares (one is the timecapsule and one the samba share) and then uses rsync to copy all the data. The advantage is that I only need to enter a password of my choosing once to initiate this entire process, while the password secrets are really stored on a machine that potentially untrusted persons would have access to.
My intention here is to give some hints on how I managed to automate this recurring task. I do not intend to provide working software or counseling for those whose setups are different from mine. Hence, the following software is provided as is, and without any warranty. Your milage may wary, use at your own risk!
bash
function log(){ echo $* >&2
}
function fail(){ echo $* >&2
exit 1
}
WORK_DIR=~/storageserver-backup
log ===
log $0 invoked on `date`
log unlocking storageserver keychain to access server passwords:
security unlock-keychain $WORK_DIR/mykeychain.keychain || fail "unlocking keychain failed"
log -n initializing...
SOURCE_SUBDIR=timecapsule-mount
DEST_SUBDIR=storageserver-mount
DEST_SERVER=storage.server.name.de
DEST_USER=username
DEST_SHARE=the_name_of_your_share_here
DEST_PASSWORD=`(security find-internet-password -s $DEST_SERVER -a $DEST_USER -g $WORK_DIR/mykeychain.keychain >/dev/null) 2>&1 |sed -e 's/^password: "\(.*\)"$/\1/'` DEST_MOUNTSTR="mount_smbfs //$DEST_USER:$DEST_PASSWORD@$DEST_SERVER/$DEST_SHARE $WORK_DIR/$DEST_SUBDIR"
SOURCE_SERVER=timecapsule1.local SOURCE_PASSWORD=`(security find-internet-password -s $SOURCE_SERVER -g $WORK_DIR/mykeychain.keychain >/dev/null) 2>&1 |sed -e 's/^password: "\(.*\)"$/\1/'` SOURCE_MOUNTSTR="mount_afp afp://nobody:$SOURCE_PASSWORD@$SOURCE_SERVER/Data $WORK_DIR/$SOURCE_SUBDIR"
log done.
log locking keychain again.
security lock-keychain $WORK_DIR/mykeychain.keychain
log -n cleaning up...
umount "$WORK_DIR/$DEST_SUBDIR" "$WORK_DIR/$SOURCE_SUBDIR" || true
log done.
log -n Mounting file systems...
eval $SOURCE_MOUNTSTR || fail Failure mounting source, aborting.
log -n \(source OK\)...
eval $DEST_MOUNTSTR || fail Failure mounting destination, aborting.
log -n \(destination OK\)...
log done.
cd "$WORK_DIR/$DEST_SUBDIR"
rsync --delete-during -avP "$WORK_DIR/$SOURCE_SUBDIR" .
log -n Unmounting file systems...
umount "$WORK_DIR/$DEST_SUBDIR" "$WORK_DIR/$SOURCE_SUBDIR"
log done.
log $0 done.