Automated backup script

Hi All,

Recently we have implemented nightly backups of our Zammad instance.

I thought i would share the code for the backup script here if it may help others.

This is fed from the info from the posts below.
https://community.zammad.org/t/disable-email-via-api/9820
https://community.zammad.org/t/activate-maintenance-mode-via-rails/8067

event flow is as follows

backup initiated →
email channel disabled (currently only a single channel) →
enables maintenance mode →
does a full Zammad backup →
syncs the backup files, aswell as the email templates and the backup scripts directory to a remote server via SSH using RSYNC (will need to use key based auth) →
takes Zammad out of maintenance mode →
re-enables the email channel

The script also timestamps, and outputs all information to a log file that is also synced to the remote server.

Feel free to modify as needed. its pretty crude, i am no expert coder.

only dependency that is needed is JQ

sudo apt install -y jq

ours is inserted into CRON as below

1 23 * * * /home/zammad/backup_and_sync.sh >> /home/zammad/zammad_backup_log

main sh script
All that is needed is to edit the variables at the top specific to your environment.

#!/bin/bash

##########################################

Red='\033[0;31m'          # Red
Green='\033[0;32m'        # Green
Yellow='\033[0;33m'       # Yellow
NC='\033[0m'              # No Color

##########################################

zammad_server='<IP HERE>/api/v1/channels_email'
email_index='"id": <EMAIL ACCOUNT INDEX HERE>'
bearer_token='<API KEY HERE>'

backup_server='<IP HERE>'
backup_server_username='<BACKUP SERVER USERNAME HERE>'
backup_server_location='<LOCATION ON REMOTE SERVER WHERE TO SEND FILES TO HERE>'
backup_log='<LOCATION OF THE BACKUP LOG ON THE LOCAL ZAMMAD HOST HERE>'

json_query='.assets.Channel."<EMAIL ACCOUNT INDEX HERE>".active'

##########################################


echo -e "${Green}Zammad backup and sync process started${NC}" >> ${backup_log}
date  >> ${backup_log}
echo ''  >> ${backup_log}


echo -e "${Green}Disabling Email Chanels in Zammad${NC}" >> ${backup_log}
curl -s --request POST "${zammad_server}_disable" --header 'Content-Type: application/json' --header "Authorization: Bearer ${bearer_token}" --data-raw "{${email_index}}"
echo ''  >> ${backup_log}


echo -e "${Green}Validating Email channel state${NC}" >> ${backup_log}
curl -s --request GET "${zammad_server}" --header 'Content-Type: application/json' --header "Authorization: Bearer ${bearer_token}" | jq ${json_query} >> ${backup_log}
wait
echo ''  >> ${backup_log}


echo -e "${Green}Placing Zammad Server into Maintainence Mode${NC}" >> ${backup_log}
zammad run rails runner 'Setting.set("maintenance_mode", true)'
wait
echo ''  >> ${backup_log}


echo -e "${Green}Validating Maintenance Mode state${NC}" >> ${backup_log}
zammad run rails runner 'p Setting.get("maintenance_mode")' >> ${backup_log}
wait
echo ''  >> ${backup_log}


echo -e "${Green}Backup of the zammad database and saving its output to the backup log file${NC}"  >> ${backup_log}
/opt/zammad/contrib/backup/zammad_backup.sh  >> ${backup_log}
wait
echo ''  >> ${backup_log}


echo -e "${Green}Syncing the backup directory to the backup server${NC}"  >> ${backup_log}
rsync -avz --delete-before -e ssh zammad_backups/ ${backup_server_username}@${backup_server}:${backup_server_location}/backup_files  >> ${backup_log}
wait
echo ''  >> ${backup_log}


echo -e "${Green}Syncing the email templates backup directory to the backup server${NC}"  >> ${backup_log}
rsync -avz --delete-before -e ssh email_templates/ ${backup_server_username}@${backup_server}:${backup_server_location}/email_templates  >> ${backup_log}
wait
echo ''  >> ${backup_log}


echo -e "${Green}Syncing the Zammad Backup Scripts folder to the backup server${NC}"  >> ${backup_log}
rsync -avz --delete-before --exclude functions -e ssh /opt/zammad/contrib/backup/ ${backup_server_username}@${backup_server}:${backup_server_location}/zammad_scripts  >> ${backup_log}
wait
echo ''  >> ${backup_log}


echo -e "${Green}Placing Zammad Server back into Operational Mode${NC}" >> ${backup_log}
zammad run rails runner 'Setting.set("maintenance_mode", false)'
wait
echo ''  >> ${backup_log}


echo -e "${Green}Validating Maintenance Mode state${NC}" >> ${backup_log}
zammad run rails runner 'p Setting.get("maintenance_mode")' >> ${backup_log}
wait
echo ''  >> ${backup_log}


echo -e "${Green}Enabling Email Chanels in Zammad${NC}" >> ${backup_log}
curl -s --request POST "${zammad_server}_enable" --header 'Content-Type: application/json' --header "Authorization: Bearer ${bearer_token}" --data-raw "{${email_index}}"
wait
echo ''  >> ${backup_log}


echo -e "${Green}Validating Email channel state${NC}" >> ${backup_log}
curl -s --request GET "${zammad_server}" --header 'Content-Type: application/json' --header "Authorization: Bearer ${bearer_token}" | jq ${json_query} >> ${backup_log}
wait
echo ''  >> ${backup_log}


echo -e "${Green}Syncing the backup log file to the backup server${NC}"  >> ${backup_log}
rsync -avz -e ssh zammad_backup_log ${backup_server_username}@${backup_server}:${backup_server_location}  >> ${backup_log}
wait
echo ''  >> ${backup_log}

echo -e "${Green}Backup Process Complete${NC}"  >> ${backup_log}
date  >> ${backup_log}
echo ''  >> ${backup_log}
echo ''  >> ${backup_log}
echo ''  >> ${backup_log}
echo ''  >> ${backup_log}
echo ''  >> ${backup_log}
echo ''  >> ${backup_log}
2 Likes

Can you please share your exact configuration?
At least for default backup script behavior of the Zammad backup scripts you’re using as well, the following rsyncs technically are duplicates and thus not really needed. I’m sure you have that on your radar and thus configured your script accordingly. :slight_smile:

It would make this thread complete to an great alternative / extension of the existing methods.

that is it.

I have modified the mail templates to suit our organisation, so i back those up.

Other than that, I use the inbuilt zammad backup scripts; and the only other mods i have made are to the config file in /opt/zammad/contrib/backups that is relevant to our environment, hence why i also sync that to the remote server.

Like i said, im no coding expert, and its a bit hacky. but it works exactly as needed and logs everything to a log file that is also synced for auditing.

However, im open to options for making it better if available.

The backup scripts default behavior is to backup the complete /opt/zammad/ directory unless you tell the config not to. See: Backup configuration — Zammad documentation

You can check the actual file backup of your Zammad instance to double tab and ensure everything works as expected.

ahhh right, i understand, because its a full file system dump; the entire directory is included in it…

that makes sense.

Hmm, well in that case then, i guess just omit the other 2 syncs and you should be golden.

I will leave our production system as it, because it is working as expected, and there are documented procedures on our restore process. But thanks for pointing that out for me.

I will leave the script above as is, and available for anyone else who wants to use it for their own backup system.

3 Likes