web aws cert s3
Created: 2019-10-28 Updated: 2020-04-29

Create a Static Website on AWS

Some notes on quickly setting up a static website with a custom apex & www domain over HTTPS/TLS using Amazon S3, Route 53, CloudFront and Let's Encrypt Certificate Authority.

Preamble

My plan is to add some application functionality using AWS Lambda at some point so it seemed like a useful exercise to host the static content using AWS.

I've setup 3 websites with this method. My only issues were not pointing Route 53 at S3 (and not CloudFront) to setup the certificates and being impatient while the DNS transfer that I'd also initiated went through.

Prerequisites

Make sure you're logged in to your AWS account https://console.aws.amazon.com. If you've ever used Amazon, AWS uses the same credentials. Also, you'll want to login to your domain registrar (I'm using (https://namecheap.com)).

It's helpful to have the following 4 tabs open to copy data from one to the other while going through this process.

  1. https://s3.console.aws.amazon.com
  2. https://console.aws.amazon.com/cloudfront
  3. https://console.aws.amazon.com/route53
  4. https://ap.www.namecheap.com/ (or your domain registrar)

Register a domain

I've recently switched to https://namecheap.com. They seem to be the cheapest ( their WHOIS privacy is free), their interface is pretty simple to use and I've not had any issues in the last few months of using them.

I used them to register this website electricvisions.com.

Create S3 Buckets and upload files

Apex domain bucket

Amazon requires the bucket name to match the domain name. So for the apex domain our bucket will be called electricvisions.com.

  1. Browse to https://s3.console.aws.amazon.com
  2. Click + Create Bucket
  3. Name and region, enter Bucket name which should match the domain name e.g. electricvisions.com, optionally change the region and click Next
  4. Configure options, click Next
  5. Permissions, Uncheck Block all public access and click Next
  6. Review, click Create Bucket
  7. Click Upload and drag in your HTML files (I also have a script for this: aws s3 sync output/electricvisions s3://electricvisions.com --delete. It requires the aws cli tools and basically mirrors what I have locally)
  8. Click the Bucket name, in our case electricvisions.com, to edit the settings
  9. Click Properties tab
  10. Click Static website hosting card
  11. Click Use this bucket to host a website
  12. Enter your root document in Index document (usually index.html)
  13. Enter your error document if you have one
  14. Click Save
  15. Click Permissions tab
  16. Click Bucket Policy
  17. Enter the following into the editor changing electricvisions to your domain and click Save
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::electricvisions.com/*"
        }
    ]
}

Www domain bucket

This will just redirect to the apex domain.

  1. Click + Create Bucket
  2. Name and region, enter Bucket name which should match the domain name e.g. electricvisions.com, optionally change the region and click Next
  3. Configure options, click Next
  4. Permissions, this time you can leave the defaults and click Next
  5. Review, click Create Bucket
  6. Click the Bucket name, in our case www.electricvisions.com, to edit the settings
  7. Click Properties tab
  8. Click Static website hosting card
  9. Click Redirect requests
  10. Enter electricvisions.com for the Target bucket or domain
  11. Click Save

Configure Route 53

We need to point Route 53 at the S3 website in order to verify the TLS certificates. Once that's done we can then point it at CloudFront.

  1. Browse to https://console.aws.amazon.com/route53
  2. Click Hosted Zones
  3. Click Create Hosted Zone
  4. Domain Name: electricvisions.com
  5. Click Create
  6. Click Create Record Set
  7. Check Alias Yes
  8. Click text box Alias Target and select electricvisions.com (S3 website)
  9. Click Create
  10. Click Create Record Set
  11. For Name enter www
  12. Check Alias Yes
  13. Click text box Alias Target and select www.electricvisions.com (S3 website)
  14. Click Create
  15. Make a note of the 4 NS records
  16. Go to https://namecheap.com
  17. Login and click Manage on electricvisions.com
  18. Under NAMESERVERS select Custom DNS from the list
  19. Add the 4 NS records noted previously

Create a CloudFront distribution

  1. Browse to https://console.aws.amazon.com/cloudfront
  2. Click Create Distribution
  3. Under Web click Get Started
  4. Click in the text box next to Origin Domain Name and select electricvisions.com.s3.amazonaws.com from the list
  5. Click Redirect HTTP to HTTPS (You always want to have secure connections)
  6. In Default Root Object enter index.html (or whatever you want / to go to)
  7. Click Create Distribution

This will take between 15 to 20 minutes. You'll need to wait for it to be deployed before you can complete the final step (./install ) in the following section.

Create TLS certificates

We'll now add TLS certificates to CloudFront using letsencrypt.org's free service.

Diego Lapiduz (@dlapiduz) created a great script on GitHub to automate the verification and upload of the certificates. I've added a little script to make it a one step process for apex and www domains on Windows.

git clone https://github.com/PhilT/certbot-s3front
cd certbot-s3front
docker build . -t certbot-s3front

If you haven't yet setup AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables you can do this once with:

setx AWS_ACCESS_KEY_ID <Your Amazon AWS_ACCESS_KEY_ID>
setx AWS_SECRET_ACCESS_KEY <Your Amazon AWS_SECRET_ACCESS_KEY>

Run the following to verify and send the certificates to CloudFront:

./install <your.domain.com> <your CLOUDFRONT_DESTRIBUTION_ID>

Back to CloudFront

Now the certificates have been uploaded we can add our domain names

  1. Browse to https://console.aws.amazon.com/cloudfront
  2. Click on the ID of the distribution you created previously
  3. Click Edit
  4. In Alternate Domain Names (CNAMEs) add electricvisions.com and www.electricvisions.com on separate lines
  5. Click Yes, Edit

Back to Route 53

Now the certificates are installed we can point Route 53 at CloudFront.

  1. Browse to https://console.aws.amazon.com/route53 or click on the Route53 tab you opened previously
  2. Click Hosted Zones
  3. Click electricvisions.com from the list of domains
  4. Click the electricvisions.com A record
  5. Click text box Alias Target select and delete what's there and select the CloudFront domain (it can take a while for the name to appear in the list, in that case just grab the Domain Name from CloudFront (something ending in cloudfront.net)).