#!/bin/bash ## File: cloud_backup.sh ## This automates backup of your nextcloud. ## Run as a backup user with the group rights of www-data and the ricght to sudo as that user. ## Within mariadb an user should exist, which has read permissions to everything, but only that! source ~/.config/cloud_backup.conf ## Returns the binaries full path if existent. function which_is() { declare -n RETVAL=$1; # declare RETVAL a reference of $1 local EXECUTABLE=$2; local WITHFULLPATH=$(which ${EXECUTABLE} 2>/dev/null); if [ -x "$WITHFULLPATH" ]; then RETVAL="$WITHFULLPATH"; return 0; else RETVAL="$EXECUTABLE not found!"; return 1; fi } ## Log levels for messages LLMUTE=0 LLMDTRY=1 LLERROR=2 LLWARNING=3 LLINFO=4 LLDEBUG=5 ## Actual log level of the logger used LOGLEVEL=$LLDEBUG ## Write log of the script function logger() { local LOGGINGLEVEL=$1; local LOGMESSAGE=$2; local _NOW=$($DATE +%Y%m%d_%H:%M:%S); if [[ $LOGLEVEL -ge $LOGGINGLEVEL ]]; then echo "cloud_backup $_NOW: ${LOGMESSAGE}" >> $LOGFILE; fi if [[ $LOGLEVEL -eq $LLDEBUG ]]; then echo "cloud_backup $_NOW: ${LOGMESSAGE}"; fi } ## updates nextcloud files cache for a given path ## $1 Path to update nextcloud filescache on. ## Attention: path is relative to nextcloud data folder without '/'! ## return 0 in case of success, 1 on fail. update_filescache() { local CLOUDPATH=$1; logger $LLINFO "Updating file cache for $CLOUDPATH."; logger $LLDEBUG "$SUDO -u www-data $PHP ${CONFIG_NC_BASE}occ files:scan --path=\"$CLOUDPATH\""; $SUDO -u www-data $PHP ${CONFIG_NC_BASE}occ files:scan --path="$CLOUDPATH"; return $?; } ## Cleanup and exit with exit value given. function clean_up() { local EXITVAL=$1; logger $LLINFO "Cleaning up on exit $EXITVAL."; # re-enable the cloud under all circumstances! logger $LLINFO "Re-enabling cloud, switching maintenance mode off."; $SUDO -u www-data $PHP ${CONFIG_NC_BASE}occ maintenance:mode --off; logger $LLINFO "Making log file $CONFIG_NC_LOGPATH visible to cloud."; update_filescache ${CONFIG_NC_LOGPATH}; # make logfile visible in cloud if [ $? -ne 0 ]; then logger $LLWARNING "Could not update files cache of nextcloud!"; fi logger $LLMDTRY "Exiting on $EXITVAL."; exit $EXITVAL; } #echo "Levels $LLMUTE $LLMDTRY $LLERROR $LLWARNING $LLINFO $LLDEBUG Loglevel: $LOGLEVEL"; ## Check binaries availability which_is SUDO 'sudo'; if [ $? -ne 0 ]; then echo $SUDO; exit 1; fi which_is DATE 'date'; if [ $? -ne 0 ]; then echo $DATE; exit 1; fi which_is MYSQLDUMP 'mysqldump'; if [ $? -ne 0 ]; then echo $MYSQLDUMP; exit 1; fi which_is RSYNC 'rsync'; if [ $? -ne 0 ]; then echo $RSYNC; exit 1; fi which_is LN 'ln'; if [ $? -ne 0 ]; then echo $LN; exit 1; fi which_is RM 'rm'; if [ $? -ne 0 ]; then echo $RM; exit 1; fi which_is SSH 'ssh'; if [ $? -ne 0 ]; then echo $SSH; exit 1; fi which_is PHP 'php'; if [ $? -ne 0 ]; then echo $PHP; exit 1; fi which_is TOUCH 'touch' if [ $? -ne 0 ]; then echo $TOUCH; exit 1; fi which_is CHOWN 'chown' if [ $? -ne 0 ]; then echo $CHOWN; exit 1; fi # Add slash to paths if missing if [ "${BACKUP_TARGET:${#BACKUP_TARGET}-1:1}" != "/" ]; then BACKUP_TARGET=$BACKUP_TARGET/ fi if [ "${CONFIG_NC_DATA:${#CONFIG_NC_DATA}-1:1}" != "/" ]; then CONFIG_NC_DATA=$CONFIG_NC_DATA/ fi if [ "${CONFIG_NC_BASE:${#CONFIG_NC_BASE}-1:1}" != "/" ]; then CONFIG_NC_BASE=$CONFIG_NC_BASE/ fi if [ "${CONFIG_NC_LOGPATH:${#CONFIG_NC_LOGPATH}-1:1}" != "/" ]; then CONFIG_NC_LOGPATH=$CONFIG_NC_LOGPATH/ fi ## Logfile in nextcloud to have a visible result. RUNDATE=$($DATE +%Y_%m_%d) LOGFILE="$CONFIG_NC_DATA$CONFIG_NC_LOGPATH${RUNDATE}_cloudbackup.log"; $TOUCH ${LOGFILE}; if [ $? -ne 0 ]; then echo "Could not create log file! exiting."; exit 1; fi logger $LLINFO "Chown logfile $LOGFILE."; $CHOWN :www-data ${LOGFILE}; if [ $? -ne 0 ]; then logger $LLWARNING "Cloud not set group ownership of log file."; # The logfile may not appaer in the clouds dedicated folder. exit 1; fi logger $LLINFO "Making log file $CONFIG_NC_LOGPATH visible to cloud."; update_filescache $CONFIG_NC_LOGPATH; # make logfile visible in cloud if [ $? -ne 0 ]; then logger $LLWARNING "Could not update files cache of nextcloud!"; fi TODAY=$($DATE +%y%m%d_%H%M) logger $LLMDTRY "Starting backup for ${TODAY}."; ## Let nextcloud enter maintenance mode logger $LLDEBUG "$SUDO -u www-data $PHP ${CONFIG_NC_BASE}occ maintenance:mode --on;"; logger $LLINFO "Enabling maintenance mode of nextcloud."; $SUDO -u www-data $PHP ${CONFIG_NC_BASE}occ maintenance:mode --on; if [[ "$?" != "0" ]]; then logger $LLERROR "Setting nextcloud maintenance mode failed!"; clean_up 1; fi ## Dump mariadb logger $LLDEBUG "$MYSQLDUMP --single-transaction -h ${CONFIG_NC_DB_SERVER} -u ${CONFIG_NC_DB_USER} -p${CONFIG_NC_DB_PASSWD} ${CONFIG_NC_DB_NAME} > $CONFIG_NC_DATA/${TODAY}_nextcloud.sqlbkp;"; logger $LLINFO "Dumping nextcloud database."; $MYSQLDUMP --single-transaction -h ${CONFIG_NC_DB_SERVER} -u ${CONFIG_NC_DB_USER} ${CONFIG_NC_DB_NAME} > $CONFIG_NC_DATA/${TODAY}_nextcloud.sqlbkp; if [[ "$?" != "0" ]]; then logger $LLERROR "Dump of the nextcloud database failed!"; clean_up 1; fi ## Connect to Borg Repo and backup the: ## - config folder, ## - data folder, ## - theme folder, ## - dumped database # Simple backup with rsync # local-mode, tossh-mode, fromssh-mode ### do not edit ### RSYNCCONF=(--delete) LAST="last"; INC="--link-dest=$BACKUP_TARGET$LAST" if [ "$SSHUSER" ] && [ "$SSHPORT" ]; then S="$SSH -p $SSHPORT -l $SSHUSER"; else logger $LLERROR "Invalid ssh command, port or user: »$SSH« »$SSHPORT« «$SSHUSER«"; clean_up 1; fi for SOURCE in "${BACKUP_SOURCES[@]}"; do logger $LLDEBUG "$RSYNC -e $S --exclude-from=$CONFIG_EXCLUDE -avR $SOURCE ${RSYNCCONF[@]} $TOSSH:$BACKUP_TARGET$TODAY $INC"; logger $LLINFO "Rsyncing $SOURCE."; $RSYNC -e "$S" --exclude-from=$CONFIG_EXCLUDE -avR "$SOURCE" "${RSYNCCONF[@]}" "$TOSSH:$BACKUP_TARGET$TODAY" $INC; if [ $? -ne 0 ]; then logger $LLERROR "Rsync of $SOURCE failed!"; fi done if [ "$S" ] && [ "$TOSSH" ] && [ -z "$FROMSSH" ]; then logger $LLDEBUG "$S $TOSSH $LN -nsf $BACKUP_TARGET$TODAY $BACKUP_TARGET$LAST"; logger $LLINFO "Setting Link to last to »$BACKUP_TARGET$TODAY«"; $S $TOSSH "$LN -nsf $BACKUP_TARGET$TODAY $BACKUP_TARGET$LAST"; if [ $? -ne 0 ]; then logger $LLERROR "Resetting link to last backup of todays failed!"; clean_up 1; fi fi logger $LLMDTRY "Backup of nextcloud done, cleaning up."; #if [[ "$?" != "0" ]]; then $(logger 1 "Borgbackup of the nextcloud data folder failed!"); exit 1; fi #if [[ "$?" != "0" ]]; then $(logger 1 "Borgbackup of the nextcloud database failed!"); exit 1; fi ## End maintenance mode of nextcloud end exit 0 clean_up 0; ## EOF