How to Create and Renew Wildcard SSL Certificates with Certbot and Let’s Encrypt
Creating a wildcard certificate for names such as *.example.com with Certbot and Let’s Encrypt always requires the ACME DNS-01 challenge rather than HTTP-01. Domain control is verified by publishing TXT records below _acme-challenge instead of placing HTTP validation files on an individual server. Let’s Encrypt introduced wildcard certificate support with ACMEv2 in March 2018, and this requirement has remained unchanged.
What You Will Learn
In this tutorial you will:
- Verify that wildcard DNS resolves as expected.
- Install Certbot together with the DNS plugin provided for your DNS service, or use a manual DNS challenge when API access is unavailable.
- Protect API credentials when DNS automation is enabled.
- Run
certbot certonlywith the appropriate options, including configurations that combine an apex domain and wildcard, several apex domains in one certificate, and multi-level subdomain structures, then verify the PEM files and prepare unattendedcertbot renewoperations with deployment hooks that automatically reload the web server. - Configure Nginx or Apache to handle TLS traffic with the generated certificate files.
The procedure applies to common Linux distributions. Package names can vary, so keep the documentation for your operating system and DNS provider available while following the steps.
Key Takeaways
- A certificate for
*.example.comcovers exactly one label below the apex, such asapi.example.com. It does not automatically coverexample.comunless that name is included separately, and it does not coverdev.api.example.com. - Wildcard certificates always require DNS validation. HTTP-01 can still validate individual hostnames, but a certificate authority requires DNS-based proof for wildcard issuance.
- Automatic renewal of wildcard certificates requires a compatible DNS plugin or another unattended method for updating DNS records. Manual TXT validation can still be used for issuance, but the TXT records must be updated manually again during every renewal unless DNS changes are automated.
- Production systems should automate renewal through systemd timers or cron because Let’s Encrypt certificates are valid for 90 days.
- Staging requests are useful when troubleshooting DNS validation or rate-limit problems without using production issuance limits. Use
--stagingwhile testing and remove it when requesting a trusted production certificate.
Why Wildcard Certificates Require DNS-01 Validation
HTTP-01 proves control over one specific hostname by requiring a token to be served from that host. A wildcard pattern represents many possible future hostnames, including names that may not yet resolve to your server, so validating one HTTP endpoint cannot demonstrate control over the entire DNS namespace. DNS-01 instead requires a TXT record under _acme-challenge at the authoritative DNS service responsible for the zone, which makes it suitable for wildcard validation.
Manual DNS Validation vs. an Automated Certbot DNS Plugin
| Topic | Manual --manual DNS |
DNS Provider Plugin |
|---|---|---|
| API token | Not required | Requires DNS write permission |
| Best use | Occasional or isolated environments | Production renewal automation |
| Renewal | Manual TXT changes unless DNS is scripted | certbot renew updates TXT records automatically |
| Interaction | Stops and waits for TXT record creation | Runs without user interaction |
Prerequisites
You should already have:
- A domain for which you control DNS records used during certificate issuance and renewal. Check the Certbot DNS plugin directory to determine whether your DNS provider is supported.
- A Linux system with
sudoaccess.
Use the newest Certbot release available through your Linux distribution or Snap. Installation methods differ between systems.
- For package-based installations, follow an appropriate Certbot standalone installation guide for your Linux distribution.
- For newer Ubuntu releases, use the installation method recommended for the version you are running.
- The Certbot project also publishes Snap installation instructions. On Ubuntu, Snap is the preferred installation method. DNS plugins are installed separately and connected to the Certbot Snap.
- For additional background about the certificates issued by Let’s Encrypt, consult an introduction to Let’s Encrypt.
If you already operate Nginx or Apache but have not configured wildcard certificate automation, consult a Certbot HTTPS setup guide for the web server you use.
Step 1: Configure Wildcard DNS
Point *.example.com to the server or load balancer that should receive HTTPS requests. A typical DNS record can look like this:
*.example.com. 3600 IN A 203.0.113.1
The * label matches one leftmost hostname level. For example, *.example.com matches app.example.com, but it does not match example.com or dev.app.example.com.
If you are creating the record for the first time, you can temporarily reduce the TTL from a value such as 3600 seconds to a lower value such as 300. A shorter TTL causes DNS resolvers to discard cached results sooner, allowing corrections to propagate more quickly. After the record is stable and Let’s Encrypt validation has succeeded, the TTL can be increased again to reduce DNS query load.
Refer to the DNS record management documentation supplied by your DNS provider.
Verify propagation with dig or host:
dig +short A app.example.com
host app.example.com
Confirm that an A or CNAME response is returned before continuing.
Step 2: Install the Appropriate Certbot DNS Plugin
Certbot provides three common approaches to DNS validation: completely manual validation without an API, a DNS plugin installed through the operating system package manager, or a DNS plugin installed through Snap. Select the method that corresponds to the way Certbot is installed and whether your DNS provider offers API access.
Option A: Manual DNS Validation
Use manual mode if your DNS provider does not offer suitable API access or if you only need to issue the certificate once:
sudo certbot certonly –manual –preferred-challenges dns \
-d ‘*.example.com’ -d ‘example.com’
Certbot displays the TXT values that must be created. Add them through your DNS provider, wait until the records have propagated, and then continue in the terminal. The same interactive step is required during every renewal, so an unattended certbot renew process started by cron or a systemd timer will eventually fail while waiting for human input. Renewal alternatives are covered in Step 7.
Option B: Automated DNS Validation with a Package Manager
Install the Certbot DNS plugin supplied for your provider through your Linux distribution. The exact package name depends on the DNS service and distribution.
sudo apt install python3-certbot-dns-provider
On Fedora or RHEL 8 and newer, use dnf with the corresponding package:
sudo dnf install python3-certbot-dns-provider
List the available Certbot plugins to confirm that the provider plugin has been registered:
certbot plugins
The DNS provider plugin should appear together with plugins such as standalone and webroot.
Option C: Automated DNS Validation with Snap
On Ubuntu 22.04 and newer, Certbot is commonly distributed as a Snap, while a package-manager version of a particular DNS plugin may be unavailable or older. Install the Certbot Snap first if it is not already installed:
sudo snap install –classic certbot
Allow Certbot to use plugins that require elevated privileges:
sudo snap set certbot trust-plugin-with-root=ok
Install the Snap package for your DNS provider plugin:
sudo snap install certbot-dns-provider
Connect the DNS plugin to Certbot:
sudo snap connect certbot:plugin certbot-dns-provider
Confirm that Certbot recognizes the plugin:
certbot plugins
The DNS provider plugin should now be listed. You can then continue with the credential configuration in Step 3.
For a more focused setup, consult a DNS validation guide for the operating system and Certbot installation method you use.
Step 3: Configure the Certbot DNS Plugin
Create a credentials file that only the required system account can read. A suitable path on production systems is /etc/letsencrypt/certbot-creds.ini, which keeps the credential file together with other Certbot data. You can alternatively store it inside the appropriate user home directory.
sudo nano /etc/letsencrypt/certbot-creds.ini
The exact credential key depends on your DNS provider. A provider plugin may use a configuration similar to the following:
/etc/letsencrypt/certbot-creds.ini
dns_provider_token = paste_your_write_scoped_token_here
Create an API token with permission to modify DNS records instead of granting unnecessary full account access. Restricting the token to DNS write access limits the impact if the credential is exposed. After saving the file, change its permissions so only root can read it:
sudo chmod 600 /etc/letsencrypt/certbot-creds.ini
Restrictive file permissions also prevent Certbot from reporting security warnings about an exposed credentials file.
Step 4: Retrieve the Wildcard Certificate
Use certbot certonly when issuing wildcard certificates. Installer modes such as --nginx and --apache do not automatically configure wildcard virtual hosts, so certonly is the supported approach. The following sections cover automated DNS-plugin issuance, staging tests, generated files, multiple apex domains, and multi-level subdomains.
Automated Certificate Request with a DNS Provider Plugin
Request both the apex domain and wildcard name in one command if your service handles HTTPS traffic for both:
sudo certbot certonly \
–dns-provider \
–dns-provider-credentials /etc/letsencrypt/certbot-creds.ini \
–dns-provider-propagation-seconds 60 \
-d ‘example.com’ \
-d ‘*.example.com’
The DNS propagation option determines how long Certbot waits after creating the _acme-challenge TXT record before validation begins. The default and recommended delay depend on the DNS plugin and provider. DNS updates may require 30 to 60 seconds or longer. A value of 60 seconds can be a safer starting point, while 120 seconds or more can be used if validation fails. Other DNS plugins provide equivalent options, although their names and appropriate values can differ.
The --nginx and --apache installers do not automatically create wildcard virtual-host configurations, so certonly remains the appropriate method for wildcard issuance.
Test with the Let’s Encrypt Staging Environment
Add --staging while testing DNS configuration or deployment hooks. Staging certificates are not trusted by browsers, but staging avoids consuming production rate limits. Remove --staging only after the complete test succeeds.
Expected Certificate Files
After successful issuance, Certbot stores PEM files below /etc/letsencrypt/live/example.com/. The directory normally corresponds to the first -d domain supplied in the request:
fullchain.pemprivkey.pemchain.pemcert.pem
Multiple Domains and Multi-Level Wildcard Coverage
A single certbot certonly command can contain several Subject Alternative Names by supplying multiple -d options. Consult the official Let’s Encrypt rate-limit documentation for the current SAN-related limits. The following patterns are commonly used.
Apex Domain and Wildcard in One Certificate
This is the most common configuration and is shown in the automated example above. Without the apex domain, the wildcard alone does not cover example.com. For example, *.example.com matches api.example.com, but not the bare example.com domain.
Multiple Apex Domains in One Certificate
If you operate several domains, combining them into one certificate can reduce the number of renewal configurations that must be monitored:
sudo certbot certonly \
–dns-provider \
–dns-provider-credentials /etc/letsencrypt/certbot-creds.ini \
–dns-provider-propagation-seconds 60 \
-d ‘example.com’ -d ‘*.example.com’ \
-d ‘example.net’ -d ‘*.example.net’
Each domain requires its own wildcard TXT validation record. Certbot therefore performs the required DNS API operations for every domain, and all validation records must propagate before Let’s Encrypt can continue.
Multi-Level Subdomains
The ACME specification in RFC 8555 limits a wildcard to one label. Therefore, *.example.com does not match v2.api.example.com. To cover that subdomain branch, request another wildcard:
sudo certbot certonly \
–dns-provider \
–dns-provider-credentials /etc/letsencrypt/certbot-creds.ini \
–dns-provider-propagation-seconds 60 \
-d ‘api.example.com’ \
-d ‘*.api.example.com’
This certificate covers api.example.com and one-level subdomains beneath it, such as v1.api.example.com and v2.api.example.com. It does not cover example.com or *.example.com.
Step 5: Verify the Wildcard Certificate
Use OpenSSL to inspect the issued certificate. Check the SAN entries to confirm that all requested names are included:
sudo openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem \
-noout -text | grep -A1 “Subject Alternative Name”
The result should contain DNS:*.example.com together with any additional names supplied using -d. A certificate requested with -d 'example.com' -d '*.example.com' should contain both entries.
Also inspect the validity dates and confirm that the expiration date is approximately 90 days from issuance:
sudo openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem \
-noout -dates
The output contains notBefore and notAfter timestamps. If notAfter is less than 30 days away, you may be inspecting an older certificate instead of the newly issued one.
The four PEM files below /etc/letsencrypt/live/example.com/ have different purposes:
| File | Contents | Usage |
|---|---|---|
fullchain.pem |
Server certificate together with the intermediate CA certificate | The certificate chain that the web server should send to clients |
privkey.pem |
Private key | Required as the server’s private TLS credential |
cert.pem |
Server certificate without the intermediate chain | Useful for inspection, but normally not appropriate as the production ssl_certificate file |
chain.pem |
Intermediate CA certificate only | Used separately by some TLS configurations |
Step 6: Configure Nginx or Apache to Use the Certificate Files
certbot certonly generates the certificate but does not modify your web server configuration. Add the certificate paths and TLS configuration to the relevant virtual hosts or server blocks yourself.
Nginx Configuration for a Wildcard Certificate
The following Nginx server block uses both the wildcard pattern and apex domain in server_name so that Nginx can match both:
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name example.com *.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Paste current TLS settings from the Mozilla SSL Configuration Generator
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
# Your application directives go here
root /var/www/html;
index index.html;
}
# Redirect HTTP to HTTPS
server {
listen 80;
listen [::]:80;
server_name example.com *.example.com;
return 301 https://$host$request_uri;
}
For TLS protocol and cipher configuration, use the Mozilla SSL Configuration Generator and select Nginx with the Intermediate profile. The generator creates current ssl_protocols and ssl_ciphers settings based on the selected Nginx and OpenSSL versions, which is more dependable than keeping a static cipher configuration that can become outdated.
The ssl_session_cache shared:SSL:10m directive provides a shared 10 MB TLS session cache for Nginx workers, supporting approximately 40,000 sessions and allowing faster resumed TLS handshakes. ssl_session_timeout 1d keeps cached sessions valid for one day.
fullchain.pem contains both the server certificate and the intermediate CA certificate. Configure ssl_certificate to use fullchain.pem instead of cert.pem, because clients with older trust stores may otherwise reject the certificate chain.
Test the Nginx configuration and reload the service after making changes:
sudo nginx -t && sudo systemctl reload nginx
Apache Configuration for a Wildcard Certificate
The equivalent Apache VirtualHost configuration uses ServerAlias with the wildcard pattern to extend matching beyond the bare apex domain:
<VirtualHost *:443>
ServerName example.com
ServerAlias *.example.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
# Paste TLS settings from https://ssl-config.mozilla.org (Apache, Intermediate)
DocumentRoot /var/www/html
</VirtualHost>
# Redirect HTTP to HTTPS
<VirtualHost *:80>
ServerName example.com
ServerAlias *.example.com
RewriteEngine On
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>
Use the Mozilla SSL Configuration Generator with Apache and the Intermediate profile to obtain current SSLProtocol and SSLCipherSuite settings appropriate for your Apache and OpenSSL versions, then place those directives in the configuration.
SSLCertificateFile should reference fullchain.pem, which contains both the server certificate and intermediate CA certificate. This is the appropriate configuration for Apache 2.4.8 and newer. The older SSLCertificateChainFile directive became unnecessary beginning with Apache 2.4.8 because SSLCertificateFile can contain the complete certificate chain. On Apache 2.4.8 or newer, use SSLCertificateFile with fullchain.pem and remove an existing SSLCertificateChainFile directive.
The HTTP redirect shown above requires mod_rewrite. Enable the required modules if they are not active:
sudo a2enmod rewrite ssl headers
Test the Apache configuration and reload the service:
sudo apachectl configtest && sudo systemctl reload apache2
The equivalent commands can differ on RHEL-based systems, where the Apache service is commonly named httpd.
Step 7: Automate Wildcard Certificate Renewal
This step covers fully automated certificate renewal without recurring manual work. It explains why manual validation should be avoided for unattended renewal, how to verify that the DNS plugin is configured, how to inspect the renewal schedule, and how to reload a web server after a certificate is renewed.
Why Certificates Created in Manual Mode Cannot Renew Unattended
When a certificate is issued with --manual, Certbot stores that method in /etc/letsencrypt/renewal/example.com.conf:
[renewalparams]
authenticator = manual
Every renewal attempt then waits for a user to update the TXT record manually. When the command runs through cron or a systemd timer, the process eventually times out and renewal fails.
When the certificate is created through a DNS provider plugin instead, the renewal configuration contains the plugin authenticator and credentials path:
[renewalparams]
authenticator = dns-provider
dns_provider_credentials = /etc/letsencrypt/certbot-creds.ini
With those settings, certbot renew can complete the DNS-01 validation process without human interaction.
Verify the Renewal Configuration
Inspect the renewal configuration and make sure its authenticator points to your DNS plugin before depending on unattended renewal:
sudo cat /etc/letsencrypt/renewal/example.com.conf
You should see the DNS provider authenticator below [renewalparams]. If the file still contains authenticator = manual from an older certificate request, issue the certificate again with the DNS plugin as described in Step 4 so Certbot can update the renewal configuration.
Confirm the Certbot Systemd Timer
On Ubuntu and Debian, Certbot commonly installs a systemd timer that checks for renewal twice each day. The unit name depends on the installation method:
- systemctl status certbot.timer
- snap.certbot.renew.timer
systemctl status certbot.timer
If no timer exists, such as on a system where Certbot was installed with pip instead of apt or snap, create an equivalent cron job:
0 */12 * * * root certbot renew –quiet
Place this entry in /etc/cron.d/certbot. If you add it through sudo crontab -e instead, leave out the root field because the username column is only used in files below /etc/cron.d/.
You can place the entry in /etc/cron.d/certbot or configure it through crontab -e for the root account.
Test the Renewal Process
Always perform a dry run before depending on automatic certificate renewal:
sudo certbot renew –dry-run
A dry run simulates the complete ACME workflow, including the DNS-01 challenge, against the Let’s Encrypt staging environment instead of the production certificate authority. If the test fails, correct the problem before the real certificate approaches expiration. Common causes include an incorrect credentials path or an API token that does not have sufficient DNS permissions.
A dry run reproduces the complete ACME exchange, including DNS-01 validation, without replacing the production certificate files or contacting the production certificate authority. If the test fails, resolve the underlying problem, which is often an incorrect credentials file path or insufficient DNS API permissions, before the active certificate nears expiration.
Reload Services After a Successful Renewal
Certbot can execute a command immediately after a certificate has been renewed successfully. There are two ways to configure this behavior.
When requesting the certificate, include --deploy-hook with certbot certonly:
sudo certbot certonly \
–dns-provider \
–dns-provider-credentials /etc/letsencrypt/certbot-creds.ini \
–dns-provider-propagation-seconds 60 \
-d ‘example.com’ -d ‘*.example.com’ \
–deploy-hook “systemctl reload nginx”
Certbot stores the deployment hook in /etc/letsencrypt/renewal/example.com.conf, allowing it to run automatically after future successful renewals. The option does not need to be supplied again.
For an existing certificate, create an executable script inside the deployment hooks directory. Certbot checks this directory after successful renewal operations:
sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
#!/bin/sh
systemctl reload nginx
Make the script executable:
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
Scripts in this directory apply to all certificates managed by Certbot on the system. This can be convenient if several certificates use the same web server. If a hook should apply only to one certificate, configure --deploy-hook specifically when issuing that certificate.
Deployment hooks run only when Certbot actually renews a certificate. They do not run when a renewal check determines that the current certificate remains valid. Certbot periodically checks certificate expiration and renews certificates when necessary. Because deployment hooks execute only after a successful renewal, they are the appropriate choice for reloading services such as Nginx or Apache.
Pre-hooks and post-hooks run before and after renewal attempts regardless of whether a certificate is changed. They are useful when a web server must be stopped for standalone validation that requires port 80. DNS plugins generally do not require these hooks, and using them unnecessarily can create additional log output. For routine web server reloads after renewal, use deployment hooks.
Wildcard Certificate Troubleshooting
TXT Record Does Not Propagate
Diagnosis
Check whether the _acme-challenge.example.com TXT record can be queried from the authoritative DNS servers:
dig TXT _acme-challenge.example.com +short
If the expected value is missing, the DNS record has not propagated yet.
Resolution
Wait until repeated DNS queries consistently return the expected TXT value.
If automated validation through the DNS plugin frequently fails, increase the provider-specific DNS propagation waiting period, for example:
–dns-provider-propagation-seconds 120
Certificate Does Not Cover the Required Hostname
Diagnosis
If a certificate covers subdomains such as api.example.com but not example.com, the certificate was probably requested with only the wildcard name.
Resolution
Include both names when issuing the certificate:
-d example.com -d ‘*.example.com’
A wildcard such as *.example.com never includes the apex domain automatically.
Sub-Subdomains Are Not Matched
Diagnosis
If v2.api.example.com is not included in a certificate for *.example.com, the reason is that wildcard certificates match only one hostname level.
Resolution
Request another wildcard for the deeper subdomain level:
-d ‘api.example.com’ -d ‘*.api.example.com’
DNS Plugin Authentication Errors
Diagnosis
Renewal operations fail with authentication-related plugin errors or DNS API failures.
Resolution
- Rotate the DNS API token.
- Confirm that the token includes DNS write permissions.
- Verify that the credentials file on disk uses the same path recorded in the Certbot renewal configuration under
/etc/letsencrypt/renewal/*.conf.
Let’s Encrypt Rate-Limit Errors
Diagnosis
Certbot reports messages such as “Too many certificates” or another rate-limit error.
Resolution
- Temporarily use the staging environment with
--stagingwhile testing and troubleshooting. - After correcting the underlying problem, try again without
--staging.
Renewal Configuration Still Uses Manual Authentication
Diagnosis
The Certbot renewal configuration continues to use manual authentication, which prevents unattended renewal.
Resolution
Issue the certificate again with the DNS provider plugin as described in Step 4. Certbot will update the renewal configuration so later renewals use the automated validation method.
Web Server Still Serves the Previous Certificate
Diagnosis
certbot renew finishes successfully, but the website continues to present an older certificate.
Resolution
Check whether a deployment hook is configured.
Inspect /etc/letsencrypt/renewal/example.com.conf for a renewal or deployment hook.
You can also inspect the deployment hook directory:
ls /etc/letsencrypt/renewal-hooks/deploy/
If no hook exists, reload the web server manually:
sudo systemctl reload nginx
To automate this operation for future renewals, configure a deployment hook as described in Step 7.
If renewed certificate files are present but the server continues to provide outdated TLS material, inspect the web server SSL certificate and HTTPS redirect configuration.
Frequently Asked Questions About Certbot Wildcard Certificates
1. Do I Need Separate Certificates for the Apex Domain and Wildcard?
No. If HTTPS is used on both example.com and *.example.com, include both names in a single request. Supply two -d options as demonstrated in Step 4. Let’s Encrypt stores them as separate SAN entries in one certificate, and one renewal configuration can maintain both names.
2. Why Does Certbot Reject HTTP Validation for a Wildcard Request?
Let’s Encrypt issues wildcard certificates only after successful DNS-01 validation. HTTP-01 cannot demonstrate control over every possible hostname beneath a domain, so a wildcard request cannot be validated through HTTP alone.
3. How Often Do Files in /etc/letsencrypt/live/ Change?
Certbot updates the symbolic links whenever renewal succeeds. Applications should reference the files inside the live directories instead of using copied certificate files so that they always point to the renewed material. If an application keeps the certificate file descriptor open from startup instead of reading the symbolic link again, a reload hook may still be required.
4. Can *.api.example.com and *.example.com Be Included in the Same Certificate?
Yes. Both wildcard names can be included in one certificate by adding -d '*.api.example.com' together with the other -d values. Certbot performs a separate DNS-01 validation for every wildcard label, which means separate _acme-challenge TXT records are created at _acme-challenge.example.com and _acme-challenge.api.example.com. Each additional wildcard also requires its own DNS API operation during renewal.
Several wildcard names can be combined into one certificate, although separate certificates can sometimes make administration simpler and reduce the effect of a compromised private key.
5. Does a Wildcard Certificate Replace Certificates for Individual Hosts?
Wildcard certificates can reduce the total number of certificates that must be managed, but they also increase the impact if the associated private key is compromised. Many environments therefore combine both approaches, such as using a wildcard certificate on edge load balancers while using individual service certificates inside an internal service network.
Conclusion
You now know how wildcard certificates issued by Let’s Encrypt through Certbot depend on DNS validation, how manual certificate requests differ from automated DNS-plugin validation, how multiple domains and different wildcard subdomain levels can be included in certificate requests, how Nginx or Apache can be configured to serve TLS with the resulting certificate files, and how certificates can be verified and renewed automatically without unexpected service interruption.


