S3 Website Complete Setup

Hosting a static website on Amazon Web Services’ S3 is extremely cheap and effective. There are many tools these days for helping with this task. We use Jekyll to drive this very website. One frustrating thing about hosting on S3 is getting all of the redirects happening correctly. In our scenario (which is really common), we want the following:

  • https://www.portzeroventures.com (Primary Domain)
  • https://portzeroventures.com --> Primary Domain (HTTP 301 Redirect)
  • http://portzeroventures.com --> Primary Domain (HTTP 301 Redirect)
  • http://www.portzeroventures.com --> Primary Domain (HTTP 301 Redirect)

If you follow most of the resources online for setting up static s3 websites, you will find that they miss-out on one or more of these redirection scenarios. Furthermore, some modern browsers add www to the URL, and some will try HTTPS by default, which can obscure the true problem.

This is the architecture we use to host www.portzeroventures.com as a static website on Amazon Web Services S3.

S3 Static Website Architecture
S3 static website architecture that handles all of our redirection scenarios.

The key that most resources miss is that you need to setup two cloudfront distributions, one for handling the naked domain (e.g. portzeroventures.com), and the other for handling the primary domain (e.g. www.portzeroventures.com). Amazon Web Services has a lot of internal tooling that they have created for connecting resources in a cloud environment. It can be hard to tell what’s going on. After much trial and error, this is the setup that we’ve arrived at that works for our needs.

The rest of this post has the steps required to set everything up. There are three levels that need to be addressed:

  1. The DNS Level (using Route53) - Routing requests for www.portzeroventures.com and portzeroventures.com (HTTPS doesn’t matter at this level) to the correct Cloudfront distributions.
  2. The Content Distribution Network Level (using Cloudfront) - Handling HTTPS, but more importantly gathering the website content from the S3 bucket (origin).
  3. The Application Level (using S3 as a static filesystem) - Holds the actual content of the website.

S3 Setup

  1. Create a bucket with the same name as your goal website, e.g. www.portzeroventures.com in our case. Enable static website hosting as shown.
  2. Upload your static website to this bucket. You should try hitting the bucket URL directly (i.e. http://www.portzeroventures.com.s3-website-us-east-1.amazonaws.com) to verify the site works.

  3. Create another empty bucket named portzeroventures.com. Under “Static website hosting”, configure it to redirect requests to www.portzeroventures.com.

Cloudfront Setup

We need to make two cloudfront distributions, the first serves the true content at https://www.portzeroventures.com. The second serves the “content” of the S3 bucket setup to redirect to the true content.

  1. Create a cloudfront distribution for serving the primary site.
    • Add www.portzeroventures.com as a CNAME
    • Use a custom SSL certificate, setup for www.portzeroventures.com (You can click the button below to set one up – it isn’t hard)
    • Create an origin, and for the Origin Domain Name, use the full domain name of the S3 bucket as the value
      • It will auto-fill one such as www.portzeroventures.com.s3.amazonaws.com, but this is INCORRECT!
      • You need to use www.portzeroventures.com.s3-website.us-east-1.amazonaws.com.
    • Create a behavior for the origin, setting the Viewer Protocol Policy as “Redirect HTTP to HTTPS”

  2. Create a cloudfront distribution for redirecting the naked (non-www) domains.
    • Add portzeroventures.com as a CNAME
    • Use a custom SSL certificate, setup for portzeroventures.com
    • Create an origin, and for the Origin Domain Name, use the full domain name of the S3 bucket as the value as before (Use portzeroventures.com.s3-website.us-east-1.amazonaws.com NOT portzeroventures.com.s3.amazonaws.com)
    • Create a behavior for the origin as before, setting the Viewer Protocol Policy as “Redirect HTTP to HTTPS”

Route53 Setup

  1. Create an “A” record in route53 for the primary domain, www.portzeroventures.com. Make it as an alias to the full cloudfront domain name for the primary cloudfront distribution, e.g. d1j1qwwijgvt8y.cloudfront.net. The domain name for the cloudfront distribution can be found in cloudfront. Do not use the pre-filled dropdown values, they will lead you wrong.
  2. Create another “A” record for the naked (non-www) domain, pointing to the redirect cloudfront distribution that we setup.

Pro Tip:

Use curl with the -v (verbose) flag to verify the redirects are all happening correctly. Your browser and its plugins (e.g. HTTPS everywhere) can hide the true behavior of your setup.