AWSGatsby
2021-02-094365 chars

How to Host Static Gatsby Website on AWS

I had a blog built using Gatsby and its starter library gatsby-starter-blog. It was hosted on AWS using the following services.

  • Route 53
  • Certificate Manager
  • S3
  • CloudFront

1. Route 53

I bought likaiguang.com. Created a hosted zone, hosted zone is a container for records (A, CNAME) about how to route traffic for a domain.

2. Certificate Manager

I first made sure the region selected was US East (N. Virginia) us-east-1, because later in CloudFront it would only show certificates in this region in the drop-down menu. Then I requested a SSL/TLS public certificate with the following domain names.

Validation was done by the CNAME method, AWS added some convenience by automatically adding the DNS records.

3. S3

I created an S3 bucket named likaiguang.com using a region near me: US West (Oregon) us-west-2.

S3 Bucket: likaiguang.com

Under Tab: Properties

I enabled bucket for static website hosting, selected Use this bucket to host a website and put index.html as index document, 404.html as error document.

Under Tab: Permissions

This was the bucket for storing my website, so I set the Block public access by turning off the four options below.

Block All Public Access

I set the Bucket Policy per below.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "LikaiguangPublicRead",
      "Effect": "Allow",
      "Principal": "*",
      "Action": ["s3:GetObject"],
      "Resource": ["arn:aws:s3:::likaiguang.com/*"]
    }
  ]
}

Upload Website from Gatsby Blog Repo

I installed AWS CLI on my local machine, created a IAM user and give it access to my S3 buckets. Ran aws configure to give it both Key ID and Access Key for the IAM user.

I installed Gatsby plugin npm i gatsby-plugin-s3. This enabled me to deploy the website to my S3 bucket in my Gatsby blog repo.

I added following configurations in the gatsby-config.js file.

{
  resolve: `gatsby-plugin-s3`,
  options: {
    bucketName: `likaiguang.com`,
    acl: null,
    protocol: `https`,
    hostname: `likaiguang.com`,
  },
},

I added script "deploy": "npm run build && gatsby-plugin-s3 deploy", in the package.json file.

Ran npm run deploy to build and upload my website to the S3 bucket.

4. CloudFront

In the distribution creation, I set the Origin Domain Name to the S3 Website endpoint likaiguang.com.s3-website-us-west-2.amazonaws.com, not the S3 API endpoint likaiguang.com.s3.amazonaws.com from the drop-down.

Changed Viewer Protocol Policy to Redirect HTTP to HTTPS.

Under Alternate Domain Names (CNAMEs) I added the two domain names.

Under SSL Certificate I selected Custom SSL Certificate (example.com): and chose the certificate in the drop-down I created previously in Certificate Manager.

Left everything else in default.

After creation, I was given a domain name for my distribution dryg4r2wprzbd.cloudfront.net.

5. Back to Route 53

After the CloudFront distribution was deployed, go back to the Route 53 console.

I added an A record for likaiguang.com pointing to the ALIAS dryg4r2wprzbd.cloudfront.net CloudFront distribution.

I added a CNAME record for www.likaiguang.com pointing to the same CloudFront distribution.

After the DNS propagate, my website should be online with https shortly.

6. Extra Credit: Restrict S3 Bucket Access Policy to a Specific HTTP Referer Header

Note: Referer is a misspelling of "Referrer", details can be found on this Wikipedia page.

Update the CloudFront distribution Origin Custom Headers with a custom Referer header:

  • Header Name: Referer
  • Value: likaiguang.com

Then update the S3 Bucket Policy to restrict access to this header with the following condition added.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "LikaiguangPublicRead",
      "Effect": "Allow",
      "Principal": "*",
      "Action": ["s3:GetObject"],
      "Resource": ["arn:aws:s3:::likaiguang.com/*"],
      "Condition": {
        "StringLike": {
          "aws:Referer": ["likaiguang.com"]
        }
      }
    }
  ]
}

Test the website to make sure everything works.