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
{{ message }}
Repository navigation
Commit c87f271
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: custom-domain/dstack-ingress/DNS_PROVIDERS.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -21,7 +21,7 @@ This guide explains how to configure dstack-ingress to work with different DNS p
21
21
22
22
-`DNS_PROVIDER` - DNS provider to use (`cloudflare`, `linode`, `namecheap`, `route53`). Detected from the provider's credential variable when unset; set it explicitly for `route53`
23
23
-`ACME_EMAIL` - Contact address for the ACME account (`CERTBOT_EMAIL` still works). Published in the evidence, so leave it unset unless you want one
24
-
-`SET_CAA` - Enable CAA record setup: `true` or `false` (default). Except on Cloudflare, this makes a non-wildcard domain's pointer an A record; see the README
24
+
-`SET_CAA` - Enable CAA record setup: `true` or `false` (default`false`; `true` with `DELEGATION_ZONE`). Except on Cloudflare, this makes a non-wildcard domain's pointer an A record; see the README
25
25
-`PORT` - HTTPS port (default: 443)
26
26
-`TXT_PREFIX` - Prefix for TXT records (default: "_dstack-app-address")
27
27
@@ -112,7 +112,7 @@ PolicyDocument:
112
112
**Important Notes for Route53:**
113
113
- The certbot plugin uses the format `certbot-dns-route53` package
114
114
- CAA values are merged into the existing record set at the name: only values with the same tag are replaced, so `iodef` and other tags are kept
115
-
- Where a CAA record shares the name (`DELEGATION_ZONE`, `SET_CAA=true` on a non-wildcard domain, or any CAA already there), the gateway pointer is an A record to the resolved gateway IP instead of a CNAME, replacing any CNAME or AAAA in the same change. It is refreshed every `RENEW_INTERVAL`
115
+
- Where a CAA record shares the name (`SET_CAA=true` under `DELEGATION_ZONE`, where it is the default, or on a non-wildcard domain, or any CAA already there), the gateway pointer is an A record to the resolved gateway IP instead of a CNAME, replacing any CNAME or AAAA in the same change. It is refreshed every `RENEW_INTERVAL`
116
116
- Wildcard record names are listed by Route53 as `\052.<domain>`; they are matched as `*.<domain>`
117
117
- It is essential that the AWS service account used can only assume the limited role. See cloudformation example.
Copy file name to clipboardExpand all lines: custom-domain/dstack-ingress/README.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -175,7 +175,7 @@ otherwise arbitrary — the gateway answers every name under its domain.
175
175
|----------|---------|-------------|
176
176
| `PORT` | `443` | HAProxy listen port |
177
177
| `ROUTING_MAP` | | Multi-domain routing: `domain=host:port`per line. A wildcard entry (`*.example.com=host:port`) matches one label, and exact entries take precedence over it. Unmatched names go to the first entry. It routes only: every name still needs to be in `DOMAIN`/`DOMAINS` to get a certificate |
178
-
| `SET_CAA` | `false` | Enable CAA DNS record (dns-01 only; tls-alpn-01 cannot write DNS). Replaces existing values with the same tag; for a wildcard whose base is a zone apex this restricts the whole zone (see [Wildcard Domain Support](#wildcard-domain-support)). Except on Cloudflare, a non-wildcard domain is then published as an A record to the gateway's current address instead of a CNAME, because a CNAME would hide the CAA beside it; the address is refreshed every `RENEW_INTERVAL`. The same happens whenever a CAA record already exists at the name, whoever wrote it, so turning `SET_CAA` off later keeps the A record until you delete the CAA. Linode always uses an A record. With `DELEGATION_ZONE`the CAA is always published, whatever this says |
178
+
| `SET_CAA` | `false` | Enable CAA DNS record (dns-01 only; tls-alpn-01 cannot write DNS). Replaces existing values with the same tag; for a wildcard whose base is a zone apex this restricts the whole zone (see [Wildcard Domain Support](#wildcard-domain-support)). Except on Cloudflare, a non-wildcard domain is then published as an A record to the gateway's current address instead of a CNAME, because a CNAME would hide the CAA beside it; the address is refreshed every `RENEW_INTERVAL`. The same happens whenever a CAA record already exists at the name, whoever wrote it, so turning `SET_CAA` off later keeps the A record until you delete the CAA. Linode always uses an A record. Defaults to `true` with `DELEGATION_ZONE`; turning it off there lets anyone who can write the delegation zone get certificates for the domain. Either way, the CAA in force is checked before every issuance and a domain it refuses is not sent to the CA |
179
179
| `TXT_PREFIX` | `_dstack-app-address` | DNS TXT record prefix |
180
180
| `ACME_EMAIL` | | ACME contact address, in either mode. `CERTBOT_EMAIL` is the historical name and still works. See [below](#the-acme-contact-address-is-optional-and-public) — it is optional, and published |
181
181
| `ACME_STAGING` | `false` | Use Let's Encrypt staging, in either mode. `CERTBOT_STAGING` is the historical name and still works |
@@ -188,7 +188,7 @@ otherwise arbitrary — the gateway answers every name under its domain.
188
188
| `DNS_WEBHOOK_URL` | | `DNS_SETUP_MODE=webhook`: endpoint to notify |
189
189
| `DNS_WEBHOOK_TOKEN` | | Shared secret; the payload is HMAC-SHA256 signed with it |
190
190
| `DNS_WEBHOOK_TIMEOUT` | `15` | Seconds per webhook POST attempt |
191
-
| `DOH_RESOLVERS` | Google + Cloudflare | Comma-separated DoH endpoints used to verify records. `DOH_RESOLVER` is the historical name and still works |
191
+
| `DOH_RESOLVERS` | Google + Cloudflare | Comma-separated DoH endpoints used to verify records, and to check CAA before issuing. `DOH_RESOLVER` is the historical name and still works |
192
192
| `TLSALPN_ADDRESS` | `127.0.0.1` | Address lego's ACME responder binds to, and haproxy forwards `acme-tls/1` connections to |
193
193
| `TLSALPN_PORT` | `9443` | Loopback port lego's ACME responder binds to |
194
194
| `TLS_TERMINATE_PORT` | `9444` | Loopback port the TLS frontend moves to in tls-alpn-01 mode |
@@ -243,12 +243,12 @@ dstack-ingress publishes what they point at, in the delegation zone:
243
243
244
244
```
245
245
svc.example.com.deleg.example.net A <address of GATEWAY_DOMAIN>
Copy file name to clipboardExpand all lines: custom-domain/dstack-ingress/TESTING.md
+15-13Lines changed: 15 additions & 13 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -284,8 +284,9 @@ These fail fast and are cheap, so run them on every change:
284
284
| Scenario | Expected |
285
285
|---|---|
286
286
| tls-alpn-01 + a wildcard domain | Refused before any ACME call, citing RFC 8737 |
287
-
| Delegation, CAA in the delegated zone changed to forbid the CA | Blocked before any ACME attempt — proves the published CAA is reachable through the CNAME |
288
-
| Delegation with no CAA record at all | Proceeds, reporting `no CAA record set; issuance is unrestricted` — see below |
287
+
| Delegation, `SET_CAA=false`, CAA in the delegated zone changed to forbid the CA | Blocked before any ACME attempt — proves a CAA there is reachable through the CNAME. With `SET_CAA` on, the next pass replaces it instead |
288
+
| dns-01, `SET_CAA=false`, a CAA naming another CA or pinned to another account | Blocked before any ACME attempt with `CAA forbids issuing <domain> with this account` and the reason quoted back |
289
+
| Delegation, `SET_CAA=false`, no CAA record at all | Proceeds, reporting `no CAA record set; issuance is unrestricted` — see below |
289
290
| Delegation, later pass, gateway CNAME broken | Renewal proceeds — that record is for serving, and dns-01 does not use it |
290
291
| A CAA record with `validationmethods=dns-01`, mode tls-alpn-01 | Blocked with the restriction quoted back |
291
292
| TXT holding the wrong value | Reported as `TXT present but wrong value`, not "missing" |
@@ -298,7 +299,7 @@ it is observable rather than merely argued.
298
299
had to create the CAA record, its absence was the state that mattered: nothing
299
300
then stopped anyone else who could satisfy the delegated challenge, and the
300
301
container held no token to create it. Once the container began publishing the
301
-
delegated CAA itself, absence stopped meaning that — it means "not published
302
+
delegated CAA itself (`SET_CAA`, the default under delegation), absence stopped meaning that — it means "not published
302
303
yet", and the next pass fixes it — so the gate was removed along with
303
304
`ALLOW_MISSING_CAA`and dnsguide's `--caa-required`. `check_caa` now follows
304
305
RFC 8659 for delegation as it always did elsewhere: an absent CAA record set
@@ -310,19 +311,20 @@ attempt, which is what proves the published record is reachable through the
310
311
operator's CNAME. Expect the reason quoted back, e.g. `issue allows
311
312
'example.com', not letsencrypt.org`.
312
313
313
-
Note also that the first pass on a fresh deployment necessarily runs before any
314
-
CAA exists: the record names the ACME account, so the account has to exist
315
-
first. `process_domain` issues, writes the CAA, and issues again only if the
316
-
first attempt failed and had to create the account.
314
+
Note also that the CAA record names the ACME account, so `process_domain`
315
+
registers the account on its own first. Every dns-01 pass runs the same steps
316
+
in the same order — register, publish the records (CAA with `SET_CAA`), check
317
+
that the CAA in force lets this account issue, issue once — so even a fresh
318
+
deployment's first certificate is issued under the pin.
317
319
318
320
## Traps
319
321
320
-
**Start from a clean zone.** Records left over from an earlier run change which
321
-
branch executes. A stale CAA record naming a previous ACME account makes dns-01's
322
-
first issuance attempt fail and the second succeed — which happens to be the path
323
-
where the code was correct, hiding a bug in the ordinary path where the first
324
-
attempt succeeds. Delete test records between runs and verify against the
325
-
authoritative nameserver, not a cached resolver.
322
+
**Start from a clean zone.** Records left over from an earlier run change what a
323
+
pass does. A stale CAA record naming a previous ACME account is rewritten with
324
+
`SET_CAA=true`, but resolvers may keep the old one for its TTL, so the CAA check
325
+
fails a pass or two before issuance; with `SET_CAA=false` it blocks for good.
326
+
Delete test records between runs and verify against the authoritative
327
+
nameserver, not a cached resolver.
326
328
327
329
**One resolver is not enough to trust either answer.** Public resolvers cache
328
330
negative answers for the zone's SOA minimum, so a resolver queried before a
0 commit comments