Point your own domain at a service running on Tawa. The CLI handles DNS, TLS certificates, and ingress configuration automatically.
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
| Option | Description |
|---|---|
--cloudflare | Domain is on InsurEco Cloudflare — DNS auto-configured |
--external | External DNS provider — you add the CNAME yourself |
--env <environment> | Target environment: prod (default), sandbox, uat |
--service <name> | Target service (default: detected from directory) |
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.
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.
# 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
When you add a custom domain, the platform:
On subsequent deploys, verified custom domains are automatically included in the Helm values.
IMPORTANT: These rules exist because bypassing Tawa for domain management causes 502/522 errors and broken routing. Learn from past mistakes.
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
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
wrangler secret for Tawa servicesSecrets 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
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.
iec-cf:delete_dns_recordtawa domain add <domain> --cloudflare to do it properlytawa deploy --prod to update ingress| Symptom | Cause | Fix |
|---|---|---|
domain verify says "no CNAME record" | DNS not propagated yet | Wait and retry |
| Domain resolves but shows TLS error | Certificate not yet provisioned | Wait a few minutes |
| Domain resolves to wrong service | CNAME points to wrong hostname | Check tawa domain status |
| Domain works but stops after redeploy | Domain was not verified before deploy | Run tawa domain verify then redeploy |
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.
--cloudflare | --external | --direct | |
|---|---|---|---|
| DNS record | CF auto CNAME | CNAME → platform host | A record → ingress LB IP |
| TLS terminated at | Cloudflare edge | Cloudflare edge | In-cluster (cert-manager / Let's Encrypt) |
| Apex/root domains | CF flattening | hard (apex CNAME) | native (A record is legal at apex) |
| CDN / WAF / DDoS | yes | yes | no (origin hit directly) |
verify checks | n/a (auto) | CNAME → target | A → ingress LB IP |
| Cloudflare needed | yes | yes (for TLS) | no |
# 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
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.tawa domain verify confirms the domain's A record resolves to the ingress LB IP.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.Cloudflare/external domains are never given an in-cluster TLS block — only direct domains get cert-manager TLS.
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.
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