What a wildcard certificate is
A wildcard certificate has a name like *.example.com in its Subject Alternative Name (SAN) list. When a browser connects to shop.example.com, it checks whether that name matches any entry on the certificate, and *.example.com matches.
The matching rule is narrow, and most problems with wildcards come from assuming it is wider than it is:
- The
*must be the entire leftmost label.*.example.comis valid;shop*.example.comandwww.*.example.comare not something a public CA will issue. - The
*stands for exactly one label. It doesn’t match zero labels, and it doesn’t match two.
So for a certificate whose SAN list is only *.example.com:
| Name | Covered? |
|---|---|
www.example.com | Yes |
api.example.com | Yes |
example.com | No, zero labels in the * position |
dev.api.example.com | No, two labels |
example.net | No, different domain |
The fix for the second and fourth rows is the same: put those names on the certificate too. A single certificate can hold example.com, *.example.com and *.api.example.com together. What you can’t do is write *.*.example.com.
Check what your certificate actually covers
Read the SAN list that goes out on the wire, not the file you think the server is using:
openssl s_client -connect www.example.com:443 -servername www.example.com </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -ext subjectAltName
Typical output for a wildcard that also includes the apex:
subject=CN = example.com
issuer=C = US, O = Let's Encrypt, CN = R11
X509v3 Subject Alternative Name:
DNS:*.example.com, DNS:example.com
The -servername flag sends SNI. Without it many servers hand back their default certificate and you inspect the wrong one. The SSL check shows the same SAN list from outside your network, which is useful when you suspect a CDN or load balancer is serving something different from your origin.
If a visitor gets NET::ERR_CERT_COMMON_NAME_INVALID on a name you thought the wildcard covered, it’s almost always the apex or a second-level name. The full list of causes is in the CN-invalid guide.
Getting a free wildcard from Let’s Encrypt
Let’s Encrypt issues wildcards, but only with the DNS-01 challenge. HTTP-01 proves you control one web server, which says nothing about every possible subdomain, so it isn’t accepted for wildcards. TLS-ALPN-01 isn’t either.
DNS-01 works like this: the CA gives your ACME client a token, the client publishes a value derived from it as a TXT record at _acme-challenge.example.com, and the CA looks it up. Note the name: for *.example.com the record goes at _acme-challenge.example.com, without the *. For the apex example.com it goes at the same name. If you request both on one certificate, two different TXT values must exist at that name at the same time. Clients that “replace” the record instead of adding a second value fail one of the two authorizations, and this is the most common reason a wildcard-plus-apex order fails on the first try.
With certbot and a DNS plugin
Manual mode (--manual --preferred-challenges dns) works once but can’t renew on its own, because you’d have to paste a new TXT record every time. For anything you plan to keep, use a DNS plugin. With Cloudflare:
# /root/.secrets/cloudflare.ini (chmod 600)
dns_cloudflare_api_token = <token with Zone:DNS:Edit on this zone>
certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
-d example.com -d '*.example.com'
Quote '*.example.com'. Unquoted, the shell may expand the asterisk against files in the current directory.
Certbot has plugins for Route 53, Google Cloud DNS, DigitalOcean and several others; they’re separate packages (python3-certbot-dns-route53 and so on, or snap plugins).
With acme.sh
acme.sh supports a long list of DNS providers through its dns_* hooks:
export CF_Token="<token>"
acme.sh --issue --dns dns_cf -d example.com -d '*.example.com'
When your DNS provider has no API
Plenty of registrars and Korean hosting panels don’t offer an API. You have two reasonable options.
The first is CNAME delegation. Create one permanent record, _acme-challenge.example.com. CNAME example-com.acme.example.net., pointing into a zone that does have an API, or into a dedicated server like acme-dns. Let’s Encrypt follows the CNAME when it looks up the TXT record, so your ACME client only ever writes to the delegated zone. This also limits the blast radius: the API credential on your server can only change challenge records, not your whole zone.
The second is moving DNS hosting to a provider with an API. If the whole point was a free automated wildcard, that is often the simpler path.
Check the TXT record before blaming the CA
If validation fails, look at what public resolvers actually return:
dig +short TXT _acme-challenge.example.com @1.1.1.1
dig +short TXT _acme-challenge.example.com @8.8.8.8
An empty answer usually means the client checked too early (raise the propagation wait, --dns-cloudflare-propagation-seconds in certbot), the record was created in the wrong zone, or your registrar’s nameservers aren’t the ones you edited. The DNS lookup shows the delegated nameservers and the TXT value from outside. A CAA record that allows Let’s Encrypt for normal certificates but not wildcards will also block this; see CAA records, specifically issuewild.
Wildcard or a list of names?
A certificate can carry many explicit names instead; Let’s Encrypt allows up to 100 per certificate. Which one fits depends on how your subdomains behave.
A wildcard makes sense when subdomains are created dynamically or often: per-customer hostnames on a SaaS, preview environments, a platform where adding newteam.example.com shouldn’t require reissuing anything. It also keeps individual hostnames out of Certificate Transparency logs. Every public certificate is logged, and a SAN list of admin.example.com, vpn.example.com, jenkins.example.com publishes your internal naming to anyone who searches the logs. A wildcard only shows *.example.com. That is a small privacy gain, not a security control: the names still leak through DNS and links.
A list of names is better when you have a handful of stable services, run them on different machines, or can use HTTP-01 and don’t want to hand a DNS API key to a web server.
The security trade-off: one key, many servers
The certificate isn’t cryptographically weaker. The cost is where the private key ends up.
If *.example.com serves the marketing site, the API, the staging box and a forgotten WordPress install, the same private key sits on all four. Whoever steals it from the weakest one can present a valid certificate for login.example.com or api.example.com, provided they can also get traffic to themselves (a hijacked DNS record, a malicious Wi-Fi network, a compromised router). Revoking it means replacing the certificate on every host at once.
There is a quieter version of the same problem. Researchers have shown cross-protocol attacks where a certificate valid for many names, shared between a web server and, say, a mail or FTP server, lets an attacker redirect a browser’s TLS connection to the other service. The practical lesson is the same: don’t put the same wildcard key on services with very different exposure.
What that means in practice:
- Use the wildcard where it buys something (dynamic names, one edge proxy terminating TLS for many hosts) and give separately exposed services, such as mail, VPN and admin panels, their own certificates.
- Terminate the wildcard at one layer, a reverse proxy or load balancer, instead of copying the key to every backend.
- If you use a commercial wildcard, the private key generation is still yours. Don’t email the key around or keep it in a repository to “share” the certificate between teams.
EV certificates can’t be wildcards at all; the EV rules forbid it. OV and DV wildcards are both available commercially.
Cloudflare and wildcards
If your domain is proxied through Cloudflare, visitors see Cloudflare’s edge certificate, not yours. The free Universal SSL certificate covers example.com and *.example.com, which is exactly one level of subdomain.
So a proxied record for dev.api.example.com gets a certificate error at the edge, even if your origin has a perfect certificate for that name. The options are an Advanced Certificate (a paid add-on) that includes *.api.example.com, Cloudflare’s Total TLS feature in the same add-on, which issues for each proxied hostname, or setting that record to DNS only so visitors reach your origin and its own certificate.
For the leg between Cloudflare and your origin, Cloudflare’s Origin CA will issue a wildcard origin certificate for free. Browsers don’t trust it, so it only works while traffic goes through Cloudflare. How the edge and origin certificates interact depends on the SSL mode; see Cloudflare SSL modes.
Renewal
A wildcard renews like any other certificate, with one extra failure point: the DNS API credential. Tokens get rotated, revoked when someone leaves, or scoped to the wrong zone. The certificate keeps working until it expires, so the first sign is often an expiry warning months later.
Test the full path, not just the config:
certbot renew --dry-run
That runs a real DNS-01 challenge against the staging CA. If it fails on a credential or propagation timeout, fix it now. With maximum certificate lifetimes going down from 2026 (see the expiry checklist), renewals happen more often and a broken token surfaces sooner, but only if something is watching. After each renewal, make sure every place that holds a copy of the wildcard gets the new one; a wildcard is usually deployed in more places than a single-name certificate, which is exactly why it gets missed.
Check your own domain now
Free, no sign-up. Runs the exact check this guide describes and shows what to fix.