Michaël Gallego

This is my blog. What can you expect here? Well... Zend Framework 2, Amazon AWS...






Static website on S3, CloudFront and Route 53, the right way!

Did you notice that since a few months, this blog is WAY faster than it was before? This is not an impression. IT IS faster. There are two reasons: it is a static website (no more WordPress) and it is hosted on Amazon S3 and CloudFront as a CDN.

The best thing in this story is that it is fast all around the world (except a few places like East Europe and China were Amazon does not have - yet - server nodes), as you can see below:

My website has low latency all over the world

This guide is going to show you how to install your website using Amazon S3, Amazon CloudFront and Amazon Route 53, the right way (there were some changes in June 2013 regarding Route 53, and because the official guide is completely wrong when it comes to configuring CloudFront).

I will also give you useful tips that are not always straightforward and that can lead to poor caching.

What we are going to do

We are going to create a static website that will be accessible both from the APEX domain (without the www) and using the www domain (like this blog).

This guide is only focused to the AWS part, not the creation of the static website itself. If you want a blog, you could check at Jekyll (which is the tool I use to generate this blog).

Creating the S3 bucket

The first thing we need to do is creating a S3 bucket. Most of the other guides on the Internet ask you to name the bucket according to your domain (so if you own the domain example.com, you should name the bucket www.example.com and/or example.com). This is not needed when using CloudFront, as all requests will be directed to your CloudFront distribution.

However, as S3 buckets namespaces are shared by all users, you should better name it according to your website, just in case you may decide to drop CloudFront one day (I don’t see why, but you may have your own reasons ;-)). Click on create, and you’re done!

Create a S3 bucket

The region is no longer that important when we use CloudFront. You may just use the cheapest one (which is North Virginia if I remember correctly).

You can now upload your static website, either through the console, or using a tool like s3_website.

Setting the bucket policy

Because we are using this S3 bucket for hosting a static website, we want every files to be publicly accessible. The simplest way is to add a policy:

  1. Select the bucket.
  2. Click on “Permissions”, then “Add bucket policy”.
  3. Copy-paste the following lines (don’t forget to change the bucket name to your bucket name in the Resource key):
	"Version": "2008-10-17",
	"Statement": [
			"Sid": "Allow Public Access to All Objects",
			"Effect": "Allow",
			"Principal": {
				"AWS": "*"
			"Action": "s3:GetObject",
			"Resource": "arn:aws:s3:::www.michaelgallego.fr/*"

Setting the bucket to accept a static website

Now, click on the “Static Website Hosting” and click on “Enable website hosting”. In the “Index document” and “Error document”, you’ll likely have “index.html” and “error.html” (of course, those files must exist at the root of your bucket).

Also, make sure to copy-paste somewhere the “endpoint”. We will need it when creating the CloudFront distribution:

Bucket static website configuration

This endpoint can be used to access your website directly to S3 (even when we have our CloudFront distribution set up, this URL will completely bypass CloudFront, can be useful for testing purposes sometimes).

If you go to this URL (and if you have properly upload an index.html file at the root of the bucket), you should be able to see it.

Nice. We now have an awesome static website that is quite fast for people near the S3 region, but for others, it will be a lot slower. Let’s introduce CloudFront to the game!

Creating CloudFront distribution

Open the CloudFront tab in Amazon console, and click on “Create distribution”.

At first step, select “Download”:

Download delivery method needs to be used for website hosting

The next page is trickier. If you click on “Origin Domain Name”, CloudFront will automatically auto-complete with your S3 bucket. However, don’t select this one. Instead, copy-paste the endpoint we had in previous step. You should have something like that:

Make sure NOT to select the bucket in the auto-complete list

In next part, “Default Cache Behaviour Settings”, you can stay with the default values, excepting for “Forward Query String”. By default, you’ll want a very high cache control value for files like CSS, JavaScript… The problem is that when you change it, you’ll be forced to manually invalidate the file on CloudFront (otherwise people will still be served with the old version). By setting this option to “Yes”, you will be able to add query string to your resources (like screen.css?version=2). Whenever you change it, CloudFront will take it as another resource, and ask your origin for the new file.

Cache behaviours

In “Distribution Settings” part, you will need to set values in “Alternate Domain Names (CNAMEs)”. The values will be, most of the time, your naked domain, and your domain with www. Please note that CloudFront does not modify your DNS (we will do it later in Route 53). What this thing does is only to tell CloudFront that it can serves files from different CNAMEs.

Because we set different CNAMEs, this means that your pages can be accessed from two different URLs (for instance example.com/about/ and www.example.com/about/). In order to avoid duplicate content problems, you should always include a canonical URL in your <head>, and configuring your Google Webmaster Tools to indicate Google which is your prefered domain).

In the “Default root object” input, write “index.html”. This will indicate CloudFront which file it should retrieve when accessing your distribution directly. It should look something like this:

CloudFront distribution settings

Click on “Create Distribution” and you’re done! It will take a few minutes to set up. When it’s done, copy your CloudFront domain name (it looks like xxx.cloudfront.net). If everything went good, you should see the exact same content as on S3. Except that this time, the file is being served from a CloudFront edge server. Much faster!

Setting Route 53

Open the Route 53 tab, and click on “Create hosted zone”. The domain name you need to enter is always the naked domain.

Select your newly created hosted zone, and click on “Go to record sets”. The NS entries that were automatically generated by Route 53 should be entered in your domain provider (check their documentation to learn how to do it). You will need to wait between 24 and 72 hours before all the DNS propagated correctly.

In the mean time, we are going to properly configure Route 53. Since June 2013, Route 53 supports to alias CloudFront distribution to APEX domain (also called naked domains). This is very useful, because we will be able to “attach” both the APEX domain and the www domain name to the CloudFront distribution, hence making your website accessible from those two URL, without having to launch a small webserver to redirect it.

  1. Click on “Create Record Set”.
  2. In the “Name”, enters nothing, and make sure “Type” is to “A - IPv4 address”.
  3. Click on “Yes” for Alias, and set the CloudFront distribution as “Alias target” (it should be automatically auto-completed for you).
  4. Leave the Routing Policy to “Simple”, and validate the record set.
  5. Go back to 1, but this name enters “www” for name.

You should end up with something like this (just ignore the TXT entry, it’s related to Google verification):

Route 53 hosted zone settings

Advices for best performance

Here are several tips for having the best performance in CloudFront:

  • Nor CloudFront and S3 natively GZip documents. This means that if you want GZip (and you should), you must manually GZip each files. Hopefully, some tools like s3_website automate this process. Hopefully CloudFront will offer this feature out of the box one day!
  • I found a subtle “bug” some days ago: when using URLs like www.example.com/about/, Amazon S3 will in fact return the “index.html” file inside the folder (because it is configured as a static website bucket). The funny thing is that if you omit the trailing slash (www.example.com/about), S3 will first check if an object called “about” exists. If it does not, it will consider that about is a folder, and will issue a 301 redirection to about/. When using CloudFront, this means that CloudFront will in fact cache… the redirection instead of the file itself! Therefore, you must make sure that all your URLs end by a trailing slash to avoid a useless redirect.


Since June 2013 with alias support for CloudFront and APEX domains, we have all the tools to simply create a static website with nearly unlimited scalability and fast all over the world. Moreover, hosting a site on S3 and CloudFront is really cheap (for most small sites, the most expensive is Route 53, which is charged 0.5 $ per month).

If you have any feedbacks, don’t hesitate to comment!