AWS Developer Blog

Configuring custom domain names with AWS Chalice

Version 1.16.0 of AWS Chalice, a framework for writing serverless applications in Python, adds support for custom domain names when creating REST and WebSocket APIs. In this post, we’ll show how to associate your own domain name with a REST API we create.

When deploying REST APIs with Chalice, Amazon API Gateway automatically generates the domain name of your API endpoint. Let’s start by creating a Chalice application with a regional endpoint for our rest API so we can see the auto-generated domain name. After that, we’ll associate our custom domain with this API.

First, install Chalice in a virtual environment. We’re using Python 3.7 for this example.

$ python3 -m venv /tmp/venv37
$ . /tmp/venv37/bin/activate
$ pip install chalice
$ chalice new-project customdomain
$ cd customdomain

Next, we’ll change our endpoint to be a REGIONAL endpoint type. The default endpoint type for Chalice applications is EDGE. To do this, update your .chalice/config.json file with the api_gateway_endpoint_type parameter:

{
  "version": "2.0",
  "app_name": "customdomain",
  "api_gateway_endpoint_type": "REGIONAL",
  "stages": {
    "dev": {
      "api_gateway_stage": "api"
    }
  }
}

Now if we deploy our application, we’ll see the auto-generated domain name that API Gateway creates for us.

$ chalice deploy
Creating deployment package.
Creating IAM role: customdomain-dev
Creating lambda function: customdomain-dev
Creating Rest API
Resources deployed:
  - Lambda ARN: arn:aws:lambda:us-west-2:12345:function:customdomain-dev
  - Rest API URL: https://abcd.execute-api.us-west-2.amazonaws.com/api/

This https://abcd.execute-api.us-west-2.amazonaws.com/api/ endpoint is what you’ll configure your HTTP client to use when invoking your REST API.

Now we’ll look at how you can configure a Chalice application to use your own custom domain name.

Initial Setup

In order to set this up, we first need to configure our domain name. In this example I’ll be using a domain name of api.chalice-demo-app.com. We’ll be managing our domain name with Amazon Route 53 and we’ll use AWS Certificate Manager (ACM) to manage our SSL/TLS certificate.

You can follow the documentation for requesting a public certificate. You’ll need to ensure that you create your ACM certificate in the same region as your REST API. In this example, I’m using us-west-2. Once you’ve created your ACM certificate, you should have a CertificateArn ARN you can use. Be sure to save this value for later, we’ll need it when configuring our Chalice app.

You’ll also need the hosted zone ID of your domain name in Route53. You can find the hosted zone Id for your domain by running this CLI command and finding the hosted zone that corresponds to your domain name.

$ aws route53 list-hosted-zones
{
    "HostedZones": [
        {
            "Id": "/hostedzone/Z0560960ABCDEFGABCDE",
            "Name": "chalice-demo-app.com.",
            "CallerReference": "1658FD20-6694-E292-8259-DB8B62704A38",
            "Config": {
                "Comment": "",
                "PrivateZone": false
            },
            "ResourceRecordSetCount": 3
        }
    ]
}

With this output above, my hosted zone id is Z0560960ABCDEFGABCDE.

Chalice Configuration

Connecting your custom domain to your Chalice application consists of two parts. First we must configure our API Gateway endpoint so it knows about our custom domain name. This is done through Chalice configuration options. Second, we must configure our custom domain to point to our new application. This is done through Route53.

In order to configure Chalice with this custom domain name, you need to the specify your custom domain name as well as which ACM certificate to use. These values are specified in your .chalice/config.json file. Update your config file as shown below but replace the values of domain_name and certificate_arn with your own values. The certificate_arn should match the ARN of your ACM certificate you created earlier.

{
  "version": "2.0",
  "app_name": "customdomain",
  "api_gateway_endpoint_type": "REGIONAL",
  "stages": {
    "dev": {
      "api_gateway_custom_domain": {
        "domain_name": "api.chalice-demo-app.com",
        "certificate_arn": "arn:aws:acm:us-west-2:12345:certificate/your-uuid"
      },
      "api_gateway_stage": "api"
    }
  }
}

When we now redeploy our application, we’ll see that we’ve now created and associated a domain name with our REST API: Once I’ve done that I can deploy my Chalice application and my REST API will be configured with a new custom domain name:

$ chalice deploy
Creating deployment package.
Updating policy for IAM role: customdomain-dev
Updating lambda function: customdomain-dev
Updating rest API
Updating custom domain name: api.chalice-demo-app.com
Resources deployed:
  - Lambda ARN: arn:aws:lambda:us-west-2:123456789012:function:customdomain-dev
  - Rest API URL: https://abcdefg.execute-api.us-west-2.amazonaws.com/api/
  - Custom domain name:
      HostedZoneId: Z1UJRXOUMOOFQ8
      AliasDomainName: d-ebljg1s242.execute-api.us-west-2.amazonaws.com

Note that a HostedZoneId and an AliasDomainName are now shown in the output. We’ll now use these values to configure our hosted zone in Route53 with an ALIAS record. To do this, we can run this AWS CLI command:

$ aws route53 change-resource-record-sets --hosted-zone-id Z0560960ABCDEFGABCDE --change-batch \
'{
  "Changes": [
    {
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "api.chalice-demo-app.com",
        "Type": "A",
        "AliasTarget": {
          "DNSName": "d-ebljg1s242.execute-api.us-west-2.amazonaws.com",
          "HostedZoneId": "Z1UJRXOUMOOFQ8",
          "EvaluateTargetHealth": false
        }
      }
    }
  ]
}'

Make sure to use your own values for the Name, DNSName, and HostedZoneId. The HostedZoneId should be the value shown in the output of the chalice deploy command.

If you’re not using Route53 to manage your hosted zone, you’ll need to create a CNAME record that points to the AliasDomainName for your API using your third-party domain registrar.

Our custom domain is now setup. We can now verify that we can make requests to our custom domain.

$ curl https://api.chalice-demo-app.com/
{"hello":"world"}

Next Steps

You can configure custom domain names for a REST API as well as WebSocket APIs. The documentation also shows additional parameters that can be specified when configuring a custom domain. Try out the latest version of Chalice today, and let us know what you think. You can share feedback with us on our GitHub repo.