Wildcard SSL Certificate installed with Certbot on VPS

Wildcard SSL with Certbot + DNS Challenge

June 2026 · 7 min read

A Wildcard SSL Certificate is a single certificate that covers all subdomains of a single domain, such as *.example.com, which works for www, api, mail, staging, and any other subdomain — you don't need to issue separate certificates for each one. Let's Encrypt offers free Wildcard SSL, but you must use DNS Challenge instead of the standard HTTP Challenge.

Difference Between HTTP Challenge and DNS Challenge

Certbot has two methods to prove you own a domain:

Install Certbot on Ubuntu 22.04

# Install snap-based certbot (recommended)
sudo apt update
sudo apt install snapd -y
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

# Check version
certbot --version

Request Wildcard Certificate with Manual DNS

This method is suitable when your DNS provider doesn't have a certbot plugin. You must add the TXT record manually, but it works with any DNS provider:

# Request certificate for main domain and wildcard together
sudo certbot certonly \
  --manual \
  --preferred-challenges dns \
  -d "example.com" \
  -d "*.example.com"

Certbot will display the DNS challenge to add to your DNS:

Please deploy a DNS TXT record under the name:
_acme-challenge.example.com

with the following value:
oHbFTCFMzL_X_aBcDeFgHiJkLmNoPqRsTuVwXy

Before continuing, verify the TXT record is deployed with:
dig -t txt _acme-challenge.example.com
Do not press Enter immediately: After adding the TXT record to your DNS, wait 1-5 minutes for DNS to propagate and verify with dig first. If you press Enter before DNS propagates, certbot will fail and you'll need to start over.
# Verify DNS TXT record has propagated
dig -t txt _acme-challenge.example.com +short

# Or use nslookup
nslookup -type=TXT _acme-challenge.example.com 8.8.8.8

Set Up Auto-Renew with DNS Plugin (Cloudflare Example)

Manual Wildcard Certificates must be renewed every 90 days by hand. Setting up a DNS plugin allows automatic renewal:

# Install Cloudflare plugin
sudo snap install certbot-dns-cloudflare

# Create credentials file
sudo mkdir -p /etc/letsencrypt/cloudflare
sudo nano /etc/letsencrypt/cloudflare/credentials.ini
# Enter your Cloudflare API Token (must have Zone:DNS:Edit permission)
dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN
# Set secure permissions
sudo chmod 600 /etc/letsencrypt/cloudflare/credentials.ini

# Request Wildcard certificate with automatic renewal
sudo certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare/credentials.ini \
  -d "example.com" \
  -d "*.example.com" \
  --preferred-challenges dns-01

Use Certificate with Nginx

# Certificate location
ls /etc/letsencrypt/live/example.com/
# fullchain.pem  privkey.pem  cert.pem  chain.pem
# Configure Nginx server block
server {
    listen 443 ssl http2;
    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;

    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers off;

    # HSTS (6 months)
    add_header Strict-Transport-Security "max-age=15768000" always;
}
# Test config and reload
nginx -t && systemctl reload nginx

Set Up Auto-Renew and Test

# certbot timer is configured automatically when installed via snap
systemctl status snap.certbot.renew.timer

# Test renewal (dry-run)
sudo certbot renew --dry-run

# View existing certificates
sudo certbot certificates
Tip: Add a hook like --deploy-hook "systemctl reload nginx" to automatically reload nginx after successful renewal. Add this to /etc/letsencrypt/renewal/example.com.conf under the [renewalparams] section.

Verify Wildcard SSL is Working Correctly

# Verify issued certificate
sudo certbot certificates
# Should display: Domains: example.com *.example.com

# Test SSL with openssl
openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | \
  openssl x509 -noout -subject -dates

# Test with subdomain
openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null | \
  openssl x509 -noout -subject

# View expiration date
sudo certbot certificates | grep "Expiry Date"
Tip: Use curl -vI https://staging.example.com 2>&1 | grep -i "SSL\|certificate\|expire" to quickly test new subdomains without installing additional tools.

Common Issues & Troubleshooting

Error: "DNS problem: NXDOMAIN looking up TXT for _acme-challenge"

The TXT record hasn't propagated yet or was added to the wrong subdomain. Solution:

# Check TXT record from multiple nameservers
dig -t txt _acme-challenge.example.com @8.8.8.8 +short
dig -t txt _acme-challenge.example.com @1.1.1.1 +short

# If no result, wait 5 minutes and try again
# Some DNS providers have TTLs up to 10 minutes

Error: "An unexpected error occurred: The server will not issue certificates for the identifier"

Your domain is rate-limited by Let's Encrypt (requesting more than 5 certificates per domain per week). Wait 1 week or use the staging environment to test first:

# Test with staging (no rate limit, but certificate is not valid)
sudo certbot certonly \
  --manual \
  --preferred-challenges dns \
  --staging \
  -d "example.com" \
  -d "*.example.com"

Error: "certbot renew" doesn't work for manual Wildcard certificates

Manual renewal requires someone to be present to add the TXT record each time, which cannot be automated. You must switch to a DNS plugin:

# View current renewal config
cat /etc/letsencrypt/renewal/example.com.conf

# Line to modify
authenticator = manual
# Change to dns-cloudflare or plugin matching your DNS provider

Error: Nginx doesn't serve wildcard subdomains without a separate server block

You must configure server_name *.example.com and let Nginx handle unspecified subdomains with a default server block:

server {
    listen 443 ssl;
    server_name ~^(?<subdomain>.+)\.example\.com$;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    root /var/www/$subdomain;  # Each subdomain uses its own root directory
}

Frequently Asked Questions

Does Wildcard SSL cover sub-subdomains like a.b.example.com?

No. *.example.com works for www.example.com and api.example.com, but not a.b.example.com, which is a sub-subdomain. If you need to cover that level, you must request a separate certificate for *.b.example.com.

How long does a Let's Encrypt Wildcard SSL certificate last?

90 days, the same as regular Let's Encrypt certificates. Certbot automatically renews when 30 days remain. If you've set up the DNS plugin correctly, renewal happens silently with no additional action needed.

Can I use the same Wildcard certificate on multiple VPS servers?

Yes. The certificate issued by Let's Encrypt is a standard PEM file that you can copy to other servers. However, you must manage renewal on the primary server and sync the certificate files to other servers after each renewal.