$1/month static website on AWS

This post describes the basic setup of this blog, which uses the following tools: Publii for static website content generation, AWS S3 and AWS Cloudfront for hosting, AWS Certificate Manager for HTTPS, AWS Route53 for DNS, and Gandi.net for domain name registration. This guide assumes you have an AWS account set up, all the AWS service configurations are accessible through console.aws.amazon.com. 

  1. Use Publii to set up the content for your site, it provides a rich editing experience for writing posts, but also provides enough low level control that customization is easy.
  2. To get your objects into S3, follow, https://getpublii.com/docs/setup-static-website-hosting-amazon-s3.html 
    1. You can use a Private bucket, with no public access, as all content will be cached on AWS CloudFront, only CloudFront will need direct read access.
  3. Next set up AWS Route53 > Hosted Zones
    1. Created Public Hosted Zone, with domain name, e.g. nelsonburton.com 
  4. Update your domain name hosting service to point to Route53's Nameservers
    1. I use Gandi.net to register a domain name, as they provide anonymization on WHOIS lookups, protecting my personal information. 
    2. Copy/paste the list of Nameservers from the Route53 NS record into your domain name configuration on Gandi's dashboard. 
    3. May need to pause and wait a few minutes for DNS to propagate here. 
  5. Using AWS Certificate Manager, create a certificate so your site can do HTTPS/TLS. 
    1. Request a public certificate, add both nelsonburton.com and  *.nelsonburton.com (so that www.nelsonburton.com works).
    2. DNS Validation, click on both Domains, under Pending Validation, click the "Create Record in Route 53."
    3. Wait ~5 - 10 minutes for you certificate to be created and validated.
  6. Using AWS Cloudfront, create a distribution that will serve your site's content
    1. Custom settings to configure
      1. For Origin Domain Name, choose the S3 bucket you just created (it should auto-complete from the drop-down). 
      2. Alternate Domain names > nelsonburton.com, *.nelsonburton.com
      3. Restrict Bucket Access > Yes
      4. Origin Access Identity > Create a New Identity
      5. Grant Read Permissions on Bucket > Yes, Update Bucket Policy
      6. Viewer Protocol Policy > Redirect HTTP to HTTPS
      7. Default Root Object > index.html
      8. SSL Certificate > Custom SSL Certificate . Choose the one you just created, it it doesn't show up, you haven't waited long enough.

    2. Wait 5-10 minutes for the Cloudfront distribution to be created.
  7. Head back to the AWS Route53 Configuration, configure your domain name to alias to the Cloudfront Distribution you just created.
    1. Create Record Set > A - IPV4 Address, leave Name blank, Alias > Yes, select Cloudfront Distribution you just created. 
    2. Create Record Set > CNAME - Name, use wildcard *.nelsonburton.com,  Alias > Yes, select Cloudfront Distribution you just created. 
  8. If you use "pretty URLs", for example, /page/2 actually refers to /page/2/index.html, you will need to add a Cloudfront function to automatically do the redirect, or else you'll end up with HTTP:403 AccessDenied errors. 
    1. To do so, go to the Cloudfront distribution. On the left tab, click Functions > Create Function, enter any name you please. 
    2. For the Function code, you can use the following,
      1. https://stackoverflow.com/questions/31017105/how-do-you-set-a-default-root-object-for-subdirectories-for-a-statically-hosted/69157535#69157535 
    3. Publish the function, and then on the publish page, click "Add Association", and associate it with the Cloudfront distribution you created above. 
    4. Now, going to /page/2/, will automatically redirect to fetch /page/2/index.html from your bucket. 

There you have it, if you now navigate to nelsonburton.com you are automatically redirected to the HTTPS endpoint. The S3 bucket is secured, and the Cloudfront distribution on top of the S3 bucket provides low latency access to your content.