Custom Domains

Point your own domain at a service running on Tawa. The CLI handles DNS, TLS certificates, and ingress configuration automatically.

Add a Domain

tawa domain add mydomain.com

# Auto-configure DNS via InsurEco Cloudflare
tawa domain add mydomain.com --cloudflare

# Manual DNS — you'll add a CNAME yourself
tawa domain add mydomain.com --external
OptionDescription
--cloudflareDomain is on InsurEco Cloudflare — DNS auto-configured
--externalExternal DNS provider — you add the CNAME yourself
--env <environment>Target environment: prod (default), sandbox, uat
--service <name>Target service (default: detected from directory)

Cloudflare-Managed DNS

If the domain is on InsurEco's Cloudflare, everything is automatic:

tawa domain add portal.example.com --cloudflare

# ✓ DNS record created: portal.example.com → my-svc.tawa.insureco.io
# ✓ Domain registered in platform
# ✓ Domain is live at portal.example.com

A CNAME record is created and Cloudflare's Total TLS provisions a certificate automatically. The domain is live within seconds.

External DNS Provider

If you manage DNS elsewhere (GoDaddy, Route 53, etc.):

tawa domain add portal.example.com --external

# ℹ Please add a CNAME record at your DNS provider:
#     portal.example.com  →  my-svc.tawa.insureco.io
#
# ℹ After adding the record, run:
#   tawa domain verify portal.example.com

Add the CNAME at your provider, wait for propagation, then verify:

tawa domain verify portal.example.com
tawa deploy --prod   # apply ingress changes

DNS propagation can take up to 48 hours, though most providers complete within minutes.

Manage Domains

# Check DNS propagation status
tawa domain verify portal.example.com

# View full configuration details
tawa domain status portal.example.com

# List all custom domains
tawa domain list
tawa domain list --service my-svc

# Remove a domain
tawa domain remove portal.example.com

How It Works

When you add a custom domain, the platform:

  1. Creates a CNAME record pointing to your service's platform hostname
  2. Registers the domain in the service registry
  3. Patches the Kubernetes ingress to accept traffic on the new hostname
  4. Provisions a TLS certificate automatically (Cloudflare Total TLS or cert-manager)

On subsequent deploys, verified custom domains are automatically included in the Helm values.

Critical Rules — Do NOT Bypass Tawa

IMPORTANT: These rules exist because bypassing Tawa for domain management causes 502/522 errors and broken routing. Learn from past mistakes.

Never manually create DNS CNAMEs for Tawa services

Do NOT use iec-cf:create_dns_record or the Cloudflare dashboard to create CNAME records pointing to *.tawa.pro or *.tawa.insureco.io. The platform will not know about the domain and will return 502/522 errors.

Wrong:

# ❌ NEVER DO THIS — creates DNS but platform doesn't know about the domain
iec-cf:create_dns_record CNAME @ → policyeco-web.tawa.pro
# Result: 502/522 because ingress doesn't accept traffic for this hostname

Right:

# ✅ ALWAYS USE TAWA CLI — handles DNS + platform registration + ingress
tawa domain add mydomain.com --cloudflare

Never use Cloudflare Pages or Wrangler for Tawa services

If a service runs on Tawa, do NOT deploy it to Cloudflare Pages or use wrangler for custom domains. Tawa handles deployment, SSL, DNS, and ingress. Mixing platforms causes conflicts.

Wrong:

# ❌ NEVER DO THIS for a Tawa service
npx wrangler pages deploy dist
npx wrangler pages project create my-svc
# Then manually adding custom domains in CF Pages dashboard

Right:

# ✅ Deploy via Tawa
tawa deploy --prod
# ✅ Add domains via Tawa
tawa domain add mydomain.com --cloudflare

Never use wrangler secret for Tawa services

Secrets for Tawa services are managed via tawa secret set, not wrangler secret put. Wrangler secrets only apply to Cloudflare Workers — they are invisible to Tawa pods.

Wrong:

# ❌ This sets a secret on a CF Worker, NOT on your Tawa service
npx wrangler secret put MY_SECRET

Right:

# ✅ This sets a secret on your Tawa service pod
tawa secret set MY_SECRET

The correct workflow for multi-domain services

For services like PolicyEco that serve 30+ domains from one app:

# 1. Deploy the service first
tawa deploy --prod

