Skip to main content
Managed custom domains are coming soon. Ravion will handle certificate creation and attachment for you. Until then, use the steps in this guide to manage custom domains yourself.
Ravion doesn’t manage domains for you automatically yet. Instead, you compose the same building blocks you use for everything else: an ACM Certificate module for TLS, the module that terminates traffic (an ECS cluster, whose load balancers serve your services, or CloudFront), and DNS records — managed either with a Route 53 module or in an external DNS provider. The process at a glance:
  1. Request the certificate with an rvn-acm-certificate module.
  2. Validate the certificate by creating the DNS validation record ACM asks for.
  3. Attach the issued certificate to the module that terminates TLS.
  4. Point the traffic record at the endpoint and, optionally, shift traffic gradually.

How custom domains fit together

Two different DNS records are involved, and they play separate roles:
  • The validation record is a CNAME that proves to ACM that you control the domain. It never receives traffic — ACM just checks that it resolves, then issues the certificate. It stays in place for automatic certificate renewal.
  • The traffic record is the record users actually hit: app.example.com pointing at your CloudFront distribution or ECS cluster load balancer.
Order matters. The certificate must be validated before AWS lets you attach it to an HTTPS or TLS listener, and the certificate must be attached before the endpoint can serve your domain. Only then do you change the traffic record — which means your current site keeps working untouched until the final cutover. The certificate always lives in its own rvn-acm-certificate module instance. The module that terminates TLS references it as an input. Which module that is depends on how you expose the service:
CloudFront is a global service, so any certificate used for CloudFront aliases must be requested in us-east-1, regardless of where the rest of your infrastructure runs. Certificates for an ECS cluster’s load balancers must be in the same region as the cluster.

Step 1: Request the certificate

Add an rvn-acm-certificate module instance to your environment. The examples below use the project config file; you can do the same from the dashboard by adding a module instance of type rvn-acm-certificate and filling in the same fields. ACM public certificates use DNS validation: ACM gives you one CNAME record per domain on the certificate, and issues the certificate once those records resolve. Decide before the first apply how those records get created, because route53_validation_records_creation_enabled is immutable after creation:
If the domain already has a Route 53 public hosted zone in the same AWS account, let the certificate stack create the validation records and wait for issuance in a single apply:
ravion.yaml
Route 53 automation is scoped to a single hosted zone. If your certificate covers domains whose validation records belong in multiple zones, use the external DNS configuration instead and create each record in its zone.
Keep these rules in mind when filling in the certificate fields:
  • domain_name is the primary fully qualified domain name, such as app.example.com, or a wildcard like *.example.com. It’s immutable after creation — to change it, create a new certificate module.
  • aws_region must match where the certificate is consumed: the ECS cluster’s region, or us-east-1 for CloudFront.
Apply the change to run the stack pipeline:
--autoapprove applies the Terraform plan without a manual approval gate. Drop the flag if you want to review the plan before it applies.

Step 2: Validate the certificate with DNS

If you enabled Route 53 automation in Step 1, you’re done — the apply created the validation CNAMEs in the hosted zone and blocked until ACM issued the certificate, which usually takes a few minutes. If DNS is managed externally, create the validation records yourself:
1

Copy the validation records from the stack outputs

Open the certificate module in the dashboard and check the stack outputs, or fetch them from the CLI:
Each domain on the certificate gets one validation record with a name like _abc123.app.example.com, type CNAME, and a value like _xyz789.acm-validations.aws.
2

Create the CNAME records in your DNS provider

For each validation record, create a CNAME record with the exact name and value from the outputs. Two provider-specific gotchas:
  • Cloudflare: set the record to DNS only (gray cloud). Proxied records break ACM validation.
  • Some providers automatically append your zone name — if the output name is _abc123.app.example.com and your zone is example.com, you may need to enter only _abc123.app.
3

Verify the record resolves

The answer should be the acm-validations.aws. value. ACM then typically issues the certificate within a few minutes, though DNS propagation can take longer.
4

Optionally enable the issuance wait

Once validation records exist, you can set certificate_validation_wait_enabled: true and apply again. This field is mutable, and enabling it makes future applies fail fast if the certificate ever can’t validate. You can also just confirm the certificate shows Issued in the ACM console.

Step 3: Attach the certificate to your module

Reference the certificate module from the module that terminates TLS, using moduleGivenIdRef in the config file or the module picker in the dashboard.
The certificate attaches to the cluster, because the ECS cluster owns the ALB and its HTTPS listener. Each web service then claims its hostnames with Domain host rules (host_header_values), which become ALB listener rules:
ravion.yaml
If one ALB serves several domains, use a wildcard certificate that covers them — for example, *.example.com covers both api.example.com and auth.example.com — and give each service its own host_header_values. Use private_alb_certificate instead for services behind the private ALB.
Apply the config change with ravion project config apply <project-id> --file ravion.yaml --autoapprove. If the certificate is still Pending validation, AWS rejects attaching it to an HTTPS or TLS listener — finish Step 2 first.

Step 4: Point DNS at the endpoint

Nothing reaches the new endpoint until DNS says so. That makes DNS your traffic switch — and your rollback lever.
1

Find the endpoint hostname

Get the target hostname from the terminating module’s stack outputs in the dashboard, or with ravion stack get <stack-id> --json:
  • ALB / NLB: the load balancer DNS name, like my-alb-123456.us-east-2.elb.amazonaws.com
  • CloudFront / static site: the distribution domain, like d1234abcd.cloudfront.net
2

Test before changing DNS

Verify the endpoint serves your domain correctly without touching DNS:
You should get a valid TLS handshake for app.example.com and the expected response. A certificate error here means the wrong certificate is attached; an HTTP 404/421 usually means the host rules or aliases don’t match the domain.
3

Optionally lower the TTL on the existing record

If the domain currently points somewhere else, lower the record’s TTL to 60 seconds and wait for the old TTL to expire before cutting over. This shortens the window where clients keep hitting the old target, and makes rollback near-instant.
4

Create or update the DNS record

Use an rvn-route53 module instance and an alias record. Alias records are the standard way to point at AWS targets and work at the zone apex:
ravion.yaml
For an ALB or NLB target, use the load balancer’s DNS name as alias_name and its canonical hosted zone ID as alias_zone_id (both are in the load balancer’s details in the AWS console).
5

Verify the cutover

Once responses come from the new endpoint and error rates look normal in the module’s metrics and logs, raise the TTL back to a normal value such as 300 seconds.

Optional: shift traffic gradually

For higher-stakes cutovers, use Route 53 weighted routing to move a fraction of traffic at a time instead of flipping everything at once. Create two records with the same name and type, each with a set_identifier and a weight:
ravion.yaml
Then ramp in stages:
  1. Start at 90/10 and watch error rates and latency on the new target.
  2. Move through 50/50 to 0/100, applying the config change at each stage.
  3. Once the old target has drained, remove the old record and the routing_policy fields to return to a simple record.
Traffic splits are approximate — DNS caching means clients move over gradually as their cached answers expire. Rollback at any stage is just shifting the weights back.
Weighted DNS shifts traffic between endpoints, such as an old load balancer and a new one. For shifting traffic between application versions on the same endpoint, use the built-in blue/green, canary, and linear deploy strategies instead.

Certificate renewal

ACM renews DNS-validated certificates automatically. Starting 45 days before expiration, ACM re-validates and renews the certificate when both conditions hold:
  • The certificate is in use by an AWS service — attached to your ALB, NLB, or CloudFront distribution.
  • All validation CNAME records are still present and resolvable via public DNS.
Renewal happens in place: the certificate keeps the same ARN, so your module references keep working with no config change, Terraform plan, or redeploy. Because of this, never delete the validation CNAME records after issuance — removing them (or detaching the certificate from every AWS resource) silently breaks the next renewal. If ACM can’t re-validate, it notifies you through AWS Health and EventBridge events starting 30 days before expiration.

Troubleshooting

ACM Certificate

Full input reference for rvn-acm-certificate.

Route 53 DNS

Hosted zones, records, and routing policies with rvn-route53.

CloudFront CDN

Aliases, certificates, and origin routing for rvn-cloudfront.

ECS Cluster

ALB certificates and listeners on rvn-ecs-cluster.

Static Hosting

Custom domains for static sites with rvn-aws-static.

Deploy strategies

Blue/green, canary, and linear traffic shifting between app versions.