Use Route 53 and Cloudfront for My Website

Recently I tested with migrating wordpress site to Hugo, and host it in AWS s3 static website. In this excerise, I will use Route 53 for the dns service and Cloudfront for content delivery, before starting, a working s3 static website should be ready, please refer to How to Create Site With Hugo to see how to setup a hugo site in S3.

Request a certificate in AWS Certificate Manager

  • Add domain names: *.example.com and example.com
  • Select validation method: DNS validation
  • Create record in Route 53 or manually add a CNAME record in the DNS configuration
  • Wait for Certificate status changing to Issued

Create Cloudfront Distribution

  • Origin Settings
    • Origin Domain Name: the s3 static website Url
    • Restrict Bucket Access: Yes
    • Origin Access Identity: Create a New Identity
    • Grant Read Permissions on Bucket: Yes, Update Bucket Policy
  • Default Cache Behavior Settings
    • Viewer Protocol Policy: Redirect HTTP to HTTPS
    • Edge Function Associations: (due to Cloudfront doesn’t support Default Root Ojbect for subdirectoy, so need add redirect to make it work)
      • Go to AWS serverlessrepo - standard-redirects-for-cloudfront and hit Deploy
      • Once Deployed, open serverlessrepo-standard-redirects-for-cloudfront stack
      • Go to Resources tab, locate Logical ID is StandardRedirectsForCloudFrontRole and Type is AWS::IAM::Role, click the Phyical ID link
      • Edit trust relationship in Trust relationships tab, then add “edgelambda.amazonaws.com” in the Service array, and the policy after the change is:
      {
      "Version": "2012-10-17",
      "Statement": [
          {
          "Effect": "Allow",
          "Principal": {
              "Service": [
              "lambda.amazonaws.com",
              "edgelambda.amazonaws.com"
              ]
          },
          "Action": "sts:AssumeRole"
          }
      ]
      }
      
      • Go to Outputs tab and Copy the Value of StandardRedirectsForCloudFrontVersionOutput key
      • Add a Lambda@Edge Function with
        • CloudFront Event: Origin Request
        • Function ARN/Name: the value of StandardRedirectsForCloudFrontVersionOutput from previous step
      • Below is the code deployed by standard-redirects-for-cloudfront
      'use strict';
      /*
      Copyright 2017-2019 DigitalSailors e.K.
      
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
      You may obtain a copy of the License at
      
          http://www.apache.org/licenses/LICENSE-2.0
      
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      See the License for the specific language governing permissions and
      limitations under the License.
      */
      
      exports.handler = (event, context, callback) => {
      const request = event.Records[0].cf.request;
      
      let prefixPath; // needed for 2nd condition
      
      if (request.uri.match('.+/$')) {
          request.uri += 'index.html';
          callback(null, request);
      } else if (prefixPath = request.uri.match('(.+)/index.html')) {
          const response = {
          status: '301',
          statusDescription: 'Found',
          headers: {
              location: [{
              key: 'Location', value: prefixPath[1] + '/',
              }],
          }
          };
          callback(null, response);
      } else if (request.uri.match('/[^/.]+$')) {
          const response = {
          status: '301',
          statusDescription: 'Found',
          headers: {
              location: [{
              key: 'Location', value: request.uri + '/',
              }],
          }
          };
          callback(null, response);
      } else {
          callback(null, request);
      }
      }
      
  • Distribution Settings
    • Alternate Domain Names: www.example.com and example.com
    • SSL Certificate: Custom SSL Certificate and select a certificate
    • Default Root Object: index.html
  • Click Create Distribution
  • Add Error Pages
    • Open the Distribution and go to Error Pages tab
    • Click Create Custom Error Response button, and enter values below, then click Create button
      • HTTP Error Code: 403: Forbidden
      • Customize Error Response: Yes
      • Response Page Path: /404.html
      • HTTP Response Code: 404: Not Found

Setup DNS

  • Add a Hosted zones in Route 53 for domain example.com
  • If domain is not registered with AWS, go to Domain Registrar (for example GoDaddy)’s website, update the Namservers in Domain Settings->DNS Management with the value from previous step
  • Click and open the hostzone, example.com
  • Click Create Record - example.com
    • Record name: example.com
    • Record type: A
    • Alias: Yes
    • Route traffic to: Alias to CloudFront distribution, and choose the distribution created earlier ()
  • Click Create Record - www.example.com
    • Record name: www.example.com
    • Record type: A
    • Alias: Yes
    • Route traffic to: Alias to another record in this hosted zone, and choose the a record created earlier which is example.com.

Reference