Amazon S3 and CloudFront as a WordPress CDN

0
15

My original go at setting up CloudFront as a CDN did not go very well. At the end of the last post on setting up CloudFront and W3 Total Cache, it was working (via WP Rocket), but when I changed the theme, things went back to not using the CDN. In this post, I will look at setting up Amazon S3 and using CloudFront through that instead. Hopefully, it should be a bit more stable and less likely to break.

What is Amazon S3?

It’s for object storage, as simple as that. So we can throw lots of images at it, and other things too, like CSS.

Under the Free Tier, we can get:

  • 5 GB of Standard Storage
  • 20,000 Get Requests
  • 2,000 Put Requests

This should be enough for the images on this site. Hopefully.

I need to make some changes though.

At the moment, the configuration is an Elastic Load Balancer in front of a WordPress instance, which uses (though not successfully) CloudFront as the CDN. At the end of this post, the idea will be that we use Amazon S3 as storage, which then pushes the objects into CloudFront.

The first step is to create an S3 bucket.

Creating an Amazon S3 bucket

We start by navigating to the Amazon S3 option within the AWS console. and clicking on “Create bucket”

Creating an Amazon S3 bucket

In the first page that opens, we need to give it a name and select the region. The name must be unique across S3, as someone else was already using “aws-s3” I had to use something else:

Creating an S3 bucket

Click Next

On the properties page, just click next.

Next, we have to set the permissions:

Creating an S3 bucket
I set mine to have public access, not sure if this is right, I guess so, otherwise no-one will be able to access the images, but on the other hand, the images should be served by CloudFront… Worth testing. Click Next.

Review and create the bucket:

Creating an S3 bucket

I have a bucket

Creating an S3 bucket

Setting up S3 and CloudFront

I need to create another CloudFront origin. I already have one from my previous attempt, and if I were to repeat this process, I would probably delete the other one first, the reason for this will become apparent later on.

Start by creating the  origin:

 

S3 and CloudFront

Select the S3 bucket created earlier:

CloudFront bucket origin
I grabbed the domain name from the S3 settings after uploading an image:

CloudFront originClick on Create and wait for about 15 – 20 minutes for CloudFront to finish processing.

Setting up S3 and WordPress

I am using the Offload S3 plugin here. It already has my account details set up, I just need to tell it which bucket to access:

S3 and WordPress
On the settings page, we need to copy files to S3, and I want to rewrite the URLs to use the CDN name instead:

S3 CNAME CDN
I am also forcing HTTPS.

Make sure you save your settings.

At this point, I am getting 404 errors when trying to see the images (also thumbnails are not working in WordPress). This would seem to indicate that the data is not making its way over to CloudFront. Either this is a permissions issue or an issue with pushing or pulling between S3 and CloudFront.

The first step I took was to look at the IAM permissions for the w3-cf group:

S3 IAM
No permissions for S3.
IAM
I need to give the group access to S3, so click on “Attach Policy” and then search for S3:

IAM attach policy

Select the appropriate policy and click on “Attach Policy”.

However, it is still not working. In the S3 console, I can see the objects being added, and browsing to the object in S3 I can see the URL, such as “https://aws-802101-s3.s3.amazonaws.com/wp-content/uploads/2018/06/14115559/aws-s3-cloudfront-1.png”. Finding the same object in CloudFront and trying to open it in the browser, I get the following error (I xx’d out a few bits):

<Error>
<Code>NoSuchKey</Code>
<Message>The specified key does not exist.</Message>
<Key>
    wp-content/uploads/2018/06/14115559/aws-s3-cloudfront-1.png
</Key>
<RequestId>ED6xxxxxxxxx</RequestId>
<HostId>
aTgpzRjarUuSgn43vgHXxxxxxxxxxxxxEZz18GI0vxK5HGbWnLI5+eTk=
</HostId>
</Error>
Still sounds like a permissions issue. So let’s go back to CloudFront. In CloudFront is an Origin Access Identity, which seems like something we should try out. It even says it allows CloudFront to access S3!
Click on “Create OAI”

OAI
Click on “Create”.

OAI 2I am still getting 404 errors though, so let’s check the distribution.

Testing the URLs available in a new browser window, this does work – https://s3.amazonaws.com/aws-802101-s3/wp-content/uploads/2018/06/14115559/aws-s3-cloudfront-1.png, however, it does not match the bucket name in the dropdown list offered by CloudFront, so I amended the Origin:
CloudFront S3 origin
Below, I have set the origin to match the URL given in the bucket:
CloudFront S3 origin correctedI still had issues though, and this was because there was no behavior set for the origin. I had one for my first attempt, but nothing to match this one. So I changed the origin in the behavior to match the bucket instead:
CloudFront S3 behaviors
Finally, things seem to be working properly! Would have been a bit quicker if not for the first behavior policy in CloudFront.

Still no cigar

Things only look right when I am logged in to WordPress. Trying the site in another browser, or in Incognito mode, the site looks screwed up. All the images are missing, and the CSS looks a bit funky.
Let’s try and work out what the issue is.
Step 1:
I disabled the CloudFront integration in Offload S3 so that it would use the S3 URLs instead for the images (and cleared the WP Rocket cache).
I still cannot see images but can open them in a new window by right-clicking on the whitespace, but still, they are not appearing in the post.
Step 2:
I disabled CDN integration in WP Rocket. It’s a pretty simple CDN set up there, just a push to aws-cdn.802101.com – there are no account details to use.
Things look much better now, the images look as they should, and the site does not look messed up.
Step 3:
I re-enabled CDN in Offload S3 (so it uses the aws-cdn.802101.com address in the URL and cleared the WP Rocket cache.
Everything is looking correct now, all is where it should be.
Lesson learned: Too many CDNs will lead to trouble!

TLDR version

  • Disable any other CDN integration you have!
  • Create the S3 bucket
  • Assign your IAM user (you may need to create one first) full access to S3 (and CloudFront)
  • Create a CloudFront distribution, using the Origin Domain Name and Origin Path as shown in your S3 bucket (upload an image or something to get the details).
  • Make sure that you have an Origin Access Identity set up to link S3 and CloudFront.
  • Make sure you have a Behavior rule set up in CloudFront (easy if this is your only distribution or a distribution with only one Origin).
  • Set up Offload S3 in WordPress

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.