Quick Client WordPress Staging with Digital Ocean and Amazon Route53

• ~900 words • 4 minute read

When developing for the web you'll often find yourself with three "versions" of your project, often referred to as environments:

  • Local: This is the version of the site or project as you hack away at it on your workstation.

  • Staging/Development: This is the place you test out what you've been working on. Ideally it should simulation the "real" environment to the point where you can identify any bugs your changes might have introduced.

  • Production: The final resting place.

Often I need to create quick staging websites to preview things for my work — particularly when WordPress is involved. I've come up with a workflow that leverages Digital Ocean and Amazon Web Services (Specifically Route53) to quickly create staging websites to share with my clients.

You'll need to the following:

When we're done you'll be able to run:

clientloft acmeclient.example.com

And after a few minutes you'll have a brand new WordPress site up and running at acmeclient.example.com.

When you're done with it you'll be able to run

clientloft destroy someclient.example.com

After a few moments the relevant Digital Ocean droplets and Route53 records will be removed from your accounts and they'll stop charging you money.

If you're wondering why I'm calling my script client loft you can find an explanation towards the end.

Step 1: Install and configure tugboat.

You can find more information on the GitHub repository, but if you're a Mac or Linux user it boils down to keeping a .tugboat file in your home directory.

You'll want to specify a default region, image and size for your droplets. It will make the snippet we're going to write a little less verbose. I recommend using this as a minimum in your defaults section:

defaults: region: nyc2 image: wordpress-16-04 size: 1gb

Step 2: Install and configure the AWS CLI tools.

There is more information on their website and the man pages, but you'll want to run was configure and go through the steps of entering access keys.

Step 3: Setup a hosted zone in Route53.

This script is going to create subdomains off of a primary domain for our staging sites. For my client work I use a domain I registered a long while ago: clientloft.com. That means a project called acmeproject end sup getting hosted at acmeproject.clientloft.com.

To do this we'll need to setup a hosted zone in Route53 and take note of the Hosted Zone ID. It'll be a combination of numbers and letters. In the AWS web console you can find this in the last column from the hosted zones section under Route53:

Route53 Hosted Zone IDs

When you have the hosted zone created and have copied the ID you're done with this step!

Step 4: Write the script!

Those first two scripts do all the heavy-lifting. We just need to tie them together in a way that makes them easier to use.

Open up your favorite text editor and write:

#! /bin/bash
# require domain to create
if [ -z $SUBDOMAIN ]; then exit; fi

# see if we're destroying a loft
if [ $SUBDOMAIN == 'destroy' ]
  echo "Destroying $SUBDOMAIN.$DOMAIN..."
  IP=`tugboat droplets | grep $SUBDOMAIN.$DOMAIN | awk '{ print $3}' | sed 's/[\{\}, ]//g'`
  tugboat destroy $SUBDOMAIN.$DOMAIN
  # Create a JSON object to send to Route53 and save it to local file
  JSON='{ "Comment": "", "Changes": [{ "Action": "DELETE", "ResourceRecordSet": { "ResourceRecords": [ { "Value": "'$IP'" } ],"Type": "A", "Name": "'$SUBDOMAIN'.", "TTL": 300 } } ] }'
  echo $JSON > route53-delete-$SUBDOMAIN.$DOMAIN.json
  aws route53 change-resource-record-sets --hosted-zone-id=$ZONE --change-batch file://route53-delete-$SUBDOMAIN.$DOMAIN.json
  rm route53-delete-$SUBDOMAIN.$DOMAIN.json

# Create the droplet on Digital Ocean with tugboat

echo "Creating Digital Ocean droplet ($IMAGE_ID) at $SUBDOMAIN.$DOMAIN...";
tugboat create $SUBDOMAIN.$DOMAIN -i $IMAGE_ID
tugboat wait $SUBDOMAIN.$DOMAIN

# Retrieve the IP address for the newly created droplet
IP=`tugboat droplets | grep $SUBDOMAIN.$DOMAIN | awk '{ print $3}' | sed 's/[\{\}, ]//g'`

## Update the DNS records on Route53 to point to the A Record.
echo "Updating DNS to point $SUBDOMAIN.$DOMAIN to $IP..."

# Create a JSON object to send to Route53 and save it to local file
JSON='{ "Comment": "", "Changes": [{ "Action": "CREATE", "ResourceRecordSet": { "ResourceRecords": [ { "Value": "'$IP'" } ],
  "Type": "A", "Name": "'$SUBDOMAIN.$DOMAIN'.", "TTL": 300 } } ] }'
echo $JSON > route53-create-$SUBDOMAIN.$DOMAIN.json

# Use AWS CLI tools to update the records
aws route53 change-resource-record-sets --hosted-zone-id=$ZONE --change-batch file://route53-create-$SUBDOMAIN.$DOMAIN.json

# Remove JSON file
rm route53-create-$SUBDOMAIN.$DOMAIN.json

echo "Done!"

Name the file whatever you like — I called mine clientloft after the domain I use for these — and put it in a place that makes sense for your workflow.

There is one line worth pointing out:


This line tells Digital Ocean to use a specific, ready-made disk image that has the latest version of WordPress on Ubuntu 16.04. You can change this to anything you like. For a list of available images run tugboat images at the command-line.

You're done! You should now be able to create and destroy WordPress staging sites on Digital Ocean, mapped to the subdomain of your choice with just a couple commands.

Please let me know if you find this useful.