CNAME delegation for cross-provider ACME validation
Your domain's DNS sits on a provider CertMate doesn't speak, or you don't want to give your cert manager API access to the production zone. CNAME delegation moves just the ACME validation records to a separate zone — full TLS, narrow blast radius.
CertMate ships first-class adapters for 23 DNS providers, but
reality has more providers than that, and even when there's an
adapter you may not want to hand it API credentials. CNAME
delegation solves both cases. The pattern is to publish ONE record
on the production DNS — a CNAME at _acme-challenge.example.com — pointing at a
different zone you fully control, and let the second zone
hold the TXT records ACME actually validates.
The mechanic, step by step
Let's Encrypt's validator follows CNAMEs during DNS-01. When it
queries _acme-challenge.example.com and the response
is a CNAME, it follows the chain and reads the TXT at the end of
the chain. This is in the ACME spec and has been stable for years.
Concretely, you set up two things:
- A validation zone on a provider CertMate speaks.
Pick something like
validation.example.orgon Cloudflare. CertMate gets API credentials to that zone. - A static CNAME on the production zone. At
_acme-challenge.example.com, point at_acme-challenge.validation.example.org. This record is written once and never changes; CertMate doesn't need API access to the production zone to maintain it.
From that point on, every ACME validation for example.com writes its TXT record on the validation
zone, the validator follows the CNAME, and Let's Encrypt is happy.
Your production DNS provider never sees CertMate's traffic and
doesn't need to give CertMate an API key.
The CertMate fields
CertMate exposes the delegation as a per-certificate field called
domain_alias. Concretely:
curl -X POST https://certmate.local/api/certificates/create \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"domain": "example.com",
"dns_provider": "cloudflare",
"domain_alias": "validation.example.org"
}'
With domain_alias set, CertMate writes the TXT record
at _acme-challenge.validation.example.org via the
Cloudflare account it has credentials for. The CA queries _acme-challenge.example.com, follows your static
CNAME, reads the value on Cloudflare, and the certificate issues.
An optional alias_dns_provider field lets you keep
your "main" certificates on one provider and the delegation on a
different one — useful when the provider doing the delegation is
shared across many production zones.
When this pattern is the right answer
The provider you use has no CertMate adapter
The supported list covers the major commercial providers plus a handful of self-hosted options, but the long tail is long. deSEC, Gcore, smaller country-specific providers — none of these have first-class adapters today. With CNAME delegation, you don't need one: keep your authoritative DNS where it is, set up a five-dollar Cloudflare zone for validation, point a CNAME, done.
You don't want CertMate touching production DNS
Even when the provider IS supported, handing your cert manager a
token that can edit your production zone is more privilege than the
task requires. CertMate's job is to write
_acme-challenge TXT records; nothing else. A
compromised CertMate with a full-zone token can rewrite your MX,
point your apex at an attacker's IP, vandalize SPF/DKIM/DMARC. The
same CertMate with credentials to only a validation zone
can do exactly one thing: write TXT records on a zone where TXT
records are the only thing that exist.
Your DNS is split across providers
"Multi-master DNS" — Cloudflare primary plus Route53 secondary, for example — is increasingly common for resilience. ACME's validator queries via the public DNS hierarchy and uses whichever authoritative answers it gets. If your two providers' TXT records drift even slightly, the validation fails non-deterministically. Centralizing validation on a single delegated zone removes the multi-master from the validation path entirely.
Wildcards through delegation
Wildcards work exactly the same way. The wildcard
*.example.com validates via _acme-challenge.example.com, which you've delegated, so
there's no extra setup. The same request shape works:
curl -X POST https://certmate.local/api/certificates/create \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"domain": "*.example.com",
"san_domains": ["example.com"],
"dns_provider": "cloudflare",
"domain_alias": "validation.example.org"
}' Operational caveats
- The CNAME has to be in place before you ask for a cert. CertMate doesn't write it for you on the production zone — it can't, that's the whole point. Set it up once, then never touch it.
- CAA records still apply to the original name.
Let's Encrypt walks the CAA tree for the original identifier
(
example.com), not the delegation target. Keep your CAA configuration correct on the production zone. - One delegation zone can serve many production zones.
There's nothing stopping you from putting
_acme-challenge.a.com→...validation...and_acme-challenge.b.com→...validation...at the same time. CertMate handles them with one set of validation credentials. - For ACME-DNS specifically, the
domain_aliasvalue must match the configured ACME-DNSsubdomain/fulldomain exactly. CertMate updates that ACME-DNS record directly and skips cleanup (ACME-DNS keeps only the latest value by design).
Once the delegation is in place, your renewal flow is identical to the non-delegated case: the DNS-01 challenge runs as usual, the cert lands, and your deploy hooks fire. The only difference is the zone the TXT actually appears on — and that's exactly the difference you wanted.