Custom Domains
Configure dev and prod hostnames (docs/api/agent) on Azure Container Apps.
Custom Domains
This replaces packages/docs/CUSTOM-DOMAINS.md. Follow the steps below anytime you bring up a new environment or rotate domains.
Target hostnames
| Environment | Docs | API | Agent |
|---|---|---|---|
| Development | dev-docs.echo.onenine.ca | dev-api.echo.onenine.ca | dev-agent.echo.onenine.ca |
| Production | docs.echo.onenine.ca | api.echo.onenine.ca | agent.echo.onenine.ca |
All records are CNAMEs that point to the default Azure FQDN for each Container App (e.g., echo-docs-dev.<hash>.azurecontainerapps.io).
Step-by-step
-
Retrieve Azure hostnames + verification tokens
az login az containerapp show --resource-group echo-dev-rg --name echo-docs-dev \ --query "properties.configuration.ingress.fqdn" -o tsv az containerapp hostname list --resource-group echo-prod-rg --name echo-server-prodEvery
hostname listcall returns anasuidtoken Azure needs for TXT verification. -
Create DNS records
Type Name Value Notes CNAME docs<echo-docs-prod>.azurecontainerapps.ioProd docs CNAME api<echo-server-prod>.azurecontainerapps.ioProd API CNAME agent<agent-prod>.azurecontainerapps.ioProd agent CNAME dev-docs<echo-docs-dev>.azurecontainerapps.ioDev docs CNAME dev-api<echo-server-dev>.azurecontainerapps.ioDev API CNAME dev-agent<agent-dev>.azurecontainerapps.ioDev agent TXT asuid.docs<token>Provided by hostname listTXT asuid.api<token>TXT asuid.agent<token>TXT asuid.dev-docs<token>TXT asuid.dev-api<token>TXT asuid.dev-agent<token>Use your registrar’s DNS UI (Cloudflare, GoDaddy, Route 53, etc.). Disable CDN proxies—Container Apps needs direct CNAME resolution for certificate issuance.
-
Bind hostnames (if Terraform hasn’t already)
az containerapp hostname add \ --resource-group echo-dev-rg \ --name echo-docs-dev \ --hostname dev-docs.echo.onenine.caRepeat for each app/env combination.
-
Wait for managed certificates
Azure automatically provisions free certificates once DNS resolves. Check status:
az containerapp hostname list \ --resource-group echo-prod-rg \ --name echo-docs-prod \ --output tableProvisioning usually finishes within 15 minutes of DNS propagation.
-
Verify propagation
dig docs.echo.onenine.ca CNAME +short dig asuid.docs.echo.onenine.ca TXT +short curl -I https://dev-api.echo.onenine.caContinue testing until both CNAMEs and TXT records resolve to the expected targets.
Troubleshooting
| Symptom | Fix |
|---|---|
Custom domain binding not found | DNS isn’t pointing at Azure yet; double-check CNAME/TXT entries and wait for propagation (use https://www.whatsmydns.net/). |
SSL certificate pending | Certificates issue only after verification succeeds. Confirm TXT records and give it ~30 minutes. |
ERR_SSL_VERSION_OR_CIPHER_MISMATCH | Certificate still provisioning; re-check hostname list output. |
| Requests hitting old endpoints | Run az containerapp show ... --query "properties.configuration.ingress.fqdn" to confirm the current FQDN and update your CNAME. |
Security tips
- Add CAA records to
echo.onenine.cato restrict certificate issuance, e.g.echo.onenine.ca. CAA 0 issue "letsencrypt.org". - Turn on DNSSEC at your registrar if available.
- Monitor certificate state via Azure Monitor or periodic
curl -I https://docs.echo.onenine.ca.
Once these hostnames resolve, Container Apps delivers HTTPS traffic on the vanity domains and Terraform keeps the bindings declared in code.