Free wildcard certificates with Let's Encrypt
Wildcard certificates from Let's Encrypt are free and automated, but they have rules nobody warns you about. Here's the model Let's Encrypt actually uses, the cases the wildcard covers, the cases it doesn't, and the CertMate configuration that produces one.
A wildcard certificate is a single certificate whose SAN list
includes *.example.com. Browsers and standard TLS
clients accept it for any name that matches the wildcard. Let's
Encrypt issues them at no cost. The catch isn't price — it's the
set of rules around what the wildcard actually matches and how you
have to prove control to get one.
What the wildcard covers (and what it doesn't)
This is RFC 6125 territory and it trips people up regularly.
*.example.com matches a single label at the position of
the asterisk. Concretely:
api.example.com— covered.admin.example.com— covered.example.com(the apex) — NOT covered. The wildcard is one label; the apex is zero labels.v2.api.example.com— NOT covered. Two labels underexample.com, the wildcard only matches one.
In practice this means a typical SAN list is example.com, *.example.com — the apex plus the
one-deep wildcard. If you also need v2.api.example.com,
you need a second wildcard (*.api.example.com) or you
add the FQDN as another SAN.
The DNS-01 requirement
Let's Encrypt has had wildcards since 2018 and from day one the policy has been: wildcards are issued only via the DNS-01 challenge. Practically every other CA that issues free wildcards (ZeroSSL, Google Public CA, Buypass) inherits the same constraint.
The reason is mechanical, not arbitrary. HTTP-01 proves control over
a specific hostname by serving a file at /.well-known/...;
for a wildcard you'd have to serve files at every conceivable
subdomain, which doesn't generalize. DNS-01 proves control over the
zone by writing a TXT record at _acme-challenge.example.com,
and zone control IS the right scope for "any subdomain of
example.com."
So: every wildcard renewal is a DNS-01 dance. If you want a wildcard you're committing to API access to your DNS. There is no path around this.
The CertMate request
Once the DNS provider is set up, asking CertMate for a wildcard is one POST. Concretely, with Cloudflare wired in already as the default account:
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"
}'
CertMate runs certbot under the hood with --dns-cloudflare --domain '*.example.com', polls for
propagation, retrieves the certificate, and stores it under
/app/certificates/_.example.com/ (the leading
asterisk gets normalized to an underscore on disk for path safety).
To include the apex on the same certificate, list both names:
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"
}'
The resulting certificate's SAN list is exactly example.com, *.example.com — apex + one-deep wildcard.
The renewal contract
Let's Encrypt certs are valid for 90 days. CertMate's auto-renew fires when a certificate is within 30 days of expiry by default; you can override the window per certificate. Each renewal repeats the DNS-01 dance, so the DNS API credentials need to keep working forever — which is the real cost of going wildcard. Rotate the credentials and CertMate's renewal silently breaks until you update the account.
The fix is operational: monitor the audit log for renewal failures
(CertMate writes one audit row per attempt), or wire a
deploy hook on the revoked
event to page someone.
Security considerations
A wildcard certificate is a higher-value secret than a single-name one. If the private key leaks, the attacker can impersonate any subdomain — including ones you'll create in the future. Two implications:
- Don't share the wildcard. If three services need TLS at three different subdomains, give them three SAN certificates rather than one wildcard that they all keep on disk. CertMate makes this trivial because issuance is cheap.
- Reduce file permissions aggressively. CertMate
stores cert + key with mode 600 owned by the certmate user, but
deploy hooks that push the cert elsewhere need to preserve that
discipline. The hook contract passes file paths via env vars
(
CERTMATE_KEY_PATH, etc.) — never embed the bytes inline in a shell command.
Cross-provider validation
What if your domain's DNS is hosted on a provider CertMate doesn't
have a plugin for? You can still get the wildcard, by delegating
just the _acme-challenge sub-zone to a provider it
does speak. That's the CNAME
delegation pattern — and it's also the safest way to scope
DNS API credentials when you don't want CertMate's token to be able
to edit your main zone.