Custom Domain Names, CloudFront, & SSL

The new API Gateway HTTP API makes it easy to configure your application with a custom domain name using CloudFormation. These steps will get you there.

  1. Route53 Information
  2. SSL/TLS Certificate with ACM
  3. SSM Template Parameters
  4. CloudFormation Code

If your custom domain name needs a CloudFront distribution for edge caching use this guide with one small change to step #4 above.

  1. CloudFront Distribution

Route53 Information

The following steps assume you have a domain managed by Route53. Before proceeding you will need the Hosted Zone ID for the domain zone you are going to use.

SSL/TLS Certificate with ACM

We are going to use AWS Certificate Manager to secure your HTTPS traffic under your custom domain. Again, this assumes your domain is setup in Route53 since you will need to validate the certificate and AWS makes that super easy with DNS.

Verification will take about 3 minutes. From the Certificate Manager dashboard, you can wait and/or hit the 🔄 button and the Status will change from "Pending validation" to "Issued".

SSM Template Parameters

ℹī¸ Skip this section if you do not need to deploy your application to distinct staging & production AWS accounts. If so, make sure to replace the references to both CertificateArn and HostedZoneId in step #4's CloudFormation code.

In this example we are going to use a more interesting form of Environment & Configuration. Instead of environment variables for our application, we want to leverage another CloudFormation Parameter for our SAM template.yaml file. Using SSM parameter types will allow the template to use differnt domain names when deployed to different AWS accounts. Add these to the Parameters: section of your template.yaml file.

HostedZoneId:
  Type: 'AWS::SSM::Parameter::Value<String>'
  Default: '/config/route53/example.com'

CertificateArn:
  Type: 'AWS::SSM::Parameter::Value<String>'
  Default: '/config/ssl/cert/example.com'

Open up SSM in each AWS account and create a new parameter for each path above. The value for HostedZoneId would be from step #1 above and CertificateArn would be from step #2.

CloudFormation Code

Once we have both our Hosted Zone ID and the ARN of our SSL certificate, we can use CloudFormation in our SAM template.yaml file to create our custom domain name. We are going to use the following resources.

Add this YAML code to the Resources: section of your template.yaml file. Remember to:

RailsDomainName:
  Type: AWS::ApiGatewayV2::DomainName
  Properties:
    DomainName: www.example.com
    DomainNameConfigurations:
      - CertificateArn: !Ref CertificateArn
        EndpointType: REGIONAL
        SecurityPolicy: TLS_1_2

RailsApiMapping:
  Type: AWS::ApiGatewayV2::ApiMapping
  DependsOn: RailsDomainName
  Properties:
    ApiId: !Ref RailsHttpApi
    DomainName: www.example.com
    Stage: !Ref RailsEnv

RailsRecordSet:
  Type: AWS::Route53::RecordSetGroup
  DependsOn: RailsApiMapping
  Properties:
    HostedZoneId: !Ref HostedZoneId
    RecordSets:
      - Name: www.example.com
        Type: A
        AliasTarget:
          HostedZoneId: !GetAtt RailsDomainName.RegionalHostedZoneId
          DNSName: !GetAtt RailsDomainName.RegionalDomainName
          EvaluateTargetHealth: false

From here you can do a ./bin/deploy. You can now access your Rails application's API Gateway HTTP API using a custom domain name.

CloudFront Distribution

This part is optional and requires a small chage to step #4 above by removing the RailsRecordSet resource from your template.yaml file. The goal here is to set your domain name www.example.com as an alias to this CloudFront distribution.

Before you begin, you need the "API Gateway domain name" that was created via the AWS::ApiGatewayV2::DomainName resource above. You can find it by doing the following. It will look something like d-xxxxxxxxxx.execute-api.us-east-1.amazonaws.com.

Here are the steps to create your CloudFront Distribution:

This process takes a while to fully deploy. Once done you will have a CloudFront domain name looking something like dxxxxxxxxxxxxx.cloudfront.net. Head to Route53 and create an alias for www.example.com to this CloudFront distibution domain name.