#!/bin/bash # # Federated Backup / Restore Tool to B2 Backblaze . /federated/lib/functions.sh usage() { cat << EOF Backup to Backblaze Usage: $0 [options] service Arguments: service Service to backup or 'all' for all services Options -l List files in a backup -b Perform backup of a service -d Delete backups of a service -r Restore a backup of a service EOF exit 2; } createbucket() { if [ ! -f "/federated/bin/.b2init" ]; then B2_APPLICATION_KEY_ID="$B2_APPLICATION_KEY_ID" B2_APPLICATION_KEY="$B2_APPLICATION_KEY" /federated/bin/b2-linux create_bucket $UUID allPrivate echo "$UUID" > /federated/bin/.b2init fi } listbackup() { if [ "$SERVICE" = "all" ]; then echo "* Listing backup files in all services.." for i in "${SERVICES[@]}"; do echo "* Listing backup files in $i.." PASSPHRASE=$GPG_PASSPHRASE duplicity list-current-files b2://$B2_APPLICATION_KEY_ID:$B2_APPLICATION_KEY@$UUID/$i/ done else echo "* Listing backup files in $SERVICE.." PASSPHRASE=$GPG_PASSPHRASE duplicity list-current-files b2://$B2_APPLICATION_KEY_ID:$B2_APPLICATION_KEY@$UUID/$SERVICE/ fi } backupservice() { echo "* Backing up $SERVICE.." # Dump only users and roles for postgresql service if [ "$SERVICE" = "postgresql" ]; then docker exec postgresql /bin/bash -c "pg_dumpall --globals-only -c -U postgres | gzip -9 > /docker-entrypoint-initdb.d/dump_$SERVICE.sql.gz" PASSPHRASE=$GPG_PASSPHRASE duplicity /federated/apps/$SERVICE b2://$B2_APPLICATION_KEY_ID:$B2_APPLICATION_KEY@$UUID/$SERVICE/ rm /federated/apps/postgresql/data/docker-entrypoint-initdb.d/dump_* elif [ "$SERVICE" = "pdnsmysql" ]; then docker exec -it pdnsmysql mysqldump -uroot -p${MYSQL_PASSWORD} mysql user | gzip -9 > /federated/apps/pdnsmysql/dump_$SERVICE.sql.gz PASSPHRASE=$GPG_PASSPHRASE duplicity /federated/apps/$SERVICE b2://$B2_APPLICATION_KEY_ID:$B2_APPLICATION_KEY@$UUID/$SERVICE/ rm /federated/apps/pdnsmysql/dump_$SERVICE.sql.gz elif [ "$SERVICE" = "pdns" ]; then docker exec -it pdnsmysql mysqldump -uroot -p${MYSQL_PASSWORD} pdns | gzip -9 > /federated/apps/pdns/dump_$SERVICE.sql.gz PASSPHRASE=$GPG_PASSPHRASE duplicity /federated/apps/$SERVICE b2://$B2_APPLICATION_KEY_ID:$B2_APPLICATION_KEY@$UUID/$SERVICE/ rm /federated/apps/pdns/dump_$SERVICE.sql.gz elif [ "$SERVICE" = "pdnsadmin" ]; then docker exec -it pdnsmysql mysqldump -uroot -p${MYSQL_PASSWORD} pdns | gzip -9 > /federated/apps/pdnsadmin/dump_$SERVICE.sql.gz PASSPHRASE=$GPG_PASSPHRASE duplicity /federated/apps/$SERVICE b2://$B2_APPLICATION_KEY_ID:$B2_APPLICATION_KEY@$UUID/$SERVICE/ rm /federated/apps/pdnsadmin/dump_$SERVICE.sql.gz elif [ "$SERVICE" = "castopod" ]; then docker exec -it pdnsmysql mysqldump -uroot -p${MYSQL_PASSWORD} castopod | gzip -9 > /federated/apps/castopod/dump_$SERVICE.sql.gz PASSPHRASE=$GPG_PASSPHRASE duplicity /federated/apps/$SERVICE b2://$B2_APPLICATION_KEY_ID:$B2_APPLICATION_KEY@$UUID/$SERVICE/ rm /federated/apps/castopod/dump_$SERVICE.sql.gz elif [ "$SERVICE" = "wordpress" ]; then docker exec -it pdnsmysql mysqldump -uroot -p${MYSQL_PASSWORD} wordpress | gzip -9 > /federated/apps/wordpress/dump_$SERVICE.sql.gz PASSPHRASE=$GPG_PASSPHRASE duplicity /federated/apps/$SERVICE b2://$B2_APPLICATION_KEY_ID:$B2_APPLICATION_KEY@$UUID/$SERVICE/ rm /federated/apps/wordpress/dump_$SERVICE.sql.gz elif [ "$SERVICE" = "bookstack" ]; then docker exec -it pdnsmysql mysqldump -uroot -p${MYSQL_PASSWORD} bookstack | gzip -9 > /federated/apps/bookstack/dump_$SERVICE.sql.gz PASSPHRASE=$GPG_PASSPHRASE duplicity /federated/apps/$SERVICE b2://$B2_APPLICATION_KEY_ID:$B2_APPLICATION_KEY@$UUID/$SERVICE/ rm /federated/apps/bookstack/dump_$SERVICE.sql.gz else # For all other services, If the postgresql database exists for that service then dump it docker exec -it postgresql psql -U $SERVICE -c '\q' &>/dev/null if [ $? -eq 0 ]; then docker exec postgresql /bin/bash -c "pg_dump $SERVICE -c -U postgres | gzip -9 > /docker-entrypoint-initdb.d/dump_$SERVICE.sql.gz" mv /federated/apps/postgresql/data/docker-entrypoint-initdb.d/dump_$SERVICE.sql.gz /federated/apps/$SERVICE/ fi PASSPHRASE=$GPG_PASSPHRASE duplicity /federated/apps/$SERVICE b2://$B2_APPLICATION_KEY_ID:$B2_APPLICATION_KEY@$UUID/$SERVICE/ [ -f "/federated/apps/$SERVICE/dump_$SERVICE.sql.gz" ] && rm /federated/apps/$SERVICE/dump_$SERVICE.sql.gz fi } backupserviceall() { echo "* Backing up all services.." for i in "${SERVICES[@]}"; do echo "** Backing up $i.." if [ "$i" = "postgresql" ]; then docker exec postgresql /bin/bash -c "pg_dumpall --globals-only -c -U postgres | gzip -9 > /docker-entrypoint-initdb.d/dump_$i.sql.gz" PASSPHRASE=$GPG_PASSPHRASE duplicity /federated/apps/$i b2://$B2_APPLICATION_KEY_ID:$B2_APPLICATION_KEY@$UUID/$i/ rm /federated/apps/postgresql/data/docker-entrypoint-initdb.d/dump_* elif [ "$i" = "pdnsmysql" ]; then docker exec -it pdnsmysql mysqldump -uroot -p${MYSQL_PASSWORD} mysql user | gzip -9 > /federated/apps/pdnsmysql/dump_$i.sql.gz PASSPHRASE=$GPG_PASSPHRASE duplicity /federated/apps/$i b2://$B2_APPLICATION_KEY_ID:$B2_APPLICATION_KEY@$UUID/$i/ rm /federated/apps/pdnsmysql/dump_$i.sql.gz elif [ "$i" = "pdns" ]; then docker exec -it pdnsmysql mysqldump -uroot -p${MYSQL_PASSWORD} pdns | gzip -9 > /federated/apps/pdns/dump_$i.sql.gz PASSPHRASE=$GPG_PASSPHRASE duplicity /federated/apps/$i b2://$B2_APPLICATION_KEY_ID:$B2_APPLICATION_KEY@$UUID/$i/ rm /federated/apps/pdns/dump_$i.sql.gz elif [ "$i" = "pdnsadmin" ]; then docker exec -it pdnsmysql mysqldump -uroot -p${MYSQL_PASSWORD} pdns | gzip -9 > /federated/apps/pdnsadmin/dump_$i.sql.gz PASSPHRASE=$GPG_PASSPHRASE duplicity /federated/apps/$i b2://$B2_APPLICATION_KEY_ID:$B2_APPLICATION_KEY@$UUID/$i/ rm /federated/apps/pdnsadmin/dump_$i.sql.gz elif [ "$i" = "castopod" ]; then docker exec -it pdnsmysql mysqldump -uroot -p${MYSQL_PASSWORD} castopod | gzip -9 > /federated/apps/castopod/dump_$i.sql.gz PASSPHRASE=$GPG_PASSPHRASE duplicity /federated/apps/$i b2://$B2_APPLICATION_KEY_ID:$B2_APPLICATION_KEY@$UUID/$i/ rm /federated/apps/castopod/dump_$i.sql.gz elif [ "$i" = "wordpress" ]; then docker exec -it pdnsmysql mysqldump -uroot -p${MYSQL_PASSWORD} wordpress | gzip -9 > /federated/apps/wordpress/dump_$i.sql.gz PASSPHRASE=$GPG_PASSPHRASE duplicity /federated/apps/$i b2://$B2_APPLICATION_KEY_ID:$B2_APPLICATION_KEY@$UUID/$i/ rm /federated/apps/wordpress/dump_$i.sql.gz elif [ "$i" = "bookstack" ]; then docker exec -it pdnsmysql mysqldump -uroot -p${MYSQL_PASSWORD} bookstack | gzip -9 > /federated/apps/bookstack/dump_$i.sql.gz PASSPHRASE=$GPG_PASSPHRASE duplicity /federated/apps/$i b2://$B2_APPLICATION_KEY_ID:$B2_APPLICATION_KEY@$UUID/$i/ rm /federated/apps/bookstack/dump_$i.sql.gz else docker exec -it postgresql psql -U $i -c '\q' &>/dev/null if [ $? -eq 0 ]; then docker exec postgresql /bin/bash -c "pg_dump $i -c -U postgres | gzip -9 > /docker-entrypoint-initdb.d/dump_$i.sql.gz" mv /federated/apps/postgresql/data/docker-entrypoint-initdb.d/dump_$i.sql.gz /federated/apps/$i/ fi PASSPHRASE=$GPG_PASSPHRASE duplicity /federated/apps/$i b2://$B2_APPLICATION_KEY_ID:$B2_APPLICATION_KEY@$UUID/$i/ [ -f "/federated/apps/$i/dump_$i.sql.gz" ] && rm /federated/apps/$i/dump_$i.sql.gz fi done } deletebackup() { mkdir -p /federated/tmp/empty cd /federated/tmp/empty && /federated/bin/b2-linux sync --allowEmptySource --delete . b2://$UUID/$SERVICE/ cd /federated && rm -rf /federated/tmp/empty } restorebackup() { echo "* Restoring $SERVICE.." PASSPHRASE=$GPG_PASSPHRASE duplicity --force b2://$B2_APPLICATION_KEY_ID:$B2_APPLICATION_KEY@$UUID/$SERVICE/ /federated/apps/$SERVICE } restorebackupall() { echo "* Restoring all services.." for i in "${SERVICES[@]}"; do echo "** Restoring $i.." PASSPHRASE=$GPG_PASSPHRASE duplicity --force b2://$B2_APPLICATION_KEY_ID:$B2_APPLICATION_KEY@$UUID/$i/ /federated/apps/$i done } while getopts "lbdr" OPTION; do case $OPTION in l) LIST_BACKUP="true"; ;; b) RUN_BACKUP="true"; ;; d) RUN_DELETE="true"; ;; r) RUN_RESTORE="true"; ;; *) usage; exit 2; esac done if [ $# -ne 2 ]; then usage; fi SERVICE=$2 if [ -f "/federated/bin/.gpg.backblaze" ]; then GPG_PASSPHRASE=`cat /federated/bin/.gpg.backblaze` else GPG_PASSPHRASE=$(create_password); echo "$GPG_PASSPHRASE" > /federated/bin/.gpg.backblaze fi if [ -f "/etc/federated" ]; then . /etc/federated [ -z "$B2_APPLICATION_KEY_ID" ] && failcheck "/etc/federated doesn't include B2_APPLICATION_KEY_ID for backups" [ -z "$B2_APPLICATION_KEY" ] && failcheck "/etc/federated doesn't include B2_APPLICATION_KEY for backups" [ -z "$DOMAIN" ] && failcheck "/etc/federated doesn't include DOMAIN for backups" UUID=`cat /etc/federated | grep DOMAIN | awk -F\. '{ print $1 }' | awk -F\" '{ print $2 }'` else failcheck "Could not find an /etc/federated file." fi [ -f "/federated/bin/.b2init" ] && UUID=`cat /federated/bin/.b2init` [ $LIST_BACKUP ] && listbackup [ $RUN_DELETE ] && deletebackup MYSQL_PASSWORD=`cat /federated/apps/pdnsmysql/.env | grep MYSQL_ROOT_PASSWORD | awk -F= '{ print $2 }'` if [ $RUN_RESTORE ]; then if printf '%s\0' "${SERVICES[@]}" | grep -Fxqz -- "$SERVICE"; then restorebackup elif [ "$SERVICE" = "all" ]; then restorebackupall else failcheck "$SERVICE is not a valid service" fi fi if [ $RUN_BACKUP ]; then if printf '%s\0' "${SERVICES[@]}" | grep -Fxqz -- "$SERVICE"; then createbucket backupservice elif [ "$SERVICE" = "all" ]; then createbucket backupserviceall else failcheck "$SERVICE is not a valid service" fi fi