A wildcard certificate lets one TLS certificate cover every first-level host under a domain, but Certbot cannot prove a wildcard name with the HTTP or standalone challenges. The certificate authority must see a DNS-01 TXT record for the domain, so the DNS provider account and its API token become part of the issuance path.
Using a Certbot DNS plugin keeps that TXT record lifecycle inside Certbot. The plugin creates the _acme-challenge record, waits for DNS propagation, asks the ACME server to validate it, and removes the record after the order finishes.
The package names use the Debian and Ubuntu APT layout with the Cloudflare DNS plugin. Use the matching DNS plugin and credential option for another provider, and request both example.com and *.example.com when the apex name must also be covered because a wildcard name does not match the bare domain.
$ sudo apt install --assume-yes certbot python3-certbot-dns-cloudflare dnsutils Reading package lists... Done Building dependency tree... Done The following NEW packages will be installed: certbot dnsutils python3-certbot-dns-cloudflare python3-cloudflare ##### snipped ##### Setting up python3-certbot-dns-cloudflare ...
For another DNS provider, install that provider's Certbot DNS plugin and use its matching credential flag in the later commands.
$ host -t NS example.com example.com name server arvind.ns.cloudflare.com. example.com name server nina.ns.cloudflare.com.
The Cloudflare plugin can only update zones that are active in Cloudflare DNS. Use the provider-specific Certbot DNS plugin that matches the authoritative nameservers for the zone.
$ sudo install -m 600 -o root -g root /dev/null /etc/letsencrypt/cloudflare.ini
$ sudoedit /etc/letsencrypt/cloudflare.ini
dns_cloudflare_api_token = <cloudflare-api-token>
Use a token scoped to the needed zone and DNS record edits. A broad DNS account token can change unrelated records if the host is compromised.
$ sudo ls -l /etc/letsencrypt/cloudflare.ini -rw------- 1 root root 67 Jun 12 09:20 /etc/letsencrypt/cloudflare.ini
$ certbot plugins Saving debug log to /var/log/letsencrypt/letsencrypt.log ##### snipped ##### * dns-cloudflare Description: Obtain certificates using a DNS TXT record (if you are using Cloudflare for DNS). Interfaces: Authenticator, Plugin ##### snipped #####
$ sudo certbot certonly \ --dns-cloudflare \ --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \ --dns-cloudflare-propagation-seconds 60 \ --dry-run \ --non-interactive \ --agree-tos \ --email admin@example.com \ --no-eff-email \ -d example.com \ -d '*.example.com' Saving debug log to /var/log/letsencrypt/letsencrypt.log Simulating a certificate request for example.com and *.example.com Waiting 60 seconds for DNS changes to propagate The dry run was successful.
Quote the wildcard name so the local shell does not expand *.example.com before Certbot receives it.
$ sudo certbot certonly \ --dns-cloudflare \ --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \ --dns-cloudflare-propagation-seconds 60 \ --cert-name example.com-wildcard \ --non-interactive \ --agree-tos \ --email admin@example.com \ --no-eff-email \ -d example.com \ -d '*.example.com' Saving debug log to /var/log/letsencrypt/letsencrypt.log Requesting a certificate for example.com and *.example.com Waiting 60 seconds for DNS changes to propagate Successfully received certificate. Certificate is saved at: /etc/letsencrypt/live/example.com-wildcard/fullchain.pem Key is saved at: /etc/letsencrypt/live/example.com-wildcard/privkey.pem
example.com covers the bare domain, while *.example.com covers names such as app.example.com. The wildcard does not cover deeper names such as api.dev.example.com.
$ sudo certbot certificates --cert-name example.com-wildcard
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Found the following certs:
Certificate Name: example.com-wildcard
Domains: *.example.com example.com
Expiry Date: 2026-09-10 14:20:00+00:00 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/example.com-wildcard/fullchain.pem
Private Key Path: /etc/letsencrypt/live/example.com-wildcard/privkey.pem
Use these paths in the web server, load balancer, mail server, or other TLS service that will present the certificate.
$ sudo certbot renew --cert-name example.com-wildcard --dry-run Saving debug log to /var/log/letsencrypt/letsencrypt.log Processing /etc/letsencrypt/renewal/example.com-wildcard.conf Simulating renewal of an existing certificate for example.com and *.example.com Congratulations, all simulated renewals succeeded: /etc/letsencrypt/live/example.com-wildcard/fullchain.pem (success)