How to host a static website with HTTPS on AWS, using S3 and CloudFront

Amazon’s AWS is an inexpensive and limitlessly scalable platform that can be ideal for hosting fast, secure, and reliable static websites. I host several sites using the method described below, and it costs me pennies per month. The only problem is that getting things set up–especially with HTTPS support–isn’t exactly straightforward.


Summary #


Configure S3 #

  1. Create two buckets in S3. It doesn’t matter what they’re named, but one will be used to hold your content and the other will remain empty – I suggest yourdomain-static and yourdomain-www. (Note: Amazon suggests naming the buckets yourdomain.com and www.yourdomain.com, but there are downsides to this naming approach.1 ) Be sure to uncheck the boxes for “Block new public ACLs…”, “Remove public access granted…”, “Block new public bucket policies”, and “Block public and cross-account access…”.
  2. In the S3 console, select the -static bucket, click properties, and then turn on “Static website hosting”. Select “Use this bucket to host a website”. Make the “Index document” index.html and the “Error document” error.html. Then click Save.
  3. Select the ‘-www’ bucket, click properties, and turn on “Static website hosting”. Select “Redirect requests”. Enter yourdomain.com as the “Target bucket or domain”. Set “Protocol” to https. Then click Save.
  4. Make note of the endpoint URLs displayed for each bucket in the “Static website hosting” properties panel. (Endpoint URLs look like http://yourbucketname.s3-website-us-east-1.amazonaws.com.)

Configure AWS Certificate Manager #

If you don’t already have a certificate issued for your domain with ACM, go to the AWS Certificate Manager in the AWS Console.

  1. Click “Request a certificate” (don’t worry–it’s free).
  2. Create two entries under “Add domain names”: yourdomain.com and *.yourdomain.com.
  3. Choose the validation method that works for you (but you should almost certainly use DNS validation), then request the certificate. It may take an hour or more for your certificate to be issued and available.

You’ll have to wait until your certificate is issued before continuing.


Configure CloudFront #

  1. Create two CloudFront distributions. Click “Create Distribution” in the CloudFront console. Then click “Get Started” under “Web”.
  2. For the first distribution, use the following settings:
    1. Origin Domain Name: The S3 website endpoint url for your -static bucket. (Note: Amazon will try to help you autocomplete, but ignore its suggestion. Use the S3 website endpoint URL instead).
    2. Viewer Protocol Policy: Redirect HTTP to HTTPS.
    3. Compress Objects Automatically: yes.
    4. Alternate Domain Names: yourdomain.com
    5. SSL Certificate: Choose “Custom SSL Certificate” and then select your ACM certificate from the dropdown.
    6. Default Root Object: blank
    7. Click “Create Distribution”.
  3. For the second distribution, use the following settings:
    1. Origin Domain Name: The S3 website endpoint url for your -www bucket. (Note: Amazon will try to help you autocomplete, but ignore its suggestion. Use the S3 website endpoint URL instead).
    2. Viewer Protocol Policy: Redirect HTTP to HTTPS.
    3. Compress Objects Automatically: yes.
    4. Alternate Domain Names: www.yourdomain.com
    5. SSL Certificate: Choose “Custom SSL Certificate” and then select your ACM certificate from the dropdown.
    6. Default Root Object: blank
    7. Click “Create Distribution”.
  4. Make note of the CloudFront Domain Name for each distribution. It may take a few minutes for the domain names to become visible in the CloudFront console. (CloudFront Domain Names look like d1tj8z7yt99sdx.cloudfront.net.) It may take up to an hour for the CloudFront distribution to actually start working.

Configure DNS using Route 53 #

  1. Go to the Route 53 section of the AWS console. Click “Hosted Zones”. Click on your domain.
  2. Delete any A-records listed for yourdomain.com. and www.yourdomain.com..
  3. Create a new A-record by clicking “Create Record Set”. Use the following settings:
    1. Name: blank
    2. Type: A - IPv4 address
    3. Alias: yes
    4. Alias Target: The CloudFront Domain Name of the distribution that points to your -static bucket. (In the dropdown, make sure you select from the list of “CloudFront distributions” and not from “S3 website endpoints”.)
    5. Click “Create”
  4. Create a new A-record by clicking “Create Record Set”. Use the following settings:
    1. Name: www
    2. Type: A - IPv4 address
    3. Alias: yes
    4. Alias Target: The CloudFront Domain Name of the distribution that points to your -www bucket. (In the dropdown, make sure you select from the list of “CloudFront distributions” and not from “S3 website endpoints”.)
    5. Click “Create”

Done #

It may take a while for the CloudFront distributions to activate and the DNS settings to propagate. Assuming everything is set up properly, you’ll be able to store arbitrary files in the bucket yourdomain-static and they will be available at https://yourdomain.com. Visitors to http(s)://www.yourdomain.com will be redirected to https://yourdomain.com.

If you make edits or changes to the files in yourdomain-static, you will need to invalidate the cached objects on CloudFront. To do this, go to the CloudFront console, click on your distribution, then click the “Invalidations” tab. Click “Create Invalidation” and either enter the paths to the files you changed or just “*”, which will invalidate everything. Click “Invalidate”.


  1. It is outside the scope of this guide, but there are situations in which you might want to use the AWS S3 domain for your stored objects. Using a bucket name that includes a . makes S3 more difficult to use because the AWS S3 domain name at https://bucketname.s3.amazonaws.com will have an invalid SSL certificate. In any case, it is a good idea to “claim” the yourdomain.com and www.yourdomain.com buckets in S3 by creating them, even if you don’t use them. 

 
227
Kudos
 
227
Kudos

Now read this

One of the dumbest things I’ve ever published

While I was reading through some of my older essays the other day, I came across a piece called Privacy vs. User Experience, published in 2014. In the article, I argued that Apple’s then-nascent philosophical stance on the supremacy of... Continue →