How To Get a Wildcard SSL Certificate with Certbot Using a DNS Challenge
Tricknowtech Team 13 min read
Goal
By the end of this tutorial you will have a single Let's Encrypt wildcard TLS certificate covering both example.com and *.example.com, issued via a DNS-01 challenge through a Certbot DNS plugin, with automatic renewal confirmed to work non-interactively using the same stored credentials.
Prerequisites
An Ubuntu 22.04 LTS server (or similar Linux host) reachable over SSH, with a non-root user that has sudo privileges
A registered domain name (e.g. example.com) whose DNS is managed by a provider that has a Certbot DNS plugin, or that supports RFC 2136 dynamic DNS updates
The ability to install packages with apt (or snap) on the server
Either administrative access to an RFC 2136-capable authoritative DNS server you control (most commonly BIND) to create a TSIG key, or API access from a hosted DNS provider's control panel with permission to create a token scoped to edit records for that zone
Basic comfort with editing files and setting file permissions (chmod/chown) from the command line
Let an AI agent do this for you
Copy a ready-made prompt for an AI coding assistant with terminal access to your server (Claude Code, Cursor, or similar) — it can carry out the steps below for you. Review what it plans to run before it executes anything.
A wildcard certificate — one issued for *.example.com — lets a single TLS certificate secure an unlimited number of first-level subdomains (blog.example.com, api.example.com, staging.example.com) without requesting a new certificate every time you add one. Let's Encrypt issues these for free through the ACME protocol, but wildcard SAN entries come with one non-negotiable requirement: they can only be validated with a DNS-01 challenge, never an HTTP-01 challenge.
HTTP-01 proves domain control by asking your server to publish a specific file at http://example.com/.well-known/acme-challenge/TOKEN and having Let's Encrypt fetch it. That works for a single, already-existing hostname, but a wildcard covers every possible subdomain, including ones that don't exist yet — there is no single web-reachable path that could ever prove control over all of them. DNS-01 sidesteps this by asking you to prove control of the zone itself: you publish a TXT record at _acme-challenge.example.com containing a token tied to your ACME account, and Let's Encrypt looks that record up in DNS instead of over HTTP. Because editing a domain's DNS zone requires the same authority as owning the domain, this is accepted as proof for a wildcard SAN, and it's the only challenge type the CA/Browser Forum baseline requirements permit for wildcard issuance.
Doing this by hand every 90 days is impractical, so Certbot supports the DNS-01 challenge through DNS plugins that automate proving control of your zone — either by talking to a hosted DNS provider's REST API, or by sending an authenticated DNS UPDATE request (RFC 2136) directly to your own authoritative name server. Either way, the plugin creates the _acme-challenge TXT record automatically, waits for propagation, lets Let's Encrypt validate it, and deletes the record afterward. This tutorial walks through installing the right plugin, authorizing DNS-01 updates for your zone, requesting a wildcard certificate covering both the apex domain and *.example.com, and confirming unattended renewal will keep working.
“This tutorial uses the certbot-dns-rfc2136 plugin as the running example because RFC 2136 is a generic DNS protocol standard — implemented by self-hosted servers like BIND — rather than any single commercial DNS host, which keeps every command below reusable no matter who's in front of your domain's nameservers. If your zone is instead hosted by a third-party DNS provider, Certbot ships equivalent plugins for most of them: certbot-dns-cloudflare, certbot-dns-digitalocean, certbot-dns-route53 (AWS), certbot-dns-google, certbot-dns-ovh, and certbot-dns-linode, among others. Swap in the plugin that matches your actual DNS host; the overall flow, flag shapes, and file layout below carry over directly — only the plugin name and how you obtain its credentials change.”
Tricknowtech DNS Management
Cloudflare-backed DNS with instant propagation, all record types, free with hosting.
You'll need a domain, a server or hosting arrangement where you can install Certbot, and a way to prove control of that domain's DNS zone in an automatable way. This guide won't work with a DNS provider whose only management interface is a web UI with no API and no RFC 2136 support, since nothing in the chain would then be able to publish the _acme-challenge record without a human clicking through a form every 90 days. The full checklist Certbot needs in place before you start is below.
Step 1 — Installing Certbot and the DNS-01 Plugin
Update your package index and install Certbot along with the DNS plugin package. On Ubuntu 22.04, Certbot and most official DNS plugins are available directly from the repositories, named python3-certbot-dns-<plugin>.
Substitute the plugin package if you use a hosted DNS provider instead of running your own name server — for example python3-certbot-dns-cloudflare, python3-certbot-dns-digitalocean, python3-certbot-dns-route53, python3-certbot-dns-google, python3-certbot-dns-ovh, or python3-certbot-dns-linode. If your provider doesn't have a packaged plugin, check whether Certbot itself is installed via snap on your system (some guides recommend the snap install for faster plugin updates); in that case install the matching plugin snap instead, for example:
Don't mix installation methods — if Certbot came from apt, install the plugin from apt (or pip into the same environment); if it came from snap, install the plugin as a snap. Confirm the plugin registered correctly:
bash
certbot plugins
You should see an entry like dns-rfc2136 in the output alongside the standard webroot and nginx plugins (or dns-<provider> if you installed a hosted-provider plugin instead).
Step 2 — Generating a TSIG Key and Authorizing Dynamic Updates
RFC 2136 defines an authenticated DNS UPDATE mechanism: a client proves it's allowed to modify a zone by signing its update request with a shared secret called a TSIG (Transaction SIGnature) key, and the authoritative name server checks that signature before accepting the change. This is the generic mechanism the certbot-dns-rfc2136 plugin uses instead of a provider's web API, which is why it works against any RFC 2136-compliant server — most commonly a self-managed BIND install — without depending on any particular commercial DNS host. Generate a dedicated TSIG key on the machine running BIND (install the bind9-utils package first if tsig-keygen isn't already present):
bash
tsig-keygen -a hmac-sha512 example-com-certbot
This prints a key block similar to the one below; copy the secret value, since you'll need it both in BIND's configuration and in Certbot's credentials file.
Add that key definition to BIND's configuration (typically /etc/bind/named.conf.local on Ubuntu) and grant it update permission on the zone with an allow-update clause in the zone's stanza, then reload the running server:
“If your domain's DNS is hosted by a third-party provider rather than a name server you manage yourself, you won't have named.conf access — use that provider's own Certbot DNS plugin instead (certbot-dns-cloudflare, certbot-dns-digitalocean, certbot-dns-route53, certbot-dns-google, certbot-dns-ovh, certbot-dns-linode, and others are all officially maintained). Log in to the provider's control panel, generate an API token scoped to edit only that zone's DNS records, and skip ahead to Step 3, substituting that plugin's own credentials-file format for the one shown below.”
Step 3 — Storing the Credentials in a Protected File
Certbot's DNS plugins read credentials from a small file rather than accepting them as a command-line argument, so the secret doesn't end up in your shell history or process list. Because renewal later runs as root (via cron or a systemd timer), store this file under root's home directory rather than your own.
dns_rfc2136_server is the IP address your BIND server listens on for DNS UPDATE requests — this must be reachable from the machine running Certbot, not just reachable on port 53 for ordinary DNS queries. Lock the file down so only root can read it, then verify the permissions:
“The credentials file's expected field names are plugin-specific — check the plugin's own documentation, or run certbot --help dns-rfc2136 (substituting your plugin name) before assuming the format shown here. Some plugins, notably certbot-dns-route53, don't use a credentials file at all and instead read from the standard AWS credential chain (environment variables or an IAM instance role).”
Step 4 — Requesting the Wildcard Certificate
With the plugin installed and credentials in place, request the certificate with certbot certonly, passing the authenticator flag for your plugin, the path to the credentials file, and two -d flags: one for the apex domain and one for the wildcard. A wildcard SAN does not implicitly cover the bare apex, so both must be listed explicitly if you want a single certificate to cover example.com and every first-level subdomain.
“Quote the wildcard domain (*.example.com) exactly as shown. Without quotes, most shells will try to glob-expand the asterisk against filenames in your current directory before Certbot ever sees the argument.”
The --dns-rfc2136-propagation-seconds flag tells Certbot how long to wait after sending the DNS UPDATE before asking Let's Encrypt to check the TXT record, giving your name server time to make the change visible to Let's Encrypt's resolvers; the default is short, and you can raise it if you see validation failures caused by slow propagation or secondary-server sync. Certbot sends the signed UPDATE request, waits, triggers validation, and removes the TXT record automatically once issuance succeeds — no manual DNS editing and no port 80/443 exposure required at any point.
Step 5 — Verifying the Certificate Covers the Apex and the Wildcard
Once certonly finishes, confirm both names actually landed on the issued certificate. Certbot's own certificates subcommand lists every managed certificate along with its domains and expiry date:
bash
sudo certbot certificates
Look for a Domains: line reading example.com *.example.com under the certificate named for your domain. You can also inspect the certificate file directly to confirm the Subject Alternative Name extension lists both entries:
The output should include DNS:example.com and DNS:*.example.com. Remember that a wildcard only matches one DNS label: *.example.com covers foo.example.com and bar.example.com, but not foo.bar.example.com. If you need to cover a second level of subdomains, request a separate wildcard for that subdomain (for example *.staging.example.com) with its own -d flag.
Step 6 — Confirming Certbot Can Renew the Certificate Automatically
Because DNS-01 challenges require the same signing key at renewal time as at initial issuance, renewal only works unattended if the credentials file stays exactly where it was and Certbot's scheduled job runs with permission to read it. How that scheduled job is registered depends on how you installed Certbot: the apt package on Ubuntu 22.04 registers both a systemd timer (certbot.timer) and a legacy cron job under /etc/cron.d/certbot as a fallback, while the snap package manages its own systemd timer, snap.certbot.renew.timer, and does not use cron at all. Check whichever applies to your installation:
Certbot recorded which plugin and credentials file to use for this certificate in a per-domain renewal config file, so you don't need to pass any flags again — open it to confirm the paths are correct:
Finally, run a dry run to exercise the full renewal path — including a fresh DNS-01 challenge — without actually replacing the live certificate:
bash
sudo certbot renew --dry-run
A line reading "Congratulations, all simulated renewals succeeded" confirms the scheduled job, the plugin, and the stored credentials all still line up correctly.
“Never move, delete, or narrow the permissions on the credentials file referenced in the renewal config — unattended renewal has no way to prompt you for a replacement. If you ever rotate the TSIG key (or an API token, if you're using a hosted-provider plugin), update the same file in place immediately, or the next scheduled renewal will fail silently until someone notices the certificate is close to expiry.”
Conclusion
You installed Certbot along with the certbot-dns-rfc2136 plugin, generated a TSIG key and authorized it to make signed DNS UPDATE requests against your zone, and used certbot certonly with the plugin's --dns-rfc2136 flags to issue a wildcard certificate covering both example.com and *.example.com through a DNS-01 challenge — the only challenge type Let's Encrypt accepts for wildcard SAN entries. You then confirmed the issued certificate actually lists both names and verified that Certbot's scheduled renewal job — a systemd timer either way, plus a cron fallback on apt installs — can reach the same credentials to renew it automatically going forward, without any manual DNS editing or a web server ever needing to be publicly reachable. If your domain is hosted with a third-party DNS provider instead of a self-managed name server, the same certonly/renew flow applies unchanged — only the plugin name and how you obtain its credentials differ.