FREE THOUGHT · FREE SOFTWARE · FREE WORLD

Home  »  Shell Scripting  »  Encrypted WordPress / phpBB Backups

by 2 comments

Because backups contain all your sensitive information, its smart to encrypt any sql backups.. and while we're at it, also encrypt any site backups.

This simple shell-script is a useful and easy way to securely backup your wordpress and/or phpBB site files and database without confusing you. Just generate a GPG key once, enter in 3 settings once, and from then on it runs without any user-input whenever you want.


What it Does

When run, this script asks you for the location of your websites document root and the location of your wp-config.php or config.php file. It also asks you for your encryption UID. Then this script saves those settings in a file called .sbackup so that the next time you run the script it will run without having to re-enter that information, making it nice for cronjobs or quick and easy on-demand backups. Another cool feature that I added is this script automatically parses your wp-config.php file for the mysql database name, user, host, and password, meaning you don't have to compromise your security or take the time to type those settings in manually.

What is Backed Up

This script creates a tarred and gzipped archive of your entire document root in the folder ~/backups/domain.com/domain.com-date.tgz and also creates a backup of your WordPress database and phpBB database in a format that is ideal for restoring from. Both of these files are then encrypted using your GPG key and can then be safely downloaded as a password and key is required to decrypt them.

Generating a GPG Key

If you don't already have one setup for your shell account run this command remembering the uid which you will enter in the shell script.

gpg --gen-key

Decrypting Files

gpg -r UID --output FILENAME.tgz --decrypt FILENAME.tgz.asc

The Shell Script

site-backup.sh

#!/bin/bash
# SiteBack Version 3.3, 2008-12-17
# GNU Free Documentation License 1.2
# 12-17-08 - AskApache (www.askapache.com)
umask 022
 
### SHELL OPTIONS
set +o noclobber # allowed to clobber files
set +o noglob # globbing on
set +o xtrace # change to - to enable tracing
set +o verbose # change to - to enable verbose debugging
set -e # abort on first error
shopt -s extglob
 
###########################################################################--=--=--=--=--=--=--=--=--=--=--#
###
### SETTINGS
###
###########################################################################==-==-==-==-==-==-==-==-==-==-==#
 
DT=$(date +%x); DT=${DT///}
DTX=$(date +%x-%H%M); DTX=${DTX///}
BDIR=${HOME}/backups
RUN_FILE=${BDIR}/$$.bk.log
MY_CONFIG=".sbackup"
DOMAIN=;DB_NAME=;DB_USER=;DB_PASSWORD=;DB_HOST=;APP_CONFIG=;SQL_DEST=;ARC_DEST=;ENCRYPT_USER=
E_SUCCESS=0;E_YN=0;E_YES=251;E_NO=250;E_RETURN=65;C0=;C1=;C2=;C3=;C4=;C5=;C5=;C7=
 
###########################################################################--=--=--=--=--=--=--=--=--=--=--#
###
### FUNCTIONS
###
###########################################################################==-==-==-==-==-==-==-==-==-==-==#
 
#--=--=--=--=--=--=--=--=--=--=--#
# script_title
#==-==-==-==-==-==-==-==-==-==-==#
function script_title(){
 local e="33["
 local l=' ___________________________________________________________________ '
 
 # SET WINDOW TITLE AND COLORS IF CLIENT CAPABLE
 case $TERM in xterm*|vt*|ansi|rxvt|gnome*)
 C0="${e}0m";C1="${e}1;30m";C2="${e}1;32m";C3="${e}0;32m";C4="${e}1;37m";C5="${e}1;35m";C6="${e}30;42m"
 esac
 
 echo -e "n${C0}$l${C1}"
 echo -e "|             ${C2}___       __    ___                 __${C1}                |"
 echo -e "|            ${C2}/ _ | ___ / /__ / _ | ___  ___ _____/ /  ___${C1}           |"
 echo -e "|           ${C2}/ __ |(_-</  '_// __ |/ _ / _ `/ __/ _ / -_)${C1}          |"
 echo -e "|          ${C3}/_/ |_/___/_/_/_/ |_/ .__/_,_/__/_//_/__/${C1}           |"
 echo -e "|                               ${C3}/_/${C1}                                 |"
 echo -e "|                                                                   |"
 echo -e "|       ${C1}+--${C0} SITE BACKUP SCRIPT Version 3.3${C1}                          |"
 echo -e "${C0}$lnn"
}
 
#--=--=--=--=--=--=--=--=--=--=--#
# pm
#==-==-==-==-==-==-==-==-==-==-==#
function pm(){
 START=$(date +%s) && touch ${RUN_FILE}
 case "${2:-title}" in
  "title") echo -en "nn${C2}>>> ${C4}${1} ${C0} nn"; ;;
   "info") echo -e "${C5}=> ${C4}${1} ${C0}"; ;;
   "item") echo -e "${C4}-- ${C0}${1} "; ;;
 esac
}
 
#--=--=--=--=--=--=--=--=--=--=--#
# yes_no
#==-==-==-==-==-==-==-==-==-==-==#
function yes_no(){
 local ans
 echo -en "${1} [y/n] " ; read -n 1 ans
 case "$ans" in
  n|N) E_YN=$E_NO ;;
  y|Y) E_YN=$E_YES ;;
 esac
}
 
#--=--=--=--=--=--=--=--=--=--=--#
# do_sleep
#==-==-==-==-==-==-==-==-==-==-==#
function do_sleep (){
 local END DIFF
 echo -en "${C5}${3:-.}"; while [ -r "$RUN_FILE" ]; do sleep ${2:-3}; echo -en "${3:-.}"; done;
 echo -e "${C0}"; sleep 1; END=$(date +%s);DIFF=$(( $END - $START ))
 echo -e "n${C6} [T: ${SECONDS}] COMPLETED IN ${DIFF} SEC ${C0} nn"; sleep 1;
 return 0;
}
 
#--=--=--=--=--=--=--=--=--=--=--#
# get_settings
#==-==-==-==-==-==-==-==-==-==-==#
function get_settings(){
 local cha HOSTED_SITES G GG
 clear; script_title
 
 if [[ -r "$MY_CONFIG" ]]; then
 
  OIFS=$IFS; while IFS=: read DOMAIN DOMAINROOT APP_CONFIG ENCRYPT_USER; do
   DOMAIN=${DOMAIN};
   DOMAINROOT=${DOMAINROOT};
   APP_CONFIG=${APP_CONFIG};
   ENCRYPT_USER=${ENCRYPT_USER};
   #E_YN=$E_YES;
   break
  done <${MY_CONFIG};
  IFS=$OIFS
 
 else
 
  gpg --list-keys|grep uid.*|awk '{print $2}'
  echo -en "n What userid to use for encryption?  ";
  read -e ENCRYPT_USER; echo
 
  echo -en "n What domain would you like to backup?  "; read -e DOMAIN; echo
 
  echo $PWD
  until [ -d "$DOMAINROOT" ]; do echo -en "n Folder where config file is located?  ";
  read -e DOMAINROOT; echo; done
 
  [[ -r "$DOMAINROOT/config.php" ]] && APP_CONFIG=$DOMAINROOT/config.php && DOT=PHP
  [[ -r "$DOMAINROOT/wp-config.php" ]] && APP_CONFIG=$DOMAINROOT/wp-config.php && DOT=WP
 
  echo $PWD
  until [[ -r "$APP_CONFIG" ]]; do echo -en "n Where is the applications config file?  "; read -e APP_CONFIG; echo; done
 
 fi
 
  [[ -r "$DOMAINROOT/config.php" ]] && APP_CONFIG=$DOMAINROOT/config.php && DOT=PHP
  [[ -r "$DOMAINROOT/wp-config.php" ]] && APP_CONFIG=$DOMAINROOT/wp-config.php && DOT=WP
 
  ### For phpBB
  if [[ "${DOT}" == "PHP" ]]; then
    GG=$(sed -e '/$db(n|u|pa|h)/!d' -e "s/$db_(name|user|passwd|host) = '([^']*).*$/1='2';/g" -e 's/$db/DB_/g' ${APP_CONFIG});
    G=$(echo ${GG}|sed -e 's/DB_name/DB_NAME/g' -e 's/DB_user/DB_USER/g' -e 's/DB_passwd/DB_PASSWORD/g' -e 's/DB_host/DB_HOST/g');
  else
    G=$(sed -e "/define('DB_(NAME|USER|PASSWORD|HOST)/!d" -e "s/[^']*'DB_(NAME|USER|PASSWORD|HOST)'[^']*'([^']*)'.*$/DB_1='2';/g" ${APP_CONFIG})
  fi
  eval $G;
 
 mkdir -p ${BDIR}/${DOMAIN}
 SQL_DEST=${BDIR}/${DOMAIN}/${DOMAIN}-${DT}.sql;
 [[ -r "${SQL_DEST}.asc" ]] && SQL_DEST=${BDIR}/${DOMAIN}/${DOMAIN}-${DTX}.sql
 
 ARC_DEST=${BDIR}/${DOMAIN}/${DOMAIN}-${DT}.tgz;
 [[ -r "${ARC_DEST}.asc" ]] && ARC_DEST=${BDIR}/${DOMAIN}/${DOMAIN}-${DTX}.tgz
 
 if [[ "$E_YN" != "$E_YES" ]]; then
  for a in "DOMAIN" "DOMAINROOT" "APP_CONFIG" "ENCRYPT_USER" "DB_NAME" "DB_USER" "DB_PASSWORD" "DB_HOST"; do echo -e "${a}: ${!a}"; done
  echo; yes_no "ARE THESE SETTINGS CORRECT"
 fi
 
 while [[ "$E_YN" != "$E_YES" ]]; do
  for a in "DOMAIN" "DOMAINROOT" "APP_CONFIG" "ENCRYPT_USER" "DB_NAME" "DB_USER" "DB_PASSWORD" "DB_HOST"; do
   echo -en "n (Enter for Default: ${!a} )n ${a}:> "
   read -e cha; echo; [[ ${#cha} -gt 2 ]] && eval "$a"=$cha
  done
  yes_no "ARE THESE SETTINGS CORRECT"
 done
 
 echo -e "${DOMAIN}:${DOMAINROOT}:${APP_CONFIG}:${ENCRYPT_USER}" > $MY_CONFIG
}
 
#--=--=--=--=--=--=--=--=--=--=--#
# exit_cleanup
#==-==-==-==-==-==-==-==-==-==-==#
function exit_cleanup(){
 cd $OLDPWD
 [[ -r "${SQL_DEST}" ]] && rm ${SQL_DEST}
 [[ -r "${ARC_DEST}" ]] && rm ${ARC_DEST}
}
 
############################################################################################################
###
### MAIN CODE
###
############################################################################################################
 
#=# CATCH SCRIPT KILLED BY USER
trap exit_cleanup SIGHUP SIGINT SIGTERM
 
#=# MAKE MAIN SCRIPT NICE
renice 19 -p $$ &>/dev/null
 
cd `dirname $0`
 
get_settings
 
pm "CREATING SQL BACKUP"
mysqldump --opt -u${DB_USER} -p${DB_PASSWORD} -h ${DB_HOST} -r ${SQL_DEST} --add-drop-table ${DB_NAME} 1>&2 &>/dev/null && sleep 2 1>&2 &>/dev/null && rm ${RUN_FILE} 2>&1&
do_sleep 1 1 ":"
 
pm "ENCRYPTING SQL BACKUP"
gpg --armor --recipient ${ENCRYPT_USER} --output ${SQL_DEST}.asc --encrypt ${SQL_DEST} 1>&2 &>/dev/null && sleep 2 1>&2 &>/dev/null && rm ${RUN_FILE} 2>&1&
do_sleep 1 1 ":"; rm ${SQL_DEST}
 
pm "CREATING ARCHIVE BACKUP"
tar -czf ${ARC_DEST} . 1>&2 &>/dev/null && rm ${RUN_FILE} 2>&1&
do_sleep 1 5 ":"
 
pm "ENCRYPTING ARCHIVE BACKUP"
gpg --armor --recipient ${ENCRYPT_USER} --output ${ARC_DEST}.asc --encrypt ${ARC_DEST} 1>&2 &>/dev/null && rm ${RUN_FILE} 2>&1&
do_sleep 1 1 ":"; rm ${ARC_DEST}
 
echo -e "${C1} __________________________________________________________________________ "
echo -e "|                                                                          |"
echo -e "|                 ${C4} COMPLETED SUCCESSFULLY ${C1}                                 |"
echo -e "${C1} __________________________________________________________________________ ${C0} nn"
 
cd $OLDPWD
 
exit $?

Tags

August 4th, 2008

Comments Welcome

  • Philippe Ivaldi

    Your code is VERY interesting !
    Thanks to share it.
    However, it's possible to use rsync in order to synchronize the files and use ssh connections.

  • http://12flat.com Stu L

    Works seamlessly except it goes through the sql back up/encryption and hangs on "creating archive backup". I see the start of the .tgz file in my folder, only about 1.5mb and the little purple colons just running off my putty window. Is the expected behavior that I wait for this to complete? It doesn't seem like it's wanting to update the file any further.

Popular Articles
My Online Tools

Related Articles
Newest Posts
Twitter


  • @askapache · Jul 21
    Magic spells for sending thoughts across time? Books
  • @askapache · Jul 20
    TV is just a relic of the previous generation. We just don't know it yet.
  • @askapache · Jul 20
    I will never go back on my ideals, no matter the cost. I'll never let the economic vultures steal my dreams. I'd rather give up the ghost
  • @askapache · Jul 18
    I don't want a better seat, I want control of the engine
  • @askapache · Jul 14
    No matter how good u r, there will always be someone 2x, 5x, 100x better. This is true for me and everyone. No direction but forward.
  • @askapache · Jul 12
    Heads up, I'll DDoS the f out of askapache next week, to see how resilient it really is :) - will try to overflow disk, net, and ip stack
  • RUN GCC! This is a typical shirt I wear, from the  t.co/46LYbFr4k2  shop. A clerk at the LQ recognized it!  t.co/jjmT0dkCPu 
  • Merlin the Magician  t.co/iMmRbanUi4 
  • ROGUE CODE - Latest novel from @markrussinovich  t.co/apkn0LoPIt 
  • RTFM - surprisingly very helpful and way more comprehensive than it looks! @redteamfieldman #pwnAllTheThings  t.co/xiaJ5g0aC9 
  • Dear Hacker - Letters to the Editor of 2600, from Emmanuel Goldstein  t.co/JCfLab7FAJ 
  • The Mythical Man-Month - Essays on Software Engineering, by Frederick P. Brooks, Jr.  t.co/ilWN5GHElr 
  • "where wizards stay up late" - The Origins of the Internet. Favorite book detailing the birth of the net and IMPs  t.co/gY9VTGJgZz 
  • ZERO DAY - read before Trojan horse  t.co/pPMLGDJv8P 
  • Trojan Horse, a novel!  t.co/Hf8EtYaZVa 
  • The Hacker Playbook - very nice high level overview of attacks  t.co/lHwNVWi61u 
  • Clean Code - A Handbook of Agile Software Craftsmanship  t.co/hnJX0x1qIc 
  • Secrets of the JavaScript Ninja - By my absolute favorite JS hacker John Resig!  t.co/tZ42ljmcCl 
  • Hacking Exposed 7: Network Security Secrets & SolutionsMy all time favorite, basic but thorough and accurate.  t.co/jycW0RDVtZ 
  • Empty words will be no surrogate for cold resolve. Pain is nothing.  t.co/qXjpRxbjCw 

Hacking and Hackers

The use of "hacker" to mean "security breaker" is a confusion on the part of the mass media. We hackers refuse to recognize that meaning, and continue using the word to mean someone who loves to program, someone who enjoys playful cleverness, or the combination of the two. See my article, On Hacking.
-- Richard M. Stallman






[hide]

It's very simple - you read the protocol and write the code. -Bill Joy

Except where otherwise noted, content on this site is licensed under a Creative Commons Attribution 3.0 License, just credit with a link.
This site is not supported or endorsed by The Apache Software Foundation (ASF). All software and documentation produced by The ASF is licensed. "Apache" is a trademark of The ASF. NCSA HTTPd.
UNIX ® is a registered Trademark of The Open Group. POSIX ® is a registered Trademark of The IEEE.

| Google+ | askapache

Site Map | Contact Webmaster | License and Disclaimer | Terms of Service

↑ TOPMain