You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
|`EMBEDDED_DNS_PORT`|`53`| embedded authoritative DNS (`--embedded-dns-port`) — default provider; needs 53/tcp+udp and `CAP_NET_BIND_SERVICE` in containers |
19
20
|`ADMIN_TOKEN`| empty | bearer token for admin/policy APIs (`--admin-token`) |
|`X402_ENABLED` / `X402_TESTNET` / `X402_PAY_TO`|`false` / `false` / empty | mounts facilitator under `/api/x402` only when enabled |
29
30
30
-
DNS/ACME provider creds are also env-bound: `ACME_DNS_PROVIDER`, `CLOUDFLARE_TOKEN`, GCP (`GCP_PROJECT_ID`+aliases, `GCP_MANAGED_ZONE`+aliases), Hetzner (`HETZNER_API_TOKEN`/`HCLOUD_TOKEN`), AWS Route53 (`AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY`/`AWS_SESSION_TOKEN`/`AWS_REGION`→defaults us-east-1 downstream/`AWS_HOSTED_ZONE_ID`/`AWS_DNSSEC_KMS_KEY_ARN`), `VULTR_API_KEY`, `NJALLA_TOKEN`, `ENS_GASLESS_ENABLED`. Never hardcode these — reference as env vars / secrets.
31
+
Embedded DNS is the default `ACME_DNS_PROVIDER` (empty value): `EMBEDDED_DNS_PORT` (default 53). External provider creds remain env-bound: `ACME_DNS_PROVIDER`, `CLOUDFLARE_TOKEN`, GCP (`GCP_PROJECT_ID`+aliases, `GCP_MANAGED_ZONE`+aliases), Hetzner (`HETZNER_API_TOKEN`/`HCLOUD_TOKEN`), AWS Route53 (`AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY`/`AWS_SESSION_TOKEN`/`AWS_REGION`→defaults us-east-1 downstream/`AWS_HOSTED_ZONE_ID`/`AWS_DNSSEC_KMS_KEY_ARN`), `VULTR_API_KEY`, `NJALLA_TOKEN`, `ENS_GASLESS_ENABLED` (unsupported with embedded). Never hardcode these — reference as env vars / secrets.
31
32
32
33
## Reserved API surface (types/paths.go)
33
34
Root-host trees that must never fall through to the SPA: `types.ReservedRootPrefixes` = `/api`, `/sdk`, `/discovery`, `/v1`. x402 public paths `/x402/prepare`, `/x402/client.js`; relay facilitator `/api/x402/{supported,verify,settle}`. Discovery: `/discovery`, `/discovery/announce` (only when `DISCOVERY=true`).
@@ -37,5 +38,5 @@ Root-host trees that must never fall through to the SPA: `types.ReservedRootPref
37
38
38
39
## Config embedding & Docker
39
40
-`config.toml` (version/protocol) and `registry.json` (default relays) are embedded via `manifest.go` and parsed in `types/types.go`.
40
-
-`docker-compose.yml` runs `ghcr.io/gosuda/portal:2`, publishes TCP 443 + UDP WireGuard port, and passes the above env vars.
utils.StringFlagEnv(fs, &cfg.ACMEDNSProvider, "acme-dns-provider", "", "DNS provider for managed DNS-01/A-record sync, ECH HTTPS records, and ENS gasless DNSSEC/TXT automation (cloudflare|gcloud|hetzner|njalla|route53|vultr); leave empty to use manual fullchain.pem/privatekey.pem from IDENTITY_PATH", "ACME_DNS_PROVIDER")
105
+
utils.StringFlagEnv(fs, &cfg.ACMEDNSProvider, "acme-dns-provider", "", "DNS provider for managed DNS-01/A-record sync, ECH HTTPS records, and ENS gasless DNSSEC/TXT automation (embedded|cloudflare|gcloud|hetzner|njalla|route53|vultr); defaults to embedded when unset", "ACME_DNS_PROVIDER")
105
106
utils.BoolFlagEnv(fs, &cfg.ENSGaslessEnabled, "ens-gasless-enabled", false, "enable ENS gasless DNS import automation for the managed DNS zone and lease hostnames", "ENS_GASLESS_ENABLED")
106
-
utils.StringFlagEnv(fs, &cfg.CloudflareToken, "cloudflare-token", "", "Cloudflare DNS API token (required when acme-dns-provider=cloudflare)", "CLOUDFLARE_TOKEN")
107
+
utils.IntFlagEnv(fs, &cfg.EmbeddedDNSPort, "embedded-dns-port", 53, utils.ParsePortNumber, "listen port for the embedded authoritative DNS server (the default DNS provider); requires a one-time NS delegation of the base domain and open 53/tcp+udp", "EMBEDDED_DNS_PORT")
107
108
utils.StringFlagEnv(fs, &cfg.GCPProjectID, "gcp-project-id", "", "Google Cloud project id for Cloud DNS automation; auto-detected from ADC or GCE metadata when omitted", "GCP_PROJECT_ID", "GOOGLE_CLOUD_PROJECT", "GCLOUD_PROJECT", "GCE_PROJECT")
108
109
utils.StringFlagEnv(fs, &cfg.GCPManagedZone, "gcp-managed-zone", "", "explicit Google Cloud DNS managed zone name or numeric ID override", "GCP_MANAGED_ZONE", "GCP_ZONE", "GCE_ZONE_ID")
109
110
utils.StringFlagEnv(fs, &cfg.HetznerAPIToken, "hetzner-api-token", "", "Hetzner Cloud API token for DNS automation (required when acme-dns-provider=hetzner)", "HETZNER_API_TOKEN", "HCLOUD_TOKEN")
Copy file name to clipboardExpand all lines: docs/src/routes/configuration/+page.md
+10-2Lines changed: 10 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -58,8 +58,16 @@ The relay server (`relay-server`) reads configuration from environment variables
58
58
59
59
| Variable | Default | Type | Description |
60
60
|----------|---------|------|-------------|
61
-
|`ACME_DNS_PROVIDER`|`""`| string | DNS provider for managed DNS-01/A-record sync, the relay ECH record, opt-in tunnel ECH records, and ENS gasless DNSSEC/TXT automation (`cloudflare`\|`gcloud`\|`hetzner`\|`njalla`\|`route53`\|`vultr`); leave empty to use manual `fullchain.pem`/`privatekey.pem` from `IDENTITY_PATH`|
62
-
|`ENS_GASLESS_ENABLED`|`false`| bool | Enable ENS gasless DNS import automation for the managed DNS zone and lease hostnames |
61
+
|`ACME_DNS_PROVIDER`|`""`| string | DNS provider for managed DNS-01/A-record sync, the relay ECH record, opt-in tunnel ECH records, and ENS gasless DNSSEC/TXT automation (`embedded`\|`cloudflare`\|`gcloud`\|`hetzner`\|`njalla`\|`route53`\|`vultr`); unset defaults to `embedded`; manual `fullchain.pem`/`privatekey.pem` in `IDENTITY_PATH` is used when present |
62
+
|`ENS_GASLESS_ENABLED`|`false`| bool | Enable ENS gasless DNS import automation for the managed DNS zone and lease hostnames; not supported with `ACME_DNS_PROVIDER=embedded` yet |
63
+
64
+
### Embedded DNS
65
+
66
+
Serves the relay base domain from an authoritative DNS server embedded in the relay process, so no DNS provider API credentials are required. It is the default provider when `ACME_DNS_PROVIDER` is unset. Delegate the base domain once at the parent zone (`NS portal.example.com -> ns.portal.example.com` with glue `A` pointing at the relay public IP) and open `53/tcp` + `53/udp`. Containers running without root need `CAP_NET_BIND_SERVICE` to bind the default port. A answers for the apex and every covered name are synthesized from the relay public IPv4; ACME DNS-01 TXT and tunnel ECH HTTPS records are served directly. ENS gasless automation (zone DNSSEC) is not supported yet.
67
+
68
+
| Variable | Default | Type | Description |
69
+
|----------|---------|------|-------------|
70
+
|`EMBEDDED_DNS_PORT`|`53`| int | Listen port for the embedded authoritative DNS server (UDP and TCP) |
Copy file name to clipboardExpand all lines: docs/src/routes/deployment/+page.md
+16-9Lines changed: 16 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -31,10 +31,9 @@ SNI router.
31
31
32
32
- A public Linux server with Docker and Docker Compose.
33
33
- A public hostname such as `portal.example.com`.
34
-
- DNS `A` records for `portal.example.com` and `*.portal.example.com`.
35
-
- Inbound `443/tcp` and `51820/udp` when the overlay is enabled.
36
-
- A certificate covering the root and wildcard names, or a configured Portal
37
-
DNS provider that can issue it.
34
+
- A one-time NS delegation at the parent zone: `NS portal.example.com -> ns.portal.example.com` with a glue `A` record pointing at the relay public IP.
35
+
- Inbound `443/tcp`, `53/tcp` + `53/udp` for the embedded authoritative DNS, and `51820/udp` when the overlay is enabled.
36
+
- Certificates for the root and wildcard names are issued automatically via ACME DNS-01 against the embedded authoritative DNS.
38
37
39
38
## Configuration
40
39
@@ -48,8 +47,12 @@ LANDING_PAGE_ENABLED=false
48
47
DISCOVERY=false
49
48
BOOTSTRAPS=
50
49
51
-
ACME_DNS_PROVIDER=cloudflare
52
-
CLOUDFLARE_TOKEN=replace-with-an-api-token
50
+
# Embedded authoritative DNS is the default provider and needs no API
51
+
# credentials once the NS delegation above is in place. External providers
52
+
# (cloudflare, gcloud, hetzner, njalla, route53, vultr) remain available by
53
+
# setting ACME_DNS_PROVIDER explicitly.
54
+
ACME_DNS_PROVIDER=
55
+
EMBEDDED_DNS_PORT=53
53
56
```
54
57
55
58
`LANDING_PAGE_ENABLED` supplies the initial value. Changes made from the admin
@@ -80,7 +83,8 @@ Frameworks that require a live SSR server cannot be mounted as static files.
80
83
Run those applications separately and call the Portal API over HTTPS; the API
81
84
allows cross-origin requests. Static-export modes can use the mount directly.
82
85
83
-
When `ACME_DNS_PROVIDER` is empty, place these files in `./.portal-certs`:
86
+
To override ACME with a manually managed certificate, place these files in
| `A` | `ns.relay.example.com` | `<your server IP>` (glue) |
144
+
No wildcard record is needed: the relay synthesizes answers for every tunnel
145
+
hostname. The nameserver name is fixed to `ns.<your relay domain>`; publish the
146
+
matching glue `A` record at the parent zone as shown above.
131
147
132
-
DNS propagation typically takes a few minutes but can take up to 48 hours depending on your provider.
148
+
## TLS with ACME
133
149
134
-
## Optional: TLS with ACME
135
-
136
-
By default the relay expects you to place `fullchain.pem` and `privatekey.pem` in the `IDENTITY_PATH` directory (`.portal-certs` by default). For automatic certificate management via DNS-01 challenges, set `ACME_DNS_PROVIDER`:
150
+
Certificates are issued automatically via ACME DNS-01 against the embedded
151
+
authoritative DNS server — no DNS provider credentials are required once the
152
+
delegation above is in place. To use an external DNS provider instead, set
153
+
`ACME_DNS_PROVIDER`:
137
154
138
155
```yaml
139
156
environment:
@@ -175,21 +192,28 @@ requires TCP `443` because Portal publishes standard HTTPS tunnel URLs.
175
192
176
193
**DNS not resolving**
177
194
178
-
Verify your wildcard record is live before connecting a tunnel:
195
+
Query the relay's authoritative server directly first, then through a public
196
+
resolver:
179
197
180
198
```bash
199
+
dig +short @<your server IP> test.relay.example.com
181
200
dig +short test.relay.example.com
182
201
```
183
202
184
-
If nothing returns, check your DNS provider dashboard and allow more time for propagation.
203
+
If the direct query works but the public one does not, the NS delegation at
204
+
the parent zone is missing or not yet propagated. If both fail, confirm the
205
+
relay is running and `53/tcp` + `53/udp` are open.
185
206
186
207
**Firewall blocking connections**
187
208
188
-
Ensure the public HTTPS port is open in your cloud provider's security group or firewall:
209
+
Ensure the public HTTPS and DNS ports are open in your cloud provider's
0 commit comments