From ad783486d5aca2aca5b67023c39245eb7e556164 Mon Sep 17 00:00:00 2001 From: Hang Yin Date: Sat, 12 Sep 2026 03:33:09 +0000 Subject: [PATCH] custom-domain: stop publishing an underscore-leading CNAME target GATEWAY_DOMAIN is published as the custom domain's CNAME target, and the examples used `_.`. Android's resolver runs every name in an A/AAAA answer through res_hnok, including the CNAME RDATA, and res_hnok accepts `_` only between two alphanumerics. A label starting with `_` fails, getanswer() drops the chain, and the hostname is unresolvable on Android -- while glibc, which permits `_` anywhere, resolves it fine, so the breakage never shows up in Linux testing. Switch the examples to `gateway.`. The label is arbitrary: the gateway zone is a wildcard, the name never travels on the wire, and routing is driven by the client's SNI plus the app-address TXT record. `_.` keeps resolving, so existing deployments are unaffected by this change -- they are simply still broken on Android until they move. Co-Authored-By: Claude Opus 5 --- custom-domain/dstack-ingress/DNS_PROVIDERS.md | 8 ++++---- custom-domain/dstack-ingress/README.md | 16 +++++++++++----- .../dstack-ingress/docker-compose.multi.yaml | 2 +- .../dstack-ingress/scripts/tests/e2e-test.sh | 4 ++-- k3s/docker-compose.yaml | 2 +- 5 files changed, 19 insertions(+), 13 deletions(-) diff --git a/custom-domain/dstack-ingress/DNS_PROVIDERS.md b/custom-domain/dstack-ingress/DNS_PROVIDERS.md index 845d288c..6e8dd6b1 100644 --- a/custom-domain/dstack-ingress/DNS_PROVIDERS.md +++ b/custom-domain/dstack-ingress/DNS_PROVIDERS.md @@ -14,7 +14,7 @@ This guide explains how to configure dstack-ingress to work with different DNS p ### Common Variables (Required for all providers) - `DOMAIN` - Your custom domain (e.g., `app.example.com`) -- `GATEWAY_DOMAIN` - dstack gateway domain (e.g., `_.dstack-prod5.phala.network`) +- `GATEWAY_DOMAIN` - dstack gateway domain (e.g., `gateway.dstack-prod5.phala.network`) - `CERTBOT_EMAIL` - Email for Let's Encrypt registration - `TARGET_ENDPOINT` - Backend application endpoint to proxy to - `DNS_PROVIDER` - DNS provider to use (`cloudflare`, `linode`, `namecheap`) @@ -124,7 +124,7 @@ services: # Common configuration - DNS_PROVIDER=linode - DOMAIN=app.example.com - - GATEWAY_DOMAIN=_.dstack-prod5.phala.network + - GATEWAY_DOMAIN=gateway.dstack-prod5.phala.network - CERTBOT_EMAIL=admin@example.com - TARGET_ENDPOINT=http://backend:8080 @@ -149,7 +149,7 @@ services: # Common configuration - DNS_PROVIDER=namecheap - DOMAIN=app.example.com - - GATEWAY_DOMAIN=_.dstack-prod5.phala.network + - GATEWAY_DOMAIN=gateway.dstack-prod5.phala.network - CERTBOT_EMAIL=admin@example.com - TARGET_ENDPOINT=http://backend:8080 @@ -177,7 +177,7 @@ services: environment: DNS_PROVIDER: route53 DOMAIN: app.example.com - GATEWAY_DOMAIN: _.${DSTACK_GATEWAY_DOMAIN} + GATEWAY_DOMAIN: gateway.${DSTACK_GATEWAY_DOMAIN} AWS_REGION: ${AWS_REGION} AWS_ROLE_ARN: ${AWS_ROLE_ARN} diff --git a/custom-domain/dstack-ingress/README.md b/custom-domain/dstack-ingress/README.md index e80ce9f7..d8b5842c 100644 --- a/custom-domain/dstack-ingress/README.md +++ b/custom-domain/dstack-ingress/README.md @@ -41,7 +41,7 @@ services: environment: - CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_TOKEN} - DOMAIN=*.myapp.com - - GATEWAY_DOMAIN=_.dstack-prod5.phala.network + - GATEWAY_DOMAIN=gateway.dstack-prod5.phala.network - CERTBOT_EMAIL=${CERTBOT_EMAIL} - SET_CAA=true - TARGET_ENDPOINT=http://app:80 @@ -109,7 +109,7 @@ services: DNS_PROVIDER: cloudflare CLOUDFLARE_API_TOKEN: ${CLOUDFLARE_API_TOKEN} CERTBOT_EMAIL: ${CERTBOT_EMAIL} - GATEWAY_DOMAIN: _.dstack-prod5.phala.network + GATEWAY_DOMAIN: gateway.dstack-prod5.phala.network SET_CAA: true DOMAINS: | app.example.com @@ -158,10 +158,16 @@ environment: |----------|-------------| | `DOMAIN` | Your domain (single-domain mode). Supports wildcards (`*.example.com`) | | `TARGET_ENDPOINT` | Backend address, e.g. `app:80` or `http://app:80` | -| `GATEWAY_DOMAIN` | dstack gateway domain (e.g. `_.dstack-prod5.phala.network`) | +| `GATEWAY_DOMAIN` | dstack gateway domain (e.g. `gateway.dstack-prod5.phala.network`) | | `ACME_EMAIL` | *(optional)* ACME contact address, in either mode. `CERTBOT_EMAIL` is the historical name and still works. See below — it is optional, and published | | `DNS_PROVIDER` | DNS provider (`cloudflare`, `linode`, `namecheap`) | +`GATEWAY_DOMAIN` is published as your domain's CNAME target, so its first label +must start with a letter or digit. Android's resolver rejects a leading +underscore in an address lookup, CNAME target included, so the older +`_.` form resolves everywhere except Android. The label is +otherwise arbitrary — the gateway answers every name under its domain. + ### Optional | Variable | Default | Description | @@ -330,7 +336,7 @@ services: - TARGET_ENDPOINT=http://app:80 # Printed as the CNAME target, and used to verify that the hostname # really resolves to the gateway before issuance starts. - - GATEWAY_DOMAIN=_.dstack-prod5.phala.network + - GATEWAY_DOMAIN=gateway.dstack-prod5.phala.network # - ACME_EMAIL=you@example.com # optional, and published (see below) # - DNS_SETUP_MODE=wait # default; blocks until the records exist ports: @@ -349,7 +355,7 @@ public DNS until they are visible: DNS records required for app.example.com ========================================================================== CNAME app.example.com - -> _.dstack-prod5.phala.network + -> gateway.dstack-prod5.phala.network TXT _dstack-app-address.app.example.com -> b1ea785543bbbb19ce9de33744321360992bf63b:443 CAA app.example.com diff --git a/custom-domain/dstack-ingress/docker-compose.multi.yaml b/custom-domain/dstack-ingress/docker-compose.multi.yaml index e2fe93bd..e7fa2d01 100644 --- a/custom-domain/dstack-ingress/docker-compose.multi.yaml +++ b/custom-domain/dstack-ingress/docker-compose.multi.yaml @@ -7,7 +7,7 @@ services: DNS_PROVIDER: cloudflare CLOUDFLARE_API_TOKEN: ${CLOUDFLARE_API_TOKEN} CERTBOT_EMAIL: ${CERTBOT_EMAIL} - GATEWAY_DOMAIN: _.dstack-prod5.phala.network + GATEWAY_DOMAIN: gateway.dstack-prod5.phala.network SET_CAA: true DOMAINS: | app.example.com diff --git a/custom-domain/dstack-ingress/scripts/tests/e2e-test.sh b/custom-domain/dstack-ingress/scripts/tests/e2e-test.sh index 7352146f..029eda42 100755 --- a/custom-domain/dstack-ingress/scripts/tests/e2e-test.sh +++ b/custom-domain/dstack-ingress/scripts/tests/e2e-test.sh @@ -11,7 +11,7 @@ # CERTBOT_EMAIL - Email for Let's Encrypt registration # # Optional env vars: -# GATEWAY_DOMAIN - dstack gateway domain (default: _.dstack-prod5.phala.network) +# GATEWAY_DOMAIN - dstack gateway domain (default: gateway.dstack-prod5.phala.network) # IMAGE - dstack-ingress image (default: dstacktee/dstack-ingress:latest) # INSTANCE_TYPE - CVM instance type (default: tdx.small) # CERTBOT_STAGING - Use LE staging (default: true) @@ -27,7 +27,7 @@ set -uo pipefail : "${DOMAIN:?DOMAIN is required}" : "${CLOUDFLARE_API_TOKEN:?CLOUDFLARE_API_TOKEN is required}" : "${CERTBOT_EMAIL:?CERTBOT_EMAIL is required}" -GATEWAY_DOMAIN="${GATEWAY_DOMAIN:-_.dstack-prod5.phala.network}" +GATEWAY_DOMAIN="${GATEWAY_DOMAIN:-gateway.dstack-prod5.phala.network}" IMAGE="${IMAGE:-dstacktee/dstack-ingress:latest}" INSTANCE_TYPE="${INSTANCE_TYPE:-tdx.small}" CERTBOT_STAGING="${CERTBOT_STAGING:-true}" diff --git a/k3s/docker-compose.yaml b/k3s/docker-compose.yaml index b5caab8b..04736ce5 100644 --- a/k3s/docker-compose.yaml +++ b/k3s/docker-compose.yaml @@ -43,7 +43,7 @@ services: - DNS_PROVIDER=cloudflare - CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_TOKEN} - DOMAIN=*.${CLUSTER_DOMAIN} - - GATEWAY_DOMAIN=_.${DSTACK_GATEWAY_DOMAIN} + - GATEWAY_DOMAIN=gateway.${DSTACK_GATEWAY_DOMAIN} - CERTBOT_EMAIL=${CERTBOT_EMAIL} - SET_CAA=true - TARGET_ENDPOINT=k3s:80