Zimbra FOSS User Backup

From vWiki
Jump to navigation Jump to search

The following script is a modified version of one that can found on the Zimbra Forum here by LHammonds - http://www.zimbra.com/forums/installation/53227-my-notes-installing-zimbra-7-1-3-ubuntu-server-10-04-3-lts-2.html#post230528. The post in general is effectively a start to finish account of getting Zimbra FOSS up and running in an enterprise environment. Its well worth browsing through the whole chain, it covers everything!

My script is still a work in progress, but so far I've made the following modifications

  • Added ability to FTP backup's off to remote server
    • Requires lftp, install with apt-get lftp
  • Added logging output to end of script email

The script performs an online backup of all user accounts, which you can perform daily (or even more frequently), and maybe perform a full offline backup weekly or monthly.

#!/bin/bash
########################################################################
# Name          : zm-user-backup.sh
# Version       : 0.2
# Date          : 2011-10-29
# Author        : LHammonds
# Modifier      : SStrutt
# Compatibility : Ubuntu 10.04.3 LTS, Zimbra 7.1.2 - 7.1.3
# Purpose       : Backup individual mailbox accounts.
# Exit Codes    : (if multiple errors, value is the addition of codes)
#   0 = success
#   1 = failure
################ CHANGE LOG ##########################################
# DATE       WHO WHAT WAS CHANGED
# ---------- --- ----------------------------
# 2011-10-23 LTH Created script.
# 2011-10-29 LTH Various improvements. (yes, I forgot what)
# 2012-03-01 SSS Added remote FTPS option (requires lftp, backup retained locally for 5 days)
#		 Updated logging to log to email,
#####################################################################
# TO DO !!
# Add time-out to lftp command
# Improve error detection/handling around user export
# Add mechanism to allow monitoring of sucess.failure by Nagios

# Email notification options
EMAILFROM="admin@domain.com"
EMAILTO="someone@domain.com"

# Email account NOT to backup
EXCEPTIONS="spam.t1ml2qhoo@domain.com;ham.w5adcmdphn@domain.com;virus-quarantine.lzab8c2m_@domain.com"

# Paths and file defs, probably nothing for you to change
TEMPDIR="/backup"
LOGFILE="${TEMPDIR}/zm-user-backup.log"
SOURCEDIR="/opt/zimbra"
TARGETDIR="${TEMPDIR}/zmusers"
ARCHIVEFILE="`date +%Y-%m-%d_%H-%M`_zmusers.tar"
MAILFILE="${TEMPDIR}/zm-user-backup-mail.$$"
MAILLOG="${TEMPDIR}/zm-user-backup-mail-log.$$"
FTPLOG="${TEMPDIR}/zm-user-backup-ftp-log.$$"

# Remote NFS mount
REMOTESITE="/mnt/zmbackup"
REMOTETESTFILE="${REMOTESITE}/online.txt"

# Remote FTPS server
FTP="yes"				# To FTP or not to FTP, if no, copy to NFS will be performed
FTPSERVER="ftp.domain.com"		# FTP server to copy backup to
FTPUSER="backup"			# FTP account username
FTPPASS="backup"			# FTP account password
FTPDIR="/backups/mail"			# Directory on FTP server to place backup into

# Nothing to change here, move along
HOSTNAME=$(hostname -f)
SCRIPTNAME=${0}
RETURNVALUE=0
UCOUNT=0
ERRORFLAG=0

#######################################
##            FUNCTIONS              ##
#######################################

function f_sendmail()
{
  # Purpose: Send email message.
  # Parameter #1 = Subject
  # Parameter #2 = Body
  echo "From: ${EMAILFROM}" > ${MAILFILE}
  echo "To: ${EMAILTO}" >> ${MAILFILE}
  echo "Subject: ${1}" >> ${MAILFILE}
  echo "" >> ${MAILFILE}
  echo ${2} >> ${MAILFILE}
  echo "" >> ${MAILFILE}
  cat ${MAILLOG} >> ${MAILFILE}
  echo "" >> ${MAILFILE}
  cat ${FTPLOG} >> ${MAILFILE}
  echo "" >> ${MAILFILE}
  echo "Server: ${HOSTNAME}, Program: ${SCRIPTNAME}" >> ${MAILFILE}
  ${SOURCEDIR}/postfix/sbin/sendmail -t < ${MAILFILE}
}

function f_cleanup()
{
  rm ${MAILFILE}
  rm ${MAILLOG}
  rm ${FTPLOG}
  # Remove backup's older then 5 days
  find ${TEMPDIR}/*.tar -mtime +5 -exec rm {} \;
}

function f_log()
{
  # Handles logging of messages
  # Parameter #1 = Log Message
  STAMP=`date '+%Y-%m-%d %H:%M:%S'`
  echo "${STAMP} ${1}"
  echo "${STAMP} ${1}" >> ${LOGFILE}
  echo "${STAMP} ${1}" >> ${MAILLOG}
}


#######################################
##           MAIN PROGRAM            ##
#######################################

echo "---------------------------------------------------" >> ${LOGFILE}
f_log "- zm user backup started."
if [ -d "${TARGETDIR}" ]; then
  # Purge existing archives.
  rm ${TARGETDIR}/*.tgz 1>/dev/null 2>&1
else
  # Make the folder if it does not exist.
  mkdir -p ${TARGETDIR} 1>/dev/null 2>&1
fi
f_log "-- Getting list of user accounts"
for ACCT in `su - zimbra -c "zmprov -l gaa"`
do
  # Check to see if current account should be skipped.
  if echo "${EXCEPTIONS}" | grep -q ${ACCT}
  then
    # Exception found, skip this account.
    echo "" > /dev/null
  else
    # Backup user account.
    UCOUNT=$((UCOUNT+1))
    f_log "--- Backing up user ${ACCT}"
    ${SOURCEDIR}/bin/zmmailbox -z -m ${ACCT} getRestURL "//?fmt=tgz" > ${TARGETDIR}/${ACCT}.tgz
    RETURNVALUE=$?
    if [ ! ${RETURNVALUE} -eq 0 ]; then
      # Something went wrong.
      f_log "---- Error on ${ACCT}, exit code ${RETURNVALUE}"
      ERRORFLAG=$((ERRORFLAG+1))
    fi
  fi
done
f_log "-- ${UCOUNT} accounts processed."

# Comment out the below line if you do not want to receive statistic emails.
#f_sendmail "Zimbra User Mailbox Backup" "${UCOUNT} accounts backed up."

f_log "--- Setting file permissions on ${TARGETDIR}/*.tgz"
chmod 0600 ${TARGETDIR}/*.tgz
f_log "--- Creating a single archive ${TEMPDIR}/${ARCHIVEFILE}"
tar -cf ${TEMPDIR}/${ARCHIVEFILE} ${TARGETDIR} 1>/dev/null 2>&1
RETURNVALUE=$?
if [ ! "${RETURNVALUE}" -eq "0" ]; then
  # Something went wrong.
  f_log "--- Error creating ${TEMPDIR}/${ARCHIVEFILE}, Return Value: ${RETURNVALUE}"
  ERRORFLAG=$((ERRORFLAG+1))
fi

if [ "$FTP" = "yes" ]
then
        # Do FTPS copy to FTP site
        f_log "-- Starting FTPS copy to ${FTPSERVER}"
        lftp -u ${FTPUSER},${FTPPASS} -e "set ftp:ssl-force true,ftp:ssl-protect-data true,net:max-retries 5; cd ${FTPDIR}; put ${TEMPDIR}/${ARCHIVEFILE}; exit" ${FTPSERVER}
        RETURNVALUE=$?
        if [ "${RETURNVALUE}" == "0" ]
        then
                f_log "--- FTPS upload completed successfully"
        else
                f_log "--- FTPS upload FAILED, exit code ${RETURNVALUE}"
                ERRORFLAG=$((ERRORFLAG+1))
        fi
else
        # Do copy to remote file store

        if [ -f ${TEMPDIR}/${ARCHIVEFILE} ]; then
          # Copy archive to remote site.
          if [ -f ${REMOTETESTFILE} ]; then
            # Remote site is online / available.
            cp ${TEMPDIR}/${ARCHIVEFILE} ${REMOTESITE}/${ARCHIVEFILE} 1>/dev/null 2>&1
          else
            # Remote site is offline / unavailable.
            f_log "--- Error: Remote site is unavailable: ${REMOTESITE}"
            ERRORFLAG=$((ERRORFLAG+1))
          fi
        fi

        if [ -f ${REMOTESITE}/${ARCHIVEFILE} ]; then
          # Remote copy worked.  Remove local archive.
          rm ${TEMPDIR}/${ARCHIVEFILE}

          # Uncomment the following 2 lines if you do not wish to have a local copy of individual mailboxes.
          #rm ${TARGETDIR}/*.tgz
          #rmdir ${TARGETDIR}
        else
          # Remote copy failed.
          f_log "--- Error creating ${TEMPDIR}/${ARCHIVEFILE}, Return Value: ${RETURNVALUE}"
          ERRORFLAG=$((ERRORFLAG+1))
        fi
fi

f_log "- zm user backup complete. exit code: ${ERRORFLAG}"

if [ "${ERRORFLAG}" -ne "0" ]; then
  f_sendmail "Zimbra Mailbox Backup Error - ${HOSTNAME}" "${ERRORFLAG} errors detected in ${HOSTNAME} ${SCRIPTNAME}"<${MAILLOG}
else
  f_sendmail "Zimbra User Mailbox Backup - ${HOSTNAME}" "${UCOUNT} accounts backed up."<${MAILLOG}
fi

# Perform cleanup routine.
f_cleanup
# Exit with the combined return code value.
exit ${ERRORFLAG}