how to use certbot dns-01 for wildcard
Learn how to use Certbot DNS-01 challenge for wildcard certificates. See why HTTP-01 no work and how to use DNS plugins for automatic renewal of TXT records.
Why wildcard certificate need DNS-01
Wildcard certificate cover every first-level subdomain for one domain: *.example.com match app.example.com, blog.example.com, and any other name wey one label deep. Let's Encrypt dey issue wildcard certificates only through DNS-01 challenge, so Certbot must prove say you control the domain DNS by publish TXT record for _acme-challenge.example.com. HTTP-01 challenge no fit work, because to serve one token file only prove say you control one hostname—the one wey validation server fetch the file from. Wildcard na claim for every possible name under the domain, and DNS na only public record wey fit speak for the whole namespace.
That one requirement na him dey decide everything else for this page. To pass DNS-01, you must fit create TXT records for the domain zone, either by hand or through your DNS provider API (application programming interface). If you do am by hand, e go work once, but e go fail when time reach to renew, for one reason wey I go show below. The API route, wey use Certbot DNS plugin, dey renew itself without person intervention, and na dat setup you suppose use.
This na the wildcard chapter for our Certbot guides. Ordinary single-hostname certificates, web server configuration, and port 80 rules dey inside Certbot with nginx on Ubuntu 24.04 and Certbot with Apache on Ubuntu 24.04.
How the _acme-challenge TXT record works
When Certbot request *.example.com, Let's Encrypt go answer with one random token. Certbot go combine that token with your ACME (automatic certificate management environment) account key, use SHA-256 hash the result, and produce one short text value. That value must show as TXT record for _acme-challenge.example.com. Let's Encrypt go then query your domain's authoritative name servers from their own infrastructure. If the record wey dem read match the value wey dem expect, you don prove say you control the zone, and control of the zone mean say you control every name under am.
Two things dey cause most failures:
- If you request
example.comand*.example.comfor the same certificate, e mean say na two separate challenges, and both TXT records must dey for the same name,_acme-challenge.example.com. Both must dey exist at the same time. To add the second record na the correct way; if you replace the first record with the second one, the first challenge go fail. - Validation dey read your authoritative servers, but provider control panels fit take one minute or more before dem push new record reach dem. Check from the outside before you let validation run:
dig +short TXT _acme-challenge.example.com @1.1.1.1When that command print the value wey Certbot ask for, validation fit succeed. When e print nothing, wait small and run am again.
See am work once: manual mode
Manual mode make you do the DNS edit yourself. Na the best way to understand how the mechanism dey work before you automate am:
sudo certbot certonly --manual --preferred-challenges dns -d example.com -d '*.example.com'The quotes around the wildcard dey stop your shell from treating * as one filename pattern. Certbot go pause with instructions:
Please deploy a DNS TXT record under the name:
_acme-challenge.example.com.
with the following value:
Jx9mQ2wLr8vTn5cKp0aYdG3hB7fZs4eN1oiRuXqMk6ECreate that TXT record for your DNS provider panel. Use the dig command wey dey above take confirm say e dey visible. Only when you see am, press Enter. Because this run dey ask for the bare domain and the wildcard, Certbot go prompt you twice; make you keep both records dey there until issuance finish. If e work, you go see these familiar lines:
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pemWhy manual mode cannot renew itself
Every renewal na new challenge with new token, so the TXT value dey change every time. The record wey you paste today no go work again after 60 days. Certbot dey run renewal timer twice every day without person, and nobody dey there to paste the new value. Because of this, certificate wey you issue manually go fail to renew with this exact error:
Failed to renew certificate example.com with error: The manual plugin is not
working; there may be problems with your existing configuration.
The error was: PluginError('An authentication script must be provided with
--manual-auth-hook when using the manual plugin non-interactively.')You fit solve this problem if you write --manual-auth-hook scripts wey go call your DNS provider's API, but for that level, you dey build DNS plugin manually. Use manual mode to learn how the flow dey work, or for one-time use for domain wey you no fit automate DNS yet. Set reminder well before day 90 reach, because Let's Encrypt no dey send expiry emails again. For everything else, use plugin.
The plugin route: certbot-dns-cloudflare for Ubuntu 24.04
DNS plugin na e dey hold API credential for your DNS provider, and e dey do all the TXT record work by itself, when e dey issue certificate and every time e dey renew am. We dey use Cloudflare as example here because na the plugin most people need, and Ubuntu don package am inside.
Our Certbot guides dey recommend to use apt packages for Ubuntu 24.04, and dat one still hold for Cloudflare:
sudo apt update
sudo apt install certbot python3-certbot-dns-cloudflareOne small note for version. The 24.04 archive dey ship dis plugin for version 2.0.0 alongside Certbot 2.9.0; apt policy python3-certbot-dns-cloudflare go show you yours. Dis mismatch no go cause wahala, and scoped API tokens go work, because di underlying python3-cloudflare library for 24.04 na 2.11.1, wey pass di 2.3.1 wey di plugin need for token support. For old Ubuntu releases, dat library too old for tokens, na why dem dey give warnings online say apt plugin dey force use Global API Key. For 24.04, dem no need dat one again.
Inside Cloudflare dashboard, create scoped API token, no use Global API Key: go My Profile, then API Tokens, then Create Token, and pick only one permission: Zone / DNS / Edit, and limit am to di single zone wey you dey issue for. Put am inside file wey only root fit read:
sudo mkdir -p /root/.secrets
sudo tee /root/.secrets/cloudflare.ini > /dev/null <<'EOF'
dns_cloudflare_api_token = paste_your_scoped_token_here
EOF
sudo chmod 600 /root/.secrets/cloudflare.iniCertbot go check di mode and e go warn you about Unsafe permissions on credentials configuration file if anybody else fit read di file. Now, run dis command:
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
-d example.com -d '*.example.com'Di plugin go create di TXT records through di API, wait small for propagation, let validation run, den e go delete di records again. If your zone name servers dey slow to pick up changes, increase di wait time with --dns-cloudflare-propagation-seconds 60. Di certificate go land for /etc/letsencrypt/live/example.com/, and you go point nginx or Apache to fullchain.pem and privkey.pem exactly as di base guides show, including di deploy hook.
If your provider's plugin no dey for apt
24.04 archive only package plugins for some providers, like Cloudflare, Route 53, DigitalOcean, and the generic RFC 2136 interface. Run apt search certbot-dns to see the list. If your provider no dey for the list, we must change our apt-first advice: install Certbot and the plugin from snap instead, and make sure you remove the apt Certbot first so two renewal timers no go fight over /etc/letsencrypt:
sudo apt remove certbot python3-certbot-dns-cloudflare
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo snap set certbot trust-plugin-with-root=ok
sudo snap install certbot-dns-yourproviderSnap plugin only connect to the snap Certbot; e no fit extend the apt one, na why the two installs must no dey together. And if your DNS host no get API at all, your options na to move the domain's DNS to one provider wey get API, or run your own name server and point the rfc2136 plugin at am.
Renewal: prove am now, no wait for 60 days
Certbot dey record how dem issue every certificate for /etc/letsencrypt/renewal/example.com.conf, including authenticator = dns-cloudflare and the credentials path. This way, the standard twice-daily timer go dey renew am without you need to do anything. Test the whole process for staging environment:
sudo certbot renew --dry-runIf e pass, e mean say the credential dey work and validation complete from start to end; the real renewal wey go happen for 60 days go follow the same way. Two things you need do today. First, even if new certificate dey disk, nothing go change until you reload the web server, so make sure you set up the deploy hook wey dem explain for nginx and Apache guides. Second, treat the credentials file with care: anyone wey fit read am fit edit your DNS zone, and that one enough to redirect your mail or pass their own DNS-01 challenges. Keep am for mode 600 under /root, limit the token to one zone, and change am if you suspect say somebody don see am.
Wey you no need wildcard
Wildcard na correct tool for many subdomains, or for subdomains wey you no fit predict. For everything else, e no be the right default.
- One subdomain, or small number of known ones: normal SAN (subject alternative name) certificate simple pass.
certbot --nginx -d example.com -d www.example.com -d app.example.comcover up to 100 names over plain HTTP-01, and no DNS API credential go dey sit for server. - Wildcard match exactly one label.
*.example.comno cover the bareexample.com, na why the commands wey dey above request both, and e no covera.b.example.comeither; that one go need*.b.example.com. - One private key dey stand behind every subdomain. If the machine wey hold am get wahala, every name wey wildcard cover go affect at once.
- If Traefik dey terminate TLS (transport layer security) for your containers, you no need Certbot for the matter at all: Traefik dey request wildcard certificates itself over DNS-01, using the same kind of provider token.
Wey wildcard really dey work: per-customer or per-app subdomains wey dey create faster than you fit reissue certificates, and internal hosts wey no get public port 80, like services wey you fit reach only through a WireGuard VPN. DNS-01 no dey connect to the host wey dem dey certify, so even if machine dey fully private, e fit hold publicly trusted certificate.
FAQ
Certbot fit issue wildcard certificate with HTTP-01?
No. HTTP-01 dey prove say you control one hostname only, because validation server dey fetch token file from that exact name. Wildcard dey cover every name under the domain, so Let's Encrypt dey require DNS-01 challenge for am. All the --nginx, --apache, --webroot and --standalone authenticators na HTTP-based. The only way na to put TXT record for _acme-challenge.example.com, wey you fit do manually or use DNS plugin.
Wildcard certificate dey cover root domain?
No. Wildcard dey match exactly one label only. So *.example.com dey cover www.example.com but e no dey cover bare example.com, and e no dey cover a.b.example.com. You fit request both names for one certificate with -d example.com -d '*.example.com'. Dis one go create two challenges, and both TXT records go dey for the same _acme-challenge.example.com name, so make you add the second record without to delete the first one.
Why my wildcard certificate no dey renew automatically?
Because dem issue am with --manual. Every renewal need brand-new TXT value, and the unattended timer no get way to paste am, so renewal go stop with error An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively. Reissue the certificate with DNS plugin like certbot-dns-cloudflare, or use --manual-auth-hook and --manual-cleanup-hook scripts wey go edit the record through your provider API.
How long _acme-challenge TXT record dey take to show?
E depend on your DNS provider: e fit take anywhere from seconds to several minutes. Validation dey read your zone authoritative servers, so use dig +short TXT _acme-challenge.example.com @1.1.1.1 check am and wait until you see the correct value before you continue manual run. If you dey use plugin, increase the built-in wait through the plugin propagation option, like --dns-cloudflare-propagation-seconds 60, if validation say e no fit find the record.
Wildcard certificate less secure than normal certificate?
The cryptography na the same. The difference na for how you dey use am: one private key dey cover every subdomain, so if dem hack am, dem go get access to everything. Also, the DNS API credential wey automation dey use na sensitive secret wey dey stay for server. If you only dey run few subdomains wey you know, use SAN certificate to avoid these wahala; na why dis guide dey tell you say make you skip wildcard.