Custom Domains
With Lambda, API Gateway, ACM and CloudFront
When we are ready to take our gofaas app live, we likely want to move the API off of the https://x19vpdk568.execute-api.us-east-1.amazonaws.com/Prod
API Gateway URL and onto our own domain, say https://api.gofaas.net
.
AWS supports this by creating a CloudFront distribution that will route requests to the API Gateway URL. The CloudFront CDN naturally enables custom domain names and SSL certificates.
AWS Config
We use two CloudFormation concepts: parameters and conditions.
Parameters are values we specify to configure AWS resources, in this case the desired domain name. Conditions are rules that determine if AWS resources are created, in this case we only create the resources if the domain name parameter is set.
The CloudFormation Template Anatomy reference offers more guidance on how parameters and conditions work.
One new resource is an AWS::CertificateManager::Certificate
(ACM cert) for our domain name. ACM generates and renews SSL certificates automatically for free, solving the cost and paperwork problems of SSL in the past.
The other new resources are an AWS::ApiGateway::DomainName
and AWS::ApiGateway::BasePathMapping
which represent the CloudFront distribution and mapping to our API Gateway endpoint respectively.
Conditions:
ApiDomainNameSpecified: !Not [!Equals [!Ref ApiDomainName, ""]]
Parameters:
ApiDomainName:
Default: ""
Type: String
Resources:
ApiGatewayCertificate:
Condition: ApiDomainNameSpecified
Properties:
DomainName: !Ref ApiDomainName
Type: AWS::CertificateManager::Certificate
ApiGatewayDomainName:
Condition: ApiDomainNameSpecified
Properties:
CertificateArn: !Ref ApiGatewayCertificate
DomainName: !Ref ApiDomainName
Type: AWS::ApiGateway::DomainName
ApiGatewayMapping:
Condition: ApiDomainNameSpecified
Properties:
DomainName: !Ref ApiGatewayDomainName
RestApiId: !Ref ServerlessRestApi
Stage: !Ref ServerlessRestApiProdStage
Type: AWS::ApiGateway::BasePathMapping
From template.yml
Deploy command
Now we deploy the app, specifying a value for the ApiDomainName
parameter. Behind the scenes AWS will automatically set up a cert and distribution.
Note that the cert requires email approval from someone that administers the root gofaas.net
domain. During this deploy, check your email and click through on the approval buttons or else the deploy will eventually fail and roll back. See the ACM Email Validation doc for more info.
Also note that creating the CloudFront distribution could take 15 minutes or more. Be patient while AWS sets up infrastructure all around the globe for our API…
$ make deploy PARAMS="ApiDomainName=api.gofaas.net"
...
ApiUrl https://api.gofaas.net
ApiDistributionDomainName d2bwnae7bzw1t6.cloudfront.net
DNS
The final step is to set up a DNS CNAME from our ApiDomainName
parameter (e.g. api.gofaas.net
) to the new ApiDistributionDomainName
output (e.g. d2bwnae7bzw1t6.cloudfront.net
).
If we are using Route53, this is easy to do through the UI:
In this case we could consider automating DNS setup by adding an conditional AWS::Route53::RecordSet
resource to our template…
After a few minutes we have our custom HTTPS API endpoint:
$ curl https://api.gofaas.net
<html><body><h1>gofaas dashboard</h1></body></html>
Summary
When building an app with CloudFormation, API Gateway and CloudFront we can:
- Serve our API from a custom domain
- Automate cert creation and renewal
- Distribute our API through a global CDN
We no longer have to worry about:
- Generating or paying for certificates
- Configuring HTTP servers
Our API is easier and cheaper to set up.