diff --git a/backup-Wordpress.sh b/backup-Wordpress.sh index d26f1ee..00b4b03 100755 --- a/backup-Wordpress.sh +++ b/backup-Wordpress.sh @@ -1,22 +1,31 @@ -#!/bin/sh - -# Create DB backup in the given location - # wp db export downloads/`date +%Y%m%d`_database.sql --add-drop-table --path=/var/www/upakhyana.com/htdocs/ - # - Where to keep the db backups? - -# Do Backup of the WP files + logfiles + Db Backup files - # - Borg - run it on lower priority with "nice" - # Compression? zlib? - # Pruning? - # Max size? - # Frequency? - # What needs to be excluded? - +#!/bin/bash # Sync the backup to remote using Rclone # How about backup filling up space? # What if the server gets hacked - can he delete everything from remote location as well? +# TODO + # Display the archive name at the end + # Display the log location at start AND at end + # Check if we can avoid sudo - passphrase in user's .config dir + # Keyshortcuts for + # easily list the archives + # Mount an archive + # Health check + +# TODO - Accept the following mandatory parameters + # --project-name | -pname + # --wp-source-dir | -wp_src + # --backup-dir + ## Will be created if it does not exists +# And the following optional parameters + # --storage-quota | -quota + + +# TODO - Check on other OSes + # Ubuntu 16, 18, 18.08 + # Debian 8, 9, 10 + # So root - no good [[ "$(id -u)" != "0" ]] && { echo -e "ERROR: You must be root to run this script.\nPlease login as root and execute the script again." @@ -26,19 +35,27 @@ SCRIPT_NAME=wp_borg_backup SCRIPT_VERSION=0.1 -wp_src_dir="" -wp_log_dir="" -backup_dst_dir="" -borg_passphrase="" -storage_quota="5G" #if user provided - update this -project_name="" +project_name="$1" +wp_src_dir="$2" +backup_dst_dir="$3" + +storage_quota="5G" #if user provided - update this + +# Create the backup directory if it does not exist +mkdir -pv "${backup_dst_dir}"/{bkp_log,DB,WP} > /dev/null +bkp_log_dir="${backup_dst_dir}/bkp_log" +bkp_final_dir="${backup_dst_dir}/WP" +bkp_DB_dir="${backup_dst_dir}/DB" TS=$(date '+%d_%m_%Y-%H_%M_%S') -LOGFILE=/tmp/"$SCRIPT_NAME"_v"$SCRIPT_VERSION"_"$TS".log + +LOGFILE="${bkp_log_dir}"/"$SCRIPT_NAME"_v"$SCRIPT_VERSION"_"$TS".log +touch "${LOGFILE}" + # Install "borgbackup" if NOT installed -if ! type borg 2>> "$LOGFILE" >&2; then - apt-get install -y borgbackup 2>> "$LOGFILE" >&2 +if ! (type borg > /dev/null 2>&1); then + apt-get install -y borgbackup >> "$LOGFILE" 2>&1 fi #If borg is running the same backup - quit @@ -48,50 +65,88 @@ if (pidof -x borg > /dev/null) && $(pgrep -ac "$wp_src_dir") -gt 0 ; then exit 11 fi -# Backup the DB -if [[ -d ${backup_dst_dir}/DB ]]; then - mkdir ${backup_dst_dir}/DB 2>> "$LOGFILE" >&2 -fi - # Install wp-cli if not installed -if ! type wp 2>> "$LOGFILE" >&2; then - echo -e "wp-cli not found on system. \nInstalling wp-cli" 2>> "$LOGFILE" >&2 - wget https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar -O /usr/local/bin/wp 2>> "$LOGFILE" >&2 - chmod +x /usr/local/bin/wp 2>> "$LOGFILE" >&2 +if ! (type wp > /dev/null 2>&1); then + echo -e "wp-cli not found on system. \nInstalling wp-cli" >> "$LOGFILE" 2>&1 + wget https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar -O /usr/local/bin/wp >> "$LOGFILE" 2>&1 + chmod +x /usr/local/bin/wp >> "$LOGFILE" 2>&1 fi # Backup WP database -wp db export ${backup_dst_dir}/DB/"$TS"_database.sql --add-drop-table --path=${wp_src_dir} 2>> "$LOGFILE" >&2 +directory_owner=$(ls -ld "${wp_src_dir}" | awk '{print $3}') +sudo -u "${directory_owner}" wp db --quiet export "${wp_src_dir}"/"$TS"_database.sql --add-drop-table --path="${wp_src_dir}" -# If no passphrase provided and repo exists at the destination - Exit -if [[ ( -z "$borg_passphrase") && (-f "$backup_dst_dir"/config || -d "$backup_dst_dir"/WP || -d "$backup_dst_dir"/WP/config) ]]; then - echo -e "You did not provide passphrase for this existing backup.\nProcess will exit now." | tee -a "$LOGFILE" +if mv "${wp_src_dir}"/"${TS}"_database.sql "${bkp_DB_dir}"/"${TS}"_database.sql >> "$LOGFILE" 2>&1; then + echo "DB backed up successfully" | tee -a "$LOGFILE" +else + echo "ERROR: DB Backup Failed. Check log for more details." | tee -a "$LOGFILE" +fi + +# Try reading the passphrase from the BORG_PASSCOMMAND exported variable +if [[ -n "$BORG_PASSCOMMAND" ]]; then + borg_passphrase="$BORG_PASSCOMMAND" +# Else - try finding it from our designated password file +elif [[ -f /root/.config/borg/."$project_name" && -s /root/.config/borg/."$project_name" ]]; then + borg_passphrase=$(cat /root/.config/borg/."$project_name") +fi + +# If no passphrase found and repo EXISTS at the destination - Exit +if [[ ( -z "$borg_passphrase" ) && ( -f "$backup_dst_dir"/config || -f "$bkp_final_dir"/config ) ]]; then + echo "Could not find a passphrase" | tee -a "$LOGFILE" + echo -e "Either do a (EXPORT BORG_PASSCOMMAND=[your-passphrase] \n\t\t OR \nAdd the passphrase to /root/.config/borg/.${project_name} file." | tee -a "$LOGFILE" exit 12 fi # Auto generate passphrase if no repo exists -if [[ -z "$borg_passphrase" && ! -f "$backup_dst_dir"/config && ! -d "$backup_dst_dir"/WP && ! -d "$backup_dst_dir"/WP/config ]]; then - borg_passphrase=$(< /dev/urandom tr -cd 'a-zA-Z0-9~!@#$%^&*()_+-=' | head -c 20) # 20-character +if [[ ( ! -f "$backup_dst_dir"/config ) && ( ! -f "$bkp_final_dir"/config ) ]]; then + borg_passphrase=$(< /dev/urandom tr -cd 'a-zA-Z0-9@&_' | head -c 20) # 20-character - mkdir "$backup_dst_dir"/WP 2>> "$LOGFILE" >&2 + mkdir "$backup_dst_dir"/WP >> "$LOGFILE" 2>&1 export BORG_NEW_PASSPHRASE="$borg_passphrase" + # Backup any recidual passphrase keys + if [[ -f /root/.config/borg/."$project_name" ]]; then + mv /root/.config/borg/."$project_name" /root/.config/borg/."$project_name"_old_"${TS}" + fi + + # chmod 400 the passphrase file + touch /root/.config/borg/."$project_name" >> "$LOGFILE" 2>&1 && chmod 440 /root/.config/borg/."$project_name" >> "$LOGFILE" 2>&1 && { + # Display the passphrase on screen + echo "############### BACKUP PASSPHRASE ###############" | tee -a "$LOGFILE" + echo "$borg_passphrase" | tee /root/.config/borg/."$project_name" | tee -a "$LOGFILE" + echo "############### BACKUP PASSPHRASE ###############" | tee -a "$LOGFILE" + echo "You CANNOT access your backup without the above passphrase" | tee -a "$LOGFILE" + echo "" | tee -a "$LOGFILE" + } + # Initalize the repo - borg init -v --encryption=repokey-blake2 --storage-quota "$storage_quota" "$backup_dst_dir"/WP + if (borg init -v --encryption=repokey-blake2 --storage-quota "$storage_quota" "$bkp_final_dir" >> "$LOGFILE" 2>&1); then + echo "Repository initialized successfully" | tee -a "$LOGFILE" + else + echo "ERROR: Backup initialization failed. Check the logfile for more details." | tee -a "$LOGFILE" + fi fi -# Peform the actual backup +# This is required again - if passphrase was generated in the above step export BORG_PASSPHRASE="$borg_passphrase" -borg create \ - "$backup_dst_dir"/WP::{hostname}_"$project_name"_"$TS" \ - "$wp_src_dir" -borg create \ - --verbose \ - --filter AMEsd \ - --list \ - --json \ - --stats \ - --show-rc \ - --compression zstd \ \ No newline at end of file +# Do the actual backup +# We run it on a lower priority so it does not disturb others +if ionice -c 2 -n 7 borg create \ + --verbose \ + --filter AMEsd \ + --list \ + --json \ + --stats \ + --show-rc \ + --compression zstd \ + --exclude-caches \ + "$bkp_final_dir"::{hostname}_"$project_name"_"$TS" \ + "$wp_src_dir" \ + "${bkp_DB_dir}" \ + >> "$LOGFILE" 2>&1; then + echo "Backup Completed Successfully" | tee -a "$LOGFILE" +else + echo "ERROR: Backup failed. Check the logfile for more details" | tee -a "$LOGFILE" +fi \ No newline at end of file