Deployments

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

EnvironmentDocsAPIAgent
Developmentdev-docs.echo.onenine.cadev-api.echo.onenine.cadev-agent.echo.onenine.ca
Productiondocs.echo.onenine.caapi.echo.onenine.caagent.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

  1. 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-prod

    Every hostname list call returns an asuid token Azure needs for TXT verification.

  2. Create DNS records

    TypeNameValueNotes
    CNAMEdocs<echo-docs-prod>.azurecontainerapps.ioProd docs
    CNAMEapi<echo-server-prod>.azurecontainerapps.ioProd API
    CNAMEagent<agent-prod>.azurecontainerapps.ioProd agent
    CNAMEdev-docs<echo-docs-dev>.azurecontainerapps.ioDev docs
    CNAMEdev-api<echo-server-dev>.azurecontainerapps.ioDev API
    CNAMEdev-agent<agent-dev>.azurecontainerapps.ioDev agent
    TXTasuid.docs<token>Provided by hostname list
    TXTasuid.api<token>
    TXTasuid.agent<token>
    TXTasuid.dev-docs<token>
    TXTasuid.dev-api<token>
    TXTasuid.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.

  3. 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.ca

    Repeat for each app/env combination.

  4. 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 table

    Provisioning usually finishes within 15 minutes of DNS propagation.

  5. Verify propagation

    dig docs.echo.onenine.ca CNAME +short
    dig asuid.docs.echo.onenine.ca TXT +short
    curl -I https://dev-api.echo.onenine.ca

    Continue testing until both CNAMEs and TXT records resolve to the expected targets.

Troubleshooting

SymptomFix
Custom domain binding not foundDNS isn’t pointing at Azure yet; double-check CNAME/TXT entries and wait for propagation (use https://www.whatsmydns.net/).
SSL certificate pendingCertificates issue only after verification succeeds. Confirm TXT records and give it ~30 minutes.
ERR_SSL_VERSION_OR_CIPHER_MISMATCHCertificate still provisioning; re-check hostname list output.
Requests hitting old endpointsRun 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.ca to 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.