Image for post
Image for post

Using WP Rocket with AWS CloudFront CDN

Speed up your WordPress website with AWS CloudFront serving all your images, css, and javascript content.

I recently helped out a WordPress site owner — let’s call our site owner “Joe”.

Joe was struggling to get WP Rocket working with AWS CloudFront for stylesheets and javascript. His site was already successfully using S3 and CloudFront for all its image media using the “WP Offload Media Lite” plugin.

Joe had also configured a custom subdomain for his CloudFront distribution and SSL certificate using the techniques described in the two articles below.

However, after installing the “WP Rocket” plugin and updating its CDN configuration to point at the existing CloudFront distribution, Joe’s WordPress site no longer rendered correctly.

On closer inspection, CloudFront was returning “403 Forbidden” errors for all the .css and .js files. So what was the issue and how do we fix it.

First of all, what is WP Rocket?

WP Rocket (tagline: “Superior WordPress Performance”) is a full cache plugin that comes with many features [full feature list] including caching, file size reduction, minification, database optimization, and CDN integration. It’s the latter feature we’re interested in, and the official image below shows how easy it is to configure.

Image for post
Image for post
https://docs.wp-rocket.me/article/42-using-wp-rocket-with-a-cdn#default-pull-cdn

What was Joe’s issue and how do we fix it?

Joe’s existing CloudFront distribution had a single origin (S3) that contained the images that had been replicated from the primary server to S3 using the “WP Offload Media Lite” plugin.

WP Rocket was correctly updating all the .css and .js files to the CloudFront domain, but the CDN was returning “403 Forbidden” errors for them.

This error can be rather confusing at first — why is CloudFront giving me an Access Denied error? — but there is a simple answer and it also guides us to the solution. If a user doesn’t have s3:ListBucket permissions, then Amazon S3 returns “403 Forbidden” errors for missing objects instead of “404 Not Found” errors.

Of course! CloudFront is looking for the stylesheet and javascript files from S3, but they are still on Joe’s primary WordPress server.

Now that we know that it was Amazon S3 that returned the error — and we know that S3 returns this error when the objects don’t exist — and we know that the “WP Offload Media Lite” plugin is only offloading images to S3 — and we know that Joe’s stylesheet and javascript files are still only on his primary WordPress server — we’re getting a lot of clues as to how to configure WP Rocket and CloudFront, and now we can solve Joe’s problem.

There’s two solutions;

  1. The “WP Offload Media Lite” plugin provides a paid-for option that allows javascript and stylesheets to be offloaded to S3 as well as images.
  2. Set up an additional origin in the CloudFront distribution for Joe’s primary server; configure behaviours to direct .js and .css files to the new origin server; and allow the images to continue to be pulled from S3.

Joe ended up doing option 2.

As you read on, you can still follow these instructions even if you don’t already have a CloudFront distribution. You may not already use the “WP Offload Media Lite” plugin like Joe — that’s all okay — it’s there for our backstory, but this is a generic solution for configuring WP Rocket to work with CloudFront as well.

Step 1. Add multiple origins to CloudFront distribution

Our first step is to configure an additional origin to Joe’s existing CloudFront distribution. This will be for his primary Wordpress server.

Head to the “Origins and Origin Groups” tab and click on “Create Origin”. Set up the origin according to your WordPress server — while the details will be specific to your own set up, I’d anticipate that you would need to change the Origin Protocol Policy to “HTTPS Only”.

You’ll now have two Origins. For the purpose of demonstration, example.com is representing S3, and example2.com is representing the WordPress server.

Image for post
Image for post

Step 2. Configure Behaviors for the different paths

Now head to the “Behaviors” tab. You’ll find an existing default behaviour that is pointing all hits to the first Origin — for Joe, this was his S3 origin.

Select “Create Behavior”, leave all the defaults in place and set these values;

  • use *.js for the Path Pattern.
  • select the Origin that corresponds to the primary WordPress server.

Repeat for *.css paths and you’ll end up with three Behaviors.

Image for post
Image for post

And that’s it.

Joe updated “WP Rocket” plugin configuration with his CloudFront distribution domain and the WordPress site immediately started to render correctly. CloudFront pulled his stylesheets and javascript from Joe’s primary server, and used the existing default fallback to S3 for everything else (i.e. the images that the “WP Offload Media Lite” plugin was replicating to S3).

Gotchas. What might go wrong?

One possible consideration is continuing to serve cached versions of files after WordPress upgrades. Which isn’t good. Two solutions exist for this problem;

  1. Use Invalidations in CloudFront to clear the cache after upgrades.
  2. Update the Cache Policy to use Query String parameters — conveniently, WordPress provides a ver=x.x.x parameter that helps here.

To implement #2, on the Behavior update to “Use legacy cache settings”.

Image for post
Image for post

Under “Query String Forwarding and Caching” select “Forward all, cache based on whitelist” and type in ver

Image for post
Image for post

A note from the author

Thank you for reading this article — I hope you found it useful and can follow along to speed up your WordPress site using WP Rocket and CloudFront.

You can follow me on Twitter and connect on LinkedIn.

Written by

DevOps | SRE | AWS | GCP https://twitter.com/davelms

Get the Medium app