# 2. Register domains (one at a time, or batch in a script)
tawa domain add policyeco.io --cloudflare
tawa domain add policybench.io --cloudflare
tawa domain add policyclaim.io --cloudflare
# ... repeat for each domain

# 3. Redeploy to pick up all registered domains in ingress
tawa deploy --prod

# 4. Your Express/Next.js app reads req.hostname to serve the right page

The service must already exist before adding domains. If tawa domain add says "Service not found", deploy first.

If you accidentally create a manual CNAME

  1. Delete the CNAME via iec-cf:delete_dns_record
  2. Run tawa domain add <domain> --cloudflare to do it properly
  3. Run tawa deploy --prod to update ingress

Troubleshooting

SymptomCauseFix
domain verify says "no CNAME record"DNS not propagated yetWait and retry
Domain resolves but shows TLS errorCertificate not yet provisionedWait a few minutes
Domain resolves to wrong serviceCNAME points to wrong hostnameCheck tawa domain status
Domain works but stops after redeployDomain was not verified before deployRun tawa domain verify then redeploy

Direct Mode (BYO-DNS, No Cloudflare)

Use --direct when a domain cannot use Cloudflare — e.g. the registrar's nameservers can't be moved (HostGator/cPanel, a client who won't delegate DNS) but the owner can still set an A record. Instead of Cloudflare terminating TLS at the edge, TLS is terminated in-cluster by cert-manager (Let's Encrypt).

NOTE: Default to --cloudflare. Direct mode trades away Cloudflare's CDN/WAF/DDoS protection and exposes the origin IP. Use it only when Cloudflare is genuinely not an option.

How direct mode differs

--cloudflare--external--direct
DNS recordCF auto CNAMECNAME → platform hostA record → ingress LB IP
TLS terminated atCloudflare edgeCloudflare edgeIn-cluster (cert-manager / Let's Encrypt)
Apex/root domainsCF flatteninghard (apex CNAME)native (A record is legal at apex)
CDN / WAF / DDoSyesyesno (origin hit directly)
verify checksn/a (auto)CNAME → targetA → ingress LB IP
Cloudflare neededyesyes (for TLS)no

Workflow

# Apex + www each registered (one record per hostname)
tawa domain add example.com --direct
tawa domain add www.example.com --direct

# The CLI prints the ingress LB IP to point an A record at:
#   example.com  →  137.184.244.227  (type A)

# After the A records resolve, verify (checks the A record, not a CNAME):
tawa domain verify example.com
tawa domain verify www.example.com

# Apply: injects the hosts + a TLS block + cert-manager annotation into the ingress
tawa deploy --prod

What the platform does

  1. tawa domain add --direct stores the domain with dnsProvider: direct and an expectedTarget of the cluster ingress LoadBalancer IP (INGRESS_TARGET on the builder). Fails with DIRECT_MODE_UNAVAILABLE if that IP isn't configured.
  2. tawa domain verify confirms the domain's A record resolves to the ingress LB IP.
  3. On tawa deploy, the builder injects the verified direct hosts into the builder-managed ingress, adds a tls block (secretName: {service}-custom-tls) and the annotation cert-manager.io/cluster-issuer: letsencrypt-prod.
  4. cert-manager solves a Let's Encrypt HTTP-01 challenge over port 80 — which works because the A record already lands on the ingress — issues the cert, and auto-renews it (~30 days before expiry). No Cloudflare, no manual certs.

Cloudflare/external domains are never given an in-cluster TLS block — only direct domains get cert-manager TLS.

Platform prerequisites

  • cert-manager installed in the cluster with a ClusterIssuer matching CERT_MANAGER_CLUSTER_ISSUER (default letsencrypt-prod, HTTP-01 solver on ingressClassName: nginx).
  • INGRESS_TARGET set on the builder to the ingress LB IP.

WARNING: Direct-mode customers hardcode the ingress LB IP in their DNS. If that IP changes (cluster migration, LB recreation), every direct-mode domain breaks. Pin a reserved/floating IP for the ingress LoadBalancer before relying on direct mode at scale.

First production user

sunnysfrozenyogurt.com (+ www), service sunnysfrozenyogurt-www, is the first domain on direct mode — DNS stayed at HostGator, an apex A record points at the ingress, and the Let's Encrypt cert is issued and renewed in-cluster.

Last updated: June 24, 2026