Propagation & resolver settings
Before CertAutoPilot asks the CA to validate a DNS-01 challenge, it checks that the _acme-challenge TXT record is actually visible from public DNS. This page covers what that pre-check does and the org-wide settings that control it, under Settings → General.
What the pre-check does
The pre-check is an optimisation, not the validation itself: it avoids spending a CA validation attempt (which counts against the CA's failed-validation rate limits) on a record that hasn't propagated yet. The CA is always the authoritative validator and does its own lookup.
It applies to both DNS-01 paths:
| Path | Where the check runs |
|---|---|
| Automated DNS-01 (zone + credential) | By default the phased flow runs: the worker presents the TXT records, then a self-rescheduling propagation gate polls your resolvers (no worker held between checks) until the records are visible or the propagation deadline expires, and only then asks the CA to validate. The synchronous lego pre-check path (AddRecursiveNameservers) is used when phased mode is disabled, for the sequential RRset-replacing provider RFC 2136, and for Cloudflare, DigitalOcean, OVH and Plesk — those four clean up their TXT record inside the presenting process, so they cannot use the phased flow's separate cleanup job. |
| Manual DNS (operator-created records) | Clicking Validate on the certificate first queries each resolver for the expected TXT value. If no record is visible on any resolver, validation is not enqueued and you get an error telling you to create the records first (or skip the pre-check). |
Resolvers
Settings → General → DNS Resolvers. When the list is empty, the built-in public set is used:
8.8.8.8:53(Google)8.8.4.4:53(Google)1.1.1.1:53(Cloudflare)
Custom entries accept a bare IP or hostname (10.0.0.53, dns.internal) — port :53 is appended automatically — or an explicit host:port. IPv6 literals must be bracketed: [2001:db8::1]:53. The UI field takes multiple entries separated by comma or space.
If your network blocks outbound DNS to public resolvers, the default set will never see your records and every validation stalls at the pre-check. Point the list at resolvers you can actually reach — or use skip-precheck if those resolvers can't see what the CA sees.
Require-all vs allow-partial
dns_propagation_allow_partial (Allow Partial Propagation switch):
- Off (default, strict) — a TXT record counts as propagated only if every configured resolver returns it.
- On (partial) — a single agreeing resolver is enough. Use on networks that can reach only one (often internal) resolver.
On the automated path, enabling this also relaxes lego's authoritative-nameserver propagation requirement (DisableAuthoritativeNssPropagationRequirement).
Skip the pre-check
dns_propagation_skip_precheck (Skip Propagation Pre-check switch) bypasses the local gate entirely and lets the CA validate directly. Turn it on when the local check can't see what the CA sees:
- Split-horizon DNS — internal resolvers answer differently from the public view the CA queries.
- No outbound DNS — the CertAutoPilot host cannot query any resolver that carries the public zone.
With the gate off, a record that genuinely hasn't propagated wastes a CA validation attempt — and failed validations count against CA rate limits (Let's Encrypt: per-account, per-hostname). Keep the gate on unless it is a false blocker.
Timeout & poll interval
Two budget knobs under Settings → General → Runtime Limits shape how long DNS propagation may be waited on and how often it is re-checked:
| Setting | JSON field | Default | Allowed range |
|---|---|---|---|
| DNS Propagation Timeout | dns_propagation_timeout_seconds | 120 s | 30–600 s |
| DNS Poll Interval | dns_propagation_poll_interval_seconds | 5 s | 2–60 s (must be < timeout) |
The poll interval must be strictly less than the timeout; the API rejects the update otherwise. Each individual resolver query in the pre-check is capped at 5 s regardless of these settings.
dns_propagation_timeout_seconds and dns_propagation_poll_interval_seconds are read only on the synchronous path — manual DNS, HTTP-01, RFC 2136, and the Cloudflare, DigitalOcean, OVH and Plesk providers. On the phased flow (the default everywhere else) the wait is governed by dns_propagation_deadline_seconds instead.
Two additional settings govern the phased flow: dns_propagation_deadline_seconds — how long the propagation gate keeps polling before giving up (default 1800 s, allowed 300–14400 s; it can exceed the synchronous in-worker cap because the gate never holds a worker) — and dns_propagation_phased_disabled, the kill-switch that reverts automated DNS-01 to the synchronous path (default false = phased ON).
Settings reference
All of these fields live on the org-wide general settings document (there is no per-zone or per-certificate override):
A DNS credential carries Propagation strategy and Nameserver override fields in the API and the credential form. They are stored but nothing reads them — resolver selection is org-wide only, via dns_resolvers below. Use that setting instead.
| JSON field | Type | Default |
|---|---|---|
dns_resolvers | string list | empty → public default set |
dns_propagation_allow_partial | bool | false (require all) |
dns_propagation_skip_precheck | bool | false (gate on) |
dns_propagation_timeout_seconds | int | 120 |
dns_propagation_poll_interval_seconds | int | 5 |
dns_propagation_deadline_seconds | int | 1800 (300–14400; phased gate) |
dns_propagation_phased_disabled | bool | false (phased flow ON) |
Troubleshooting propagation stalls
- Certificate stuck in validating: see "Validating" forever.
- Manual DNS shows "no TXT records found via the configured DNS resolvers": the record isn't visible yet from any resolver in your list — check with
dig TXT _acme-challenge.<name> @8.8.8.8, wait out your provider's propagation delay, or enable skip-precheck on split-horizon networks. See also manual DNS propagation tips. - Only some resolvers see the record and you're on strict mode: either wait, or switch on allow-partial if the lagging resolver is expected (single reachable resolver).
API
Settings are org-wide and require the Admin role:
GET /api/v1/settings/general
PUT /api/v1/settings/general