The best way to do a reliable backup of Zimbra Community Edition (ZCS) and minimize downtime is to put /opt/zimbra on a dedicate LVM volume.
The reason why you have to satisfy this requirement is that you cannot simply backup /opt/zimbra while Zimbra is running.
At the same time, creating a backup of a full Zimbra installation can take from several minutes to a few hours, depending on the size of your mailboxes and the resources of your server. This means that you cannot stop Zimbra, backup it and restart it as it would cause a huge downtime.
Making a snapshot of a LVM volume takes only a few seconds. All we have to do is:
- stop zimbra
- make a snapshot of the LVM volume mounted under /opt/zimbra
- start zimbra
- mount the snapshot on a temporary dir
- backup the temporary dir
- unmount the snapshot
- destroy the snapshot
You can find many examples of this procedure on Zimbra Wiki, but I wasn’t satisfied with any of them because they didn’t support incremental remote backups.
Duplicity is a nifty piece of software which can do either a full or incremental backup of a directory and store it on a local disk or on a remote storage, via ftp or scp.
duplicity is smart enough to detect when the last full backup was performed more than 1 month ago and will automatically switch from “incremental backup” to “full backup” in that case.
As a bonus it can also purge old backups automatically, without the need for additional scripting.
In my example, I use duplicity to do a remote backup via ftp.
I choose to use symmetrical encryption because I’m lazy. Asymmetrical encryption is supported too, though.
The script shall be run by cron everyday, as root. E.g.:
0 3 * * * /root/bin/backup-zimbra.sh
You need a little more than 2 GB of free disk space inside $TEMPDIR ! duplicity is smart enough to write one backup volume at a time (the size can be set in $VOLSIZE – in my example it’s 2GB), upload it, delete it, and then start writing the next backup volume. At any given time, your TEMPDIR will contain only a single 2GB backup volume.
SECURITY WARNING: in this example script, I put all passwords inside the script itself. Make sure to
chmod 700 and
chown root:root the script or any user will be able to download and decrypt your backups! Alternatively, you can move the configuration vars to an external file,
chmod 600 it and source it inside the script.
TEMPDIR=$(mktemp -dp /var/tmp zimbra-backup-XXXXX)
# what to backup, in my case: /dev/vgdata/mail
# snapshot name
# lvcreate and lvremove commands path
echo Backup started at `date`
# Stop the Zimbra services
echo "Stopping the Zimbra services..."
/etc/init.d/zimbra stop || exit
echo "Creating a snapshot called $LV_SNAP"
# depending on the time it takes to create the backup and the traffic of your server, you may need to increase the 2G value
$lvcreate_cmd -L2G -s -n $LV_SNAP /dev/$VG/$LV
# Create a mountpoint to mount the logical volume to
echo "Creating a mountpoint for the LV..."
mkdir -p $TEMPDIR/$LV_SNAP
# Mount the logical volume to the mountpoint
echo "Mounting the snapshot..."
# WARNING: if you use xfs you MUST add nouuid option here!
mount -o ro /dev/$VG/$LV_SNAP $TEMPDIR/$LV_SNAP/
# Start the Zimbra services
echo "Restarting the Zimbra services..."
/etc/init.d/zimbra start || echo "ERROR restarting zimbra"
# Create the current backup
DUPOPTS="-v$VERBOSE --full-if-older-than 1M --tempdir $TEMPDIR --exclude $TEMPDIR/$LV_SNAP/store/delme/ --allow-source-mismatch --volsize $VOLSIZE"
# Clean up incomplete backup archive files
$DUPLICITY cleanup --force -v$VERBOSE \
# remove old backup sets: keep only the last N full backups, where N is the value of $RETENTION
$DUPLICITY remove-all-but-n-full $RETENTION --force -v$VERBOSE \
# create new backup
$DUPLICITY $DUPOPTS \
# Unmount /tmp/$lv_zimbra and remove the logical volume
echo "Unmounting and removing the snapshot."
$lvremove_cmd --force /dev/$VG/$LV_SNAP
echo $lvremove_cmd /dev/$VG/$LV_SNAP
echo Zimbra backed up to $FTP_PATH on $FTP_HOST
echo Backup ended at `date`
Note: when you cut & paste the script, make sure the resulting file is in UNIX format.
Last update: 9 Aug 2010