7 min read Grounded in docs/dns-providers.md Multi-Master DNS & Domain Alias

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:

  1. A validation zone on a provider CertMate speaks. Pick something like validation.example.org on Cloudflare. CertMate gets API credentials to that zone.
  2. 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_alias value must match the configured ACME-DNS subdomain/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.