We already improved our WordPress’ performance and content loading speed using Elasticache in a prior tutorial. Now we’re going one step forward by locating those contents closer to our users in order to enhance response time even more by creating a Content Delivery Network using Amazon’s S3 and CoudFront services.
A Content Delivery Network is a fleet of servers distributed around the world which contain copies of our content. This way users visiting our site receive a response from the server closest to their location, hence decreasing data travel distance and intermediaries, resulting in a quicker access to the content.
In order to enable our WordPress to take advantage of this, we’re doing the following changes:
- We’ll store our site’s images outside the web server that’s hosting WordPress, offloading any work related to image serving from our EC2 instances and allowing browsers to download them at the same time they download the text content. To do so, we’ll create an Amazon S3 bucket.
- We’ll configure a CloudFront distribution that will cache our images from S3 to the edge locations Amazon has set up for us (see global infrastructure).
- We’ll install a WordPress plugin that will handle the uploading of our pictures to S3 giving us a CloudFront link to them.
Creating and configuring our CDN
Creating an S3 bucket
We need to log into our AWS Management Console, navigate to S3 and press on the “Create Bucket” option.
Then, we’ll have to set a bucket name and choose the AWS region we want it on. We have to keep in mind that the bucket name is unique across all regions (this means that there can only be one single bucket with a given name on a given time). Even though we’re going to use CloudFront to serve the content, we’ll choose the same region we have our EC2 instances on and press the “Create” button.
Creating the CloudFront distribution
On the AWS console, we move to the CloudFront section, then press on “Create Distribution”.
CloudFront allows us to create both static content and streaming content distributions. We are distributing static contents, so we’re choosing the first one (“Download”), then click on “Continue”
On the next screen we have to tell CloudFront the source of the contents we want on it, the “Origin Domain Name”. As we’ve already created an S3 bucket, the console should help us autocomplete its name and it will also fill the “Origin ID” field, which is just the nickname assigned to the origin.
We recommend to enable the “Restrict Bucket Access” option to ensure our contents are unreachable directly on S3 and will always be accessed through CloudFront. This implies to create IAM identities and editing the bucket’s policies but Amazon will conveniently do that work for us if we choose “Create new identity”, assign it a comment and finally enable “Yes, Update Bucket Policy”.
In the “Default Cache Behavior Settings” section we can enforce HTTPS usage (we haven’t done that). We can also choose whether to oblige with the cache behavior that’s included in our content’s headers or override it with our own policies. In our example, the pluging we’re using sets the headers correctly for us, so we stick to the “Use Origin Cache Headers” option.
We can also have CloudFront forward cookies and/or URL query strings to our origin or even restric access to the content by using signed URLs. None of these options is relevant to our example and that’s why we’re leaving them disabled.
Below we can find the “Distribution Settings” section. The “Price Class” setting will allow us to define which regions and edge locations our content will be cached in. It’s important to choose wisely since pricing is dependant on that.
We can set up an alias on our DNS servers to our CDN. In that the case, we should tell AWS the name or names we’re going to use in the “alternate Domain Names (CNAMEs)” field.
At last, if we want to keep our CDN’s activity logged, we have to explicitly choose (“Logging”: On) then assign an S3 bucket as a destination for it and a prefix for the names of the files that will be generated.
When we’re finished configuring it, we can click on “Create Distribution”.
Once the AWS console tells us that the distribution is in the “Enabled” state, it would be finally created. We can go to check its settings, where we can find the domain name for it. We’ll note it down, since we’re going to need to tell WordPress where will our CDN be located.
Creating an S3-enabled IAM user
The WordPress plugin we’re going to use needs an user with enough privileges to upload and manage our pictures. In order to create it, we’ll navigate to the IAM section in the AWS panel, move to “Users”, then press on “Create New Users”.
We’ll give our new user a name, then click on “Create” while leaving the remaning options untouched.
We’ll see the credentials that have been generated for this user: Access Key and Secret Key. We’ll have to either download them or copy them so we can input them in the WordPress control panel later. This credentials are NOT stored in Amazon, which means this is the only chance we’ve got to retrieve them. Once we’ve made sure we’ve secured them, we can close the window.
Once the user is finally created, we have to assing it a securtiy policy for S3. To do so, we select the user, navigate to the “Permissions” tab and click on “Attach User Policy”.
There’s a list of ready to use AWS-provided templates in the “Select Policy Template” section, but we’re using a custom one in order to restrict permissions to the minimum necessary ones (write only to one specific bucket).
We name our policy with a descriptive name and define it. We’ve used this one.
Installing and configuring the WordPress plugin
We install and activate the Amazon S3 and CloudFront plugin as we would do with any other WordPress plugin.
Once activated, we navigate to “Settings > Amazon S3″, where it will ask for our IAM credentials (the “Access Key ID” and the “Secret Key ID”). Once we’ve filled the boxes, we’ll click on “Next Step”.
We’ll see two configuration sections: one for S3 and one for CloudFront.
In the S3 one, we’ll input our bucket’s name and, given the fact our content won’t change, enable the “Set a far future HTTP expiration header” option (this will improve caching). In the CloudFront one we’ll input our distribution’s domain name. Finally, we’ll activate “Enable copying of media files” to enable the CDN and save the changes.
From now on, when we embed images using the WordPress Media Gallery, we’ll notice a new section with the CloudFront URL where the content will be served from.
We have to keep in mind that any files uploaded before installing the plugin won’t be transferred to S3 nor CloudFront and will keep being served from the instance running WordPress
It’s possible that at some point we’d want to eliminate a cached version of some our content from CloudFront and force a cache refresh of it, for example when we change a file. To do so, we’ll navigate to the CloudFront section on the AWS console, select our distribution and click on the options icon.
We move to the “Invalidations” tab, then “Create Invalidation”
We write the names of the files to invalidate and press the “Invalidate” button.
Once this process is complete, the object cached on the Edge Locations will be removed from them and the new version will be cached the next time it is requested.
S3 Getting Started Guide: http://docs.aws.amazon.com/…/Welcome.html
Amazon S3 Developer Guide: http://docs.aws.amazon.com/…/Welcome.html
CloudFront Getting Started Guide: http://docs.aws.amazon.com/…/Welcome.html
Amazon CloudFront Developer Guide: http://docs.aws.amazon.com/…/Welcome.html
IAM Getting Started Guide: http://docs.aws.amazon.com/…/Welcome.html
Using IAM: http://docs.aws.amazon.com/…/Welcome.html
Amazon S3 and Cloudfront: http://wordpress.org/plugins/amazon-s3-and-cloudfront/