Incremental backup of Zimbra on LVM volume with duplicity
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.
Welcome LVM.
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
Welcome duplicity.
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.#!/bin/bash LOGDIR="/var/log" TEMPDIR=$(mktemp -dp /var/tmp zimbra-backup-XXXXX) FTP_USER='myuser' FTP_PASSWORD='mypass' FTP_HOST='ftpserver.tld' PASSPHRASE='changeme' DUPLICITY='/usr/bin/duplicity' VERBOSE=5 RETENTION=3 VOLSIZE=2048 export FTP_PASSWORD export PASSPHRASE # what to backup, in my case: /dev/vgdata/mail VG=vgdata LV=mail # snapshot name LV_SNAP=ZimbraBackup # lvcreate and lvremove commands path lvcreate_cmd="/sbin/lvcreate" lvremove_cmd="/sbin/lvremove" 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 FTP_PATH=zimbra 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 \ ftp://$FTP_USER@$FTP_HOST/$FTP_PATH/$i >>/$LOGDIR/$FTP_PATH.log # 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 \ � ftp://$FTP_USER@$FTP_HOST/$FTP_PATH >>/$LOGDIR/$FTP_PATH # create new backup $DUPLICITY $DUPOPTS \ � $TEMPDIR/$LV_SNAP/ \ � ftp://$FTP_USER@$FTP_HOST/$FTP_PATH >>$LOGDIR/$FTP_PATH.log # Unmount /tmp/$lv_zimbra and remove the logical volume echo "Unmounting and removing the snapshot." umount /dev/$VG/$LV_SNAP $lvremove_cmd --force /dev/$VG/$LV_SNAP echo $lvremove_cmd /dev/$VG/$LV_SNAP # Done! 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