Since releasing Suzie, I’ve been asked the same question a lot — “How do I use Suzie with AWS/Elastic Beanstalk to make a scalable WordPress site?”. With Suzie I purposely left a few vendor/providor specific features out, the idea was if you knew AWS well you’d adapt Suzie a little to suit your needs.
However, I’ve listened to feedback added a few AWS tweaks to help. In this tutorial, I’ll walk you through setting up a WordPress site to run on multiple EC2 instances while enjoying the simplicity of Elastic Beanstalk. We’ll be storing Media uploads and other assets on S3, using CloudFront as a CDN, and adding SSL & Varnish. If you wonder what sort of speed you can expect, our site — where you’re reading this — is using the same setup.
Costs
Don’t let the AWS pricing tables put you off – AWS is actually pretty good value for money. The setup we will create with this tutorial will run for around $30-40 per month, basing this of the assumption that most of the time the site operates with one instance.
Caveats
With most complex set ups there some drawbacks – perhaps deal breakers for some:
- Plugins can’t be installed on the production site – plugins must be committed to git and deployed.
- Some plugins may not be compatible, as there’s no permanent filesystem.
Here at Big Bite, we believe it to be good practice to test plugins on a staging server before moving them into production, so the first point isn’t a big concern for us. If a plugin requires that its settings are stored in a config file, simply committing that file to the repository solves the latter issue.
Note: Elastic File System can be an alternative solution to the above caveats but, as it’s not currently available in all regions, I haven’t included it.
AWS
Sign in to your AWS account, at which point you should be presented with the main AWS Dashboard. At first, it looks a little overwhelming seeing how many options there are, but you’ll barely touch most of it for this setup.
Once thing to note is the region in the top right — I’ve marked it in blue — make sure it’s the closest either to yourself or the receiver. Being in the UK, we’ll use Ireland.
Route 53
The first thing we’ll tackle is your domain. Unfortunately, to use AWS with your root domain, you need use AWS Route 53 nameservers. Navigate to Route 53 → Hosted Zones → Create Hosted Zone. You will be given a box in which you need to input your domain. Let’s add bigbite.net
.
Now it’s been created, you will be given a new set of nameservers. That should be enough for you to configure your domain’s nameservers with your provider.
S3
Let’s go through setting up a bucket to use with Suzie. For this example, I’ll set one up for to use with bigbite.net
. From the main AWS dashboard, navigate to the S3 section:
Select Create Bucket
:
Let’s enter assets.bigbite.net
, select Ireland again, and click Create
. Once created, we need to edit the bucket’s access policy and CORS config. We’ll start with the bucket policy by navigating to bucket properties and selecting Edit bucket policy
.
Now we need to give everyone read access. Paste the following in, replacing bucket.name
:
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"AddPerm",
"Effect":"Allow",
"Principal": "*",
"Action":["s3:GetObject"],
"Resource":["arn:aws:s3:::bucket.name/*"]
}
]
}
And click Save
. Just like you did with Edit bucket policy
, select Add CORS Configuration
and paste the following in:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
<AllowedHeader>Content-*</AllowedHeader>
<AllowedHeader>Host</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Now the last thing you will need is your access details to allow WordPress to upload files. At the top of window click on your name, then Security Credentials
. On the left of the new screen select Users
Select Create New Users
:
Let’s enter WordPress-BigBite
and select Create
:
Make a note of your Access Key ID
and Secret Access Key
, you’ll need them later.
It’s time to give that user access to your S3 bucket. Click Attach Policy
Select AmazonS3FullAccess
then Attach Policy
. It’s important to note that this gives this user access to all buckets, so you may wish to refine this later.
Elastic Beanstalk
Elastic Beanstalk is a simplified way to manage load-balanced EC2 instances. Select it from the AWS Dashboard and create your first Application. In this case Big Bite Creative
.
Next you will be asked to create an environment and pick which type you want; in this case, we want Web Server Environment
.
Time to configure the type of web server. Change the Predefined configuration
to PHP
and double check that Environment type
is set to Load balancing, auto scaling
After that, you have the chance to upload a copy of your application, but it’s best to select Sample application
for now.
Moving on, you can specify a name for your environment, which will give you a URL to access the app. As this will be the production environment for the Big Bite app, I’ll use bigbite-production
.
On the additional resources screen, you want to add an RDS, which will be your MySQL database.
There is isn’t much you need to configure on EC2; update the Instance type
to t2.micro
and specify an EC2 ssh key to use.
You will be given the option to add environment tags, but it’s best left until later.
RDS doesn’t require much configuration, either; update the Instance class
to db.t2.micro
, and generate a decent Username
& Password
The next screen lets you set up some permissions — AWS docs cover this, so I won’t bore you with the details. Finally, you should reach a review screen:
Once you’re happy with your configuration, click Launch. This can take some time, so don’t worry. Once it’s complete, you should see a Health status of Ok
.
SSL
Both your Load balancer (Elastic Beanstalk) and your CDN (CloudFront) will need to access to your SSL certificate. Please ensure you’ve got a wildcard SSL certificate for your domain.
First, you’ll need the AWS Command Line Interface. To install this, follow the official instructions here. Once that’s set up, open up your terminal and cd
to the folder containing your SSL certificate. You will need your Public Certificate
, Private Key
, and Intermediate CA
— for more on this, read. Below is an example of us uploading the SSL certificate — make sure you replace bigbitecreative
with your domain.
$ aws iam upload-server-certificate --server-certificate-name bigbitecreative --certificate-body file://public.crt --private-key file://private.key --certificate-chain file://intermediate.crt --path /cloudfront/bigbitecreative/
Now, you’ll need to go back to Elastic Beanstalk to enable SSL. Select your app, then Configuration
; scroll down a bit until you see Load Balancer
, and click on the gear. Update Secure listener port
to 443
, select the SSL certificate you uploaded earlier, and click apply.
CloudFront
CloudFront is a CDN service offered by Amazon and has to be easiest way to put a CDN in front of an S3 bucket. Select it from the AWS Dashboard and create your first Distribution.
Next, you will be asked to select which type you want; in this case we want Web
The next screen can seem a bit overwhelming, but we will tackle each section one at a time. In Origin Settings, you will find Origin Domain Name
, which is where you start typing the name of S3 bucket. Next you have the Origin ID
, which is a name to remember what the distribution is used for.
Under Default Cache Behavior Settings we need to configure the headers. Scroll down until you see Forward Headers
and change it to Whitelist
, at which point a Whitelist Headers
field should appear; we need to add the following headers to the whitelist:
- Access-Control-Request-Headers
- Access-Control-Request-Method
- Origin
Lastly, we’ll move on to the Distribution Settings. In the Alternate Domain Names
field, we will enter the domain we wish to serve our content from — cdn.bigbite.net
, in this case. We want to use SSL with this domain so, under the SSL Certificate
section, select Custom SSL Certificate
, then select the SSL certificate we uploaded earlier from the drop down.
Whilst that’s being created, we can link up cdn.bigbite.net
to our new distribution. On the main CloudFront screen with your list of distributions, note your domain name for recent one you created. It should be formatted as:
xxxxxx.cloudfront.net
Go to Route 53, and Create Record Set:
Ready to deploy
Okay at this stage, with most of the set up done, we’re almost ready to deploy — we just need to configure our code. I’m assuming you already have Suzie set up; if not go check it out. To deploy to Elastic Beanstalk we need to install their CLI. It’s easier to install this with pip
– if you do not have pip
installed you can use Homebrew to install it:
$ brew install python
Or using easy install:
$ sudo easy_install pip
Let’s set up the AWS EB CLI:
$ sudo pip install awsebcli
Now we’re ready to move to our project directory and run:
$ eb init
You will be asked a number of questions. For regions we’re using Ireland
, and for application we select Big Bite Creative
. Once completed, you will see a new folder in your project: .elasticbeanstalk
. This folder contains some basic information about your new app. The next step is to add configuration for Varnish, Composer etc. To save some time, I’ve created a repo with a folder you need to add to your project:
.ebextensions
https://github.com/getsuzie/aws
You will also find a file cron.yaml
in the repo — which we’ll talk about in more detail further on — which you’ll need to copy across to the project as well.
We have a few edits to make before we’re ready to deploy. Open .ebextensions/app.config
. We’ll start by replacing domain.com
with our actual domain (bigbite.net
). After that find the line:
if (req.http.X-Purge-Token == "xxxx")
Generate yourself a token like P54Paqg6cC5OBDWp
replace the xxxx
so:
if (req.http.X-Purge-Token == "P54Paqg6cC5OBDWp")
Our next step is to set which IPs are allowed to clear Varnish. Find the section:
acl elb {
"172.22.0.0"/20;
"172.22.16.0"/20;
"172.22.32.0"/20;
}
To get these IPs, you will need to revisit the AWS Dashboard and navigate to Select VPC. In here you will want to select Subnets on the left hand side. The values you are looking for are under the CIDR column. It is possible to restrict what IPs the EC2 will use and, in turn, tighten up who can clear Varnish; however, as we also require a token to clear the cache, it’s not strictly necessary.
Now, the moment you’ve been waiting for: deploying. Run:
$ eb deploy
It will take some time, and don’t expect your site to work right away — we still have the environment variables to add. Once the deploy is finished, visit the AWS Dashboard and go to Elastic Beanstalk. Select your application, go to Configuration, then scroll down to Software Configuration. First, let’s update Document root
to /public
. Under Environment Properties you will see a list of fields that need completing, most of which are straightforward. The following are AWS/Varnish specific:
VARNISH_AWS=true
VARNISH_AWS_LB=
VARNISH_AWS_REGION=eu-west-1
VARNISH_ENABLED=true
VARNISH_PATH=https://bigbite.net/.*
VARNISH_TOKEN=P54Paqg6cC5OBDWp
Most are easy enough to understand; the one which requires a little more work is your load balancer name VARNISH_AWS_LB
. Let jump back into AWS Dashboard and select EC2. At the top you should see a list of options, select Load Balancers
.
Next we’ll copy the name of load balancer:
And update our environment variable:
VARNISH_AWS_LB=awseb-e-y-AWSEBLoa-aabbccddeeff
Remember earlier, when we added a cron.yaml
to our project? We now need to set that up. Open it up in your editor and find the line:
url: "/?suzie=scheduler&token=EIE1AsOQtvYY2yas"
We need to set up our token for this, so please generate a new one like 5DTIWmtGM9wPc43w
, then update the line:
url: "/?suzie=scheduler&token=5DTIWmtGM9wPc43w"
There’s a few environment variables to update to match:
SCHEDULER_ROUTE=true
SCHEDULER_TOKEN=5DTIWmtGM9wPc43w
Now we’re ready to deploy again.
$ eb deploy
Closing
I hope this tutorial is enough to make you realise AWS isn’t that hard to configure, and the amazing performance it offers is worth the time spent. If you happen to know a better way to set up WordPress on AWS, please drop me email. Thanks for reading.