CloudFront and WordPress

Lots of tutorials and articles out there talk about a popular combination of CloudFront (CF) / WordPress (WP) / S3. In my case I don’t want to use S3 (why? because I don’t need to and don’t want to pay for it). I want to cache files stored by WP which in my case is using block storage. So, how do you set up CF with WP but without S3? Pretty easily, really. Here are the steps I took and pot holes I fell into. For the WP part I followed this post: https://blog.lawrencemcdaniel.com/integrating-aws-s3-cloudfront-with-wordpress-2/ the section about plugins was most useful. For AWS I followed this post: https://aws.amazon.com/blogs/startups/how-to-accelerate-your-wordpress-site-with-amazon-cloudfront/. There were a few gotchas along the way so I’ve tried to point some of them out below.

DNS and certificates

As far as your DNS records go, all we really need to do is point the www record as an alias to the CF URL and then point the apex record to the IP of your EC2. In the Origin setup, specify the Origin Domain Name as the apex record (not www). In my case this is just wojtek-kedzior.com. Don’t forget to set HTTPS Only if you are using an SSL certificate. It’s worthwhile mentioning that you will want to add both your DNS records to the Alternate Domain Names (CNAMEs). In my case these were www.wojtek-kedzior.com and wojtek-kedzior.com.  My DNS setup looks like this:

wojtek-kedzior.com.  A   <ip to instance> 
www.wojtek-kedzior.com.  ALIAS  d1l97lizsxt89f.cloudfront.net.

Not having a wildcard certificate complicates things somewhat as you only have two DNS records to work with.  Ideally you would refer to your distribution through something like cdn.domain.com.  You still can, but if you are using a certificate issued only for domain.com then using sub-domains will yield errors.  

No redirect when hitting the distribution URL.

Make sure to set “Default Root Object” to ‘/’. Since CF doesn’t follow redirects it will show your page from the origin, but the URL will stay as the distribution URL. Setting the root means a redirect happens immediately after hitting the distribution URL. One note worthwhile making is that the even though the distribution URL is public and may be easily found, if your page is setup correctly clicking any link on it will redirect you to your proper URL

CloudFront is caching everything

Make sure to add in behaviors to control what really gets cached. Most, if not all, content under /wp-content/ and /wp-includes/ is static which makes it a candidate for caching. Since WordPress relies on cookies make sure you your default behavior (the ‘/’) forwards all cookies and query strings. This ensures that your webserver will get all the info it needs otherwise weird things start to happen. One of the bizarre issue I ran into was the slash missing between the domain and the rest of the URL. Although the webserver had the slash explicitly defined at the end of the domain there was no slash to be seen in any of the links rendered in the HTML

For the WP admin pages you’ll need to allow the POST method in the distribution config.

Disabling Canonical URL Redirects

One ugly hack which is required is to update the functions.php file of your theme to disable canonical redirects.  Otherwise what happens is that you get redirected to the origin, which is something you don’t want – the distribution should be doing that.  In other words, the server generates a 301 redirect, which the distribution returns to the client.   The problem is that the redirect is pointing directly to the server, which cannot be accessed as the security group only allows traffic from the distribution. More on that later. You can also end up with a redirect loop here if you force the redirect URL to be that on the distribution.

// disable WordPress's Canonical URL Redirect feature
remove_filter('template_redirect','redirect_canonical');

Source: https://www.dev4press.com/blog/wordpress/2015/canonical-redirect-problem-and-solutions/

On admin pages there is also a reference a canonical URL with the old value. To fix it you need to remove the reference to canonical URL in:

 /var/www/html/wp-admin/includes/misc.php

source: https://taylor.callsen.me/settings-up-aws-cloudfront-in-front-of-wordpress/

Restricting traffic to your EC2 instance 

Restricting traffic to your EC2 instace to allow HTTP/HTTPS traffic originating only from the CF edge server means your site will not be accessible directly anymore.  The browser will not be able to access the your EC2 instnace any more, only the distribution will be able to do so.   The benefits here are that CF can protect against DOS attacks and to some degree other types of attacks.  The setup can be automated so that whenever AWS change the IPs of the edge servers you can trigger a lambda function which will update your security groups. 

Guides as to how to to about setting up Lambda to trigger on SNS notification:

https://blog.eq8.eu/til/configure-aws-lambda-to-alter-security-groups.html

https://aws.amazon.com/blogs/security/how-to-automatically-update-your-security-groups-for-amazon-cloudfront-and-aws-waf-by-using-aws-lambda/

https://aws.amazon.com/blogs/aws/subscribe-to-aws-public-ip-address-changes-via-amazon-sns/

Renaming URLs

Changing the URL of your site after already having some content is painful, but for the most part it works OK. It’s the themes that usually break.. In my case any images added through the theme customize page would point to the old URL (which now happens to be inaccessible due to the security groups) even though the URL has been updated in the media view and the images are accessible via the new URL. Go figure.