Introduction
Setting this thing up was one of those situations in which everything goes bad, stumbling from one hole to another. You need to sync Nginx, WordPress, S3 and CloudFront, so not an easy task. The order of things depends on what you already have and what you want to achieve. Anyway, here are some of the notes for the future reference when it comes to CloudFront Over S3.
Create AWS S3 Bucket
We’re not going to go into details here, it’s relatively straightforward process.
You might be required to set “Bucket policy” (or it’s implicitly added by IAM later on):
{ "Version": "2008-10-17", "Id": "PolicyForCloudFrontPrivateContent", "Statement": [ { "Sid": "1", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity E3EPMARLA7L1EE" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::<YOUR_DOMAIN>/*" } ] }
and CORS configuration:
<?xml version="1.0" encoding="UTF-8"?> <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <AllowedMethod>HEAD</AllowedMethod> <MaxAgeSeconds>3000</MaxAgeSeconds> <AllowedHeader>Authorization</AllowedHeader> </CORSRule> </CORSConfiguration>
Another thing you’ll most likely need (for Total Cache CDN config) is a user with specific S3/CloudFront permissions.
AmazonS3FullAccess
& CloudFrontFullAccess
or CloudFrontReadOnlyAccess
. S3 and NGINX
You might encounter some problems if you don’t have properlly set CORS on your webserver:
add_header Access-Control-Allow-Methods "GET, POST";
add_header Access-Control-Allow-Origin *;
CloudFront over S3 with TotalCache [WordPress Plugin]
Then, jump to WordPress dashboard -> Performance -> CDN and fill the necessary fields (Access/Secret key, Bucket, etc).
Hit “Test S3 upload & Cloudfront distribution”. You should see “Test passed”.
In “General” tab above, there are options on what to upload. You might be required to upload first set of files manually. Afterwards, it’s going to continue its course on its own (TotalCache). To exclude specific pages from caching, go to Performance -> "Page Cache"
and insert them in “Never cache the following pages”
Performance -> Minify
and enable “Rewrite URL Structure”. You might notice that the minify folder is still empty. Go to Performance -> CDN
and hit the Upload minified files button under “General” section (Host Minified CSS & JS files). Don’t forget to save & purge or purge the current page. Mind your steps with JS/CSS configuration in Performance -> Minify section
(JS – combine only/async and being careful on the position head/after body)Below, in the “Advanced” tab, you’ll manage available options to your preference (e.g. “Add CORS header”, “Automatically upload minify files” and “Export changed files automatically”.
You might also be required to add some directories to the “Custom file list”. For example, *.ttf
and/or *.woff
were situated in a custom theme directory:
{plugins_dir}/*.tff
You can try adjusting NGinx headers, adding expires sections for individual types:
location ~* .(jpg|jpeg|png|gif|ico|css|woff2|font.css)$ { expires 7d; add_header Pragma public; add_header Cache-Control "public"; } location ~ .(eot|ttf|otf|woff|woff2|font.css)$ { add_header Access-Control-Allow-Origin *; }
But that probably won’t help.
Cache-Control: max-age=86400
Expires: access plus 7 days
Next, you’ll need to invalidate those resources on CloudFront side for changes to take effect.
CloudFront Distribution
It’s probably best if we simply share some details of the configuration parameters from AWS CloudFront you can use. You can continue without SSL Certificate (use default) and subdomain (e.g. cdn.<DOMAIN>
) configuration. Instead of having d34wz195yp1fja.cloudfront.net
in front of our static resources, we usually want to set specific subdomain (cdn).
General config:
AWS WAF Web ACL: None Alternate Domain Names (CNAMEs): cdn.<DOMAIN> SSL Certificate: *.<DOMAIN> Domain Name: d43za264dp2fsd.cloudfront.net Custom SSL Client Support: Clients that Support Server Name Indication (SNI) - (Recommended) Security Policy: TLSv1.1_2016 Supported HTTP Versions: HTTP/2, HTTP/1.1, HTTP/1.0 IPv6: Enabled
Origin config:
Origin Domain Name: <your s3 bucket - dropdown> Origin path: empty OriginID: <s3 id, implicitly set> Restrict Bucket Access: No Origin Custom Headers: None added
Behaviour config:
Path Pattern: Default (*) Origin or Origin Group: Viewer Protocol Policy: Redirect HTTP to HTTPS Allowed HTTP Methods: GET, HEAD Field-level Encryption Config: Empty Cached HTTP Methods: GET, HEAD (Cached by default) Cache Based on Selected Request Headers: None (Improves Caching) Object Caching: Use Origin Cache Headers Minimum TTL: 0 Maximum TTL: 31536000 Default TTL: 86400 Forward Cookies: None (Improves Caching) Query String Forwarding and Caching: None (Improves Caching) Smooth Streaming: No Restrict Viewer Access: No Compress Objects Automatically: Yes
You’ll probably have to experiment a bit, but these might help as a reference.
AWS CloudFront Certificate Manager
Instead of setting specific subdomain, we wanted to have an option for additional subdomains, so we used asterisk (*.<YOUR DOMAIN>
).
d43za264dp2fsd.cloudfront.net CNAME _28b66202c32a487d7e5ecba4f05fec81.dayrqlltje.acm-validations.aws.
Amazon will automatically/occasionally check DNS and validate your domain. From our experience, it’s relatively fast, 10-15 min.
Conclusion
You’re probably going to hit some obstacles, problems, and things won’t work as expected . Is it worth it? Yes, we think so. When everything gets finished, when suffering and hard labor passes, things are not bad. We used a number of CDNs and CloudFront seem to provide a better performance and stability. For comparement, CloudFlare is showing a number of issues when it comes to stability (10-30 min of downtime monthly or sometime weekly).