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.
- https://s3.console.aws.amazon.com
- https://console.aws.amazon.com/cloudfront
- https://console.aws.amazon.com/route53
- 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.
- Browse to https://s3.console.aws.amazon.com
- Click + Create Bucket
-
Name and region, enter Bucket name which should match the domain name
e.g.
electricvisions.com
, optionally change the region and click Next - Configure options, click Next
- Permissions, Uncheck Block all public access and click Next
- Review, click Create Bucket
-
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) - Click the Bucket name, in our case electricvisions.com, to edit the settings
- Click Properties tab
- Click Static website hosting card
- Click Use this bucket to host a website
- Enter your root document in Index document (usually
index.html
) - Enter your error document if you have one
- Click Save
- Click Permissions tab
- Click Bucket Policy
-
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.
- Click + Create Bucket
-
Name and region, enter Bucket name which should match the domain name
e.g.
electricvisions.com
, optionally change the region and click Next - Configure options, click Next
- Permissions, this time you can leave the defaults and click Next
- Review, click Create Bucket
- Click the Bucket name, in our case www.electricvisions.com, to edit the settings
- Click Properties tab
- Click Static website hosting card
- Click Redirect requests
- Enter
electricvisions.com
for the Target bucket or domain - 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.
- Browse to https://console.aws.amazon.com/route53
- Click Hosted Zones
- Click Create Hosted Zone
- Domain Name: electricvisions.com
- Click Create
- Click Create Record Set
- Check Alias Yes
- Click text box Alias Target and select electricvisions.com (S3 website)
- Click Create
- Click Create Record Set
- For Name enter www
- Check Alias Yes
- Click text box Alias Target and select www.electricvisions.com (S3 website)
- Click Create
- Make a note of the 4 NS records
- Go to https://namecheap.com
- Login and click Manage on electricvisions.com
- Under NAMESERVERS select Custom DNS from the list
- Add the 4 NS records noted previously
Create a CloudFront distribution
- Browse to https://console.aws.amazon.com/cloudfront
- Click Create Distribution
- Under Web click Get Started
- Click in the text box next to Origin Domain Name and select electricvisions.com.s3.amazonaws.com from the list
- Click Redirect HTTP to HTTPS (You always want to have secure connections)
-
In Default Root Object enter
index.html
(or whatever you want/
to go to) - 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
- Browse to https://console.aws.amazon.com/cloudfront
- Click on the ID of the distribution you created previously
- Click Edit
-
In Alternate Domain Names (CNAMEs) add
electricvisions.com
andwww.electricvisions.com
on separate lines - Click Yes, Edit
Back to Route 53
Now the certificates are installed we can point Route 53 at CloudFront.
- Browse to https://console.aws.amazon.com/route53 or click on the Route53 tab you opened previously
- Click Hosted Zones
- Click electricvisions.com from the list of domains
- Click the electricvisions.com A record
- 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)).