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.
If your custom domain name needs a CloudFront distribution for edge caching use this guide with one small change to step #4 above.
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.
- AWS Console -> Route53
- Click on "Hosted zones"
- Click on your hosted zone. Ex:
- Click on "Hosted zone details" at the top.
- Note the "Hosted zone ID". Ex:
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.
- AWS Console -> Certificate Manager
- Click "Request a certificate" button.
- Select "Request a public certificate", and "Request a certificate" button.
- Domain name. Ex:
- Click "Next"
- Select "DNS validation", and "Review".
- Click "Confirm and request" button.
- Click the tiny disclosure triangle beside your domain name.
- Click the "Create record in Route 53" button then "Create" again in modal.
- Click "Continue"
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
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
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.
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:
www.example.comwith your domain name.
- If your HTTP API resource differs from
RailsHttpApi, use that name instead.
- If you opted out of step #3, replace these with your literal values:
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.
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
- AWS Console -> API Gateway
- Click "Custom domain names" on the left panel.
- Select your domain name in the list.
- Under "Endpoint configuration" find "API Gateway domain name"
Here are the steps to create your CloudFront Distribution:
- AWS Console -> CloudFront -> Create Distribution -> Web -> Get Started
- Origin Domain Name: d-xxxxxxxxxx.execute-api.us-east-1.amazonaws.com
- Origin Path: /production (or your deployed stage/env)
- Minimum Origin SSL Protocol: TLSv1.2
- Origin Protocol Policy: HTTPS Only
- Origin Custom Headers: X-Forwarded-Host www.example.com (⚠️ IMPORTANT)
- Viewer Protocol Policy: Redirect HTTP to HTTPS
- Allowed HTTP Methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
- Cached HTTP Methods: OPTIONS
- Cache Based on Selected Request Headers: Whitelist - Accept (⚠️ Allows
- Object Caching: Use Origin Cache Headers
- Forward Cookies: All
- Query String Forwarding and Caching: Forward all, cached based on all
- Compress Objects Automatically: Yes
- Alternate Domain Names (CNAMEs): www.example.com
- SSL Certificate: Custom SSL Certificate (select *.example.com from step above)
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.