Setting up S3 and CloudFront for Static Site Hosting

(This is a companion post to my post about my S3/CloudFront static site deployment script, _jaws)

S3 and CloudFront pair up really nicely to form a static site hosting solution. You can upload your site to S3, avoiding the need for real hosting, and then you can use CloudFront as a CDN to make things fast, all over the world.

If your blog gets little or no traffic, the total cost will be in the vicinity of $0.10 a month depending on your settings.

I love this setup for my blog since it means I don't need to maintain any infrastructure. Sure, I have server assets and VPSes lying around, but worrying about a WordPress blog being hacked is way down on my list of things I want to be doing. And while Amazon's datacenters have had downtime here and there, just like my Linodes, I have a pretty high level of confidence that things will come back up in a reasonable amount of time and "just work" with this setup. Push it, forget it.

I've also spent a lot of time traveling and living outside of the USA (I'm writing this blog post from my girlfriend's place in Hong Kong) which has made me particularly sensitive to sites that lack edge servers. It sounds petty, but I really don't want that extra 300ms of latency if I can avoid it.

So let's talk about how to set this up.

Step 1: S3

S3 setup is super easy. All you have to do is log into AWS and create a bucket.

There is one trick though. To make things place nice with CloudFront (and not have all your paths have index.html in them), you have to use the "Static Website Hosting" option.

Screenshot of S3 static website hosting setup

If you don't do this, you're going to get confusing AccessDenied XML error messages from CloudFront down the road.

Make note of the Endpoint that it shows you.

You're now ready to go ahead and upload your files to your S3 bucket.

Step 2: CloudFront

CloudFront is a bit less obvious. Start off by creating a download distribution. Most of the settings are pretty straightforward, but one very easy mistake to make is when you're setting the "Origin Domain Name". Make sure to specify the HTTP URL to your S3 bucket, rather than one of the pre-filled S3 buckets. Otherwise, again, you'll get those AccessDenied messages.

Most settings can be left as the default but I highly recommend:

  • Set your Default Root Object to index.html.
  • Setting "Forward Query Strings" to Yes. This can be huge for proper caching of linked assets like JavaScript and CSS.
  • Setting a couple alternate CNAMEs. One for, one for, one for The main benefit here is that you can spread your HTTP requests over several different domains, for HTTP efficiency. Not really needed.
  • For Object Caching, I select Use Origin Cache Headers. This is because I know I'm setting these properly via _jaws; if you're not doing this, you'll want to Customize and set your own Minimum TTL.

After you submit, CloudFront may take a few minutes for things to finish setting up. Once it's done, add a CNAME record into your DNS such that references your CloudFront domain name (mine for example is

You should be all set now.

A couple next steps:

  • Use a deployment script (like my aforementioned _jaws) to upload your site with proper compression and caching.
  • Make sure your naked/apex (e.g. domain 301 redirects to You can't do a CNAME on your domain apex, so CloudFront won't work nicely from there. You can use something like wwwizer. I use nginx redirect on Linode I have lying around for some other stuff. S3 can also do this with the "Redirect all requests to another host name" option pictured above.

From here, you should be in really good shape. Happy AWSing.


comments powered by Disqus