I’ve had my personal WordPress site and all of my clients’ sites hosted with Laravel Forge for a little over a year now. If you haven’t heard of Forge yet, you definitely need to check it out. Yes, it is mainly for PHP applications, but it will also host WordPress sites like a champ. Forge is great, but the one thing it lacks is a way to back up your sites.
I wrote a script to handle backing up each WordPress site to Amazon S3 for safe-keeping as a part of my own backup plan.
Before walking through the script, I want to take a moment to outline the directory structure. I’ve created a
backups folder where all of this lives.
backups |--- .env |--- backup.sh |--- client-sites/ |--- logs/ | |--- 09-2018/ | |--- 10-2018/ |--- sites
backups directory, there’s an
.env I added so the mysql\_user and password are not embedded directly in the script.
client-sites/ folder is where the script does all of the file work — things like copying current site files and compressing them happen there.
logs/ folder is just a place to store all of the logs for the backup processes.
sites file which lists out all the databases and domains of the sites that are hosted on the server. Don’t get hung up on the fact that it’s using the domains. By default, Forge creates each site in its own home directory named after the domain of the site.
Here is what the
sites file could look like:
Here’s the entire script:
Walking Through The Script
The whole first part of this script is the actual
do_backup() function which handles the backup process. If you skip down towards the bottom of the file, you’ll see a couple of loops:
This section of the script is responsible for actually kicking off the backup function for each line in the
sites file. We loop through the file and
do an action for each line. While we’re working with that line we change the [Internal Field Separator] to break up the line by spaces into two parts.
The next line then kicks off the backup function passing the two parts as parameters. The first one passed (
$1) will be the database name for the site and the second (
$2) will be the home directory where the site lives.
Here’s an example of what that line would look like if we could step through the execution of the loop:
$ do_backup trecord tannerrecord.com
The backup function looks like it does a lot, but really only does 3 things:
- Copy the current site files into
- Compress the copied site files into something like
- Upload the compressed file to Amazon S3
The beginning of the function is just defining some variables and outputting a nice header to the log file.
Next, it copies the current site files into the
client-sites/ folder so it’s not working directly on the actual live site files.
Next, it dumps the mysql database into the copy of the site files.
Compresses the file:
When uploading to S3, you will need to have
awscli installed on the server for this script to work. You can install it with
pip through ssh with:
$ pip install awscli
--no-progress parameter just suppresses some of the extra information that shouldn’t be included in the log file.
In conclusion, it only took a few hours to develop this backup script and most of that time was actually debugging some issues with an old version of
Before I wrote this script, I was paying for a backup service that was $50 a month (and that only includes 5GB of storage). When all of my sites back up, they end up being about 2GB total and I’m going to keep 30 days of backups. When you look at the pricing of S3 ($0.023 per GB), which amounts to $1.38/mo, it’s not very hard to see why I wrote this script. I hope that it helps you get a better understanding of bash scripts and the power of doing some things yourself.