Security

Wildcard SSL Certificates with Let's Encrypt

Generate a wildcard SSL certificate for *.tuodominio.com using Certbot and DNS challenge

What Are Wildcard Certificates?

A wildcard SSL certificate covers a domain and all its direct subdomains:

  • *.tuodominio.com: covers api.tuodominio.com, mail.tuodominio.com, app.tuodominio.com, etc.
  • Does NOT cover sub.api.tuodominio.com (nested subdomains)
  • Single certificate for unlimited direct subdomains

When to use:

  • Multiple subdomains on the same physical server
  • Simplifies certificate management (one renewal instead of many)
  • Reduces certificate chain overhead

When NOT to use:

  • Different teams managing different subdomains (use SAN certificates instead)
  • Nested subdomains (sub.api.tuodominio.com requires *.api.tuodominio.com)

Why DNS Challenge Is Required

Let's Encrypt uses two validation methods:

  • HTTP challenge, places a file in .well-known/acme-challenge/

    • Only proves control of the domain itself
    • Cannot verify *.tuodominio.com (the wildcard apex)
  • DNS challenge, adds a TXT record to DNS

    • Proves control of the DNS zone
    • Required for wildcard certificates

Therefore, wildcard certificates require DNS validation.

Install Certbot and DNS Plugins

Base installation:

sudo apt update
sudo apt install certbot python3-certbot-nginx

For Cloudflare DNS

If your domain uses Cloudflare, install the Cloudflare plugin:

sudo apt install python3-certbot-dns-cloudflare

For Other DNS Providers

Install the appropriate plugin:

  • Route53 (AWS): python3-certbot-dns-route53
  • DigitalOcean: python3-certbot-dns-digitalocean
  • Hetzner: python3-certbot-dns-hetzner
  • Generic/manual: use --manual flag (see below)

View all available plugins:

certbot plugins

Method 1: Manual DNS Challenge

Use this for any DNS provider or one-off testing:

sudo certbot certonly --manual --preferred-challenges dns \
  -d "tuodominio.com" \
  -d "*.tuodominio.com"

Certbot will prompt you:

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

with the following value:
  eG9zdGluZ19jaGFsbGVuZ2VfdmFsdWU=

Before continuing, verify the record is deployed
Press Enter to continue

Steps:

  1. Add the TXT record in your DNS provider's control panel

    • Name: _acme-challenge.tuodominio.com
    • Type: TXT
    • Value: (the value provided by Certbot)
    • TTL: 300 seconds
  2. Verify propagation:

    dig _acme-challenge.tuodominio.com TXT
    # or
    nslookup -type=TXT _acme-challenge.tuodominio.com
  3. Press Enter in Certbot to continue validation

Certificate will be saved to /etc/letsencrypt/live/tuodominio.com/

Manual DNS challenge does NOT auto-renew. For production, use a DNS plugin (Method 2) so renewals happen automatically every 60 days.

Method 2: Automatic Renewal with Cloudflare

If using Cloudflare, this method auto-renews without manual intervention.

Step 1: Create Cloudflare Credentials File

Create /root/.secrets/certbot/cloudflare.ini (owner must be root):

# Cloudflare API token credentials
dns_cloudflare_api_token = your_cloudflare_api_token_here

Get your API token:

  1. Log in to Cloudflare Dashboard
  2. Go to Account Settings → API Tokens
  3. Create a token with "Zone DNS" permissions
  4. Copy the token

Set secure permissions:

sudo mkdir -p /root/.secrets/certbot
sudo nano /root/.secrets/certbot/cloudflare.ini
# Paste credentials, save and exit
sudo chmod 600 /root/.secrets/certbot/cloudflare.ini

Step 2: Run Certbot with Cloudflare Plugin

sudo certbot certonly --dns-cloudflare \
  --dns-cloudflare-credentials /root/.secrets/certbot/cloudflare.ini \
  -d "tuodominio.com" \
  -d "*.tuodominio.com"

Certbot will:

  • Connect to Cloudflare API
  • Add TXT records automatically
  • Wait for DNS propagation
  • Validate and issue the certificate

Step 3: Verify Auto-Renewal

Check the renewal configuration:

sudo certbot renew --dry-run

This simulates a renewal without actually requesting a new certificate. Output should show success:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/tuodominio.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not yet due for renewal

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
All simulations succeeded. You may want to run Certbot again when
certificates are due for renewal.

The renewal daemon (certbot.timer for systemd) runs automatically.

Using the Wildcard Certificate in Nginx

Configuration is identical to regular certificates:

server {
    listen 443 ssl http2;
    server_name tuodominio.com *.tuodominio.com;

    ssl_certificate /etc/letsencrypt/live/tuodominio.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/tuodominio.com/privkey.pem;

    # ... rest of SSL configuration
}

Reload Nginx:

sudo nginx -t  # Test syntax
sudo systemctl reload nginx

All subdomains are now served with the same certificate:

  • https://tuodominio.com
  • https://api.tuodominio.com
  • https://mail.tuodominio.com
  • https://cdn.tuodominio.com

Auto-Renewal Strategy

DNS Plugin Renewals (Automatic)

When using --dns-cloudflare or similar:

  • Certbot daemon checks daily
  • Renews automatically 30 days before expiry
  • No manual action required
  • Safe for production

If you used --manual:

  • Manual renewal required every 90 days
  • Set a calendar reminder
  • Run the same certbot command again
  • Certificate will not renew automatically

Always use a DNS plugin for production environments. The manual method is suitable only for testing or rare one-off certificates.

Verification

Check that your wildcard certificate covers all subdomains:

# View certificate details
echo | openssl s_client -connect tuodominio.com:443 2>/dev/null | openssl x509 -noout -text | grep -A1 "Subject Alternative Name"

Expected output:

X509v3 Subject Alternative Name:
    DNS:tuodominio.com, DNS:*.tuodominio.com

Test a subdomain:

echo | openssl s_client -connect api.tuodominio.com:443 2>/dev/null | openssl x509 -noout -subject

Output:

subject=CN=tuodominio.com

Check certificate expiry:

sudo certbot certificates

Output example:

Found the following certs:
  Certificate Name: tuodominio.com
    Domains: tuodominio.com, *.tuodominio.com
    Expiry Date: 2026-06-26

Troubleshooting

DNS propagation is slow:

# Monitor TXT record propagation
watch -n 2 'dig _acme-challenge.tuodominio.com TXT +short'

Certificate renewal is failing:

# Check renewal logs
sudo journalctl -u certbot.timer -n 50
sudo tail -f /var/log/letsencrypt/letsencrypt.log

Cloudflare API token issues:

  • Verify token has "Zone DNS" permissions
  • Check that the domain is active on Cloudflare
  • Confirm credentials file permissions: chmod 600

Checklist

  • Install Certbot and DNS plugin
  • Configure DNS credentials (for automatic renewal)
  • Issue wildcard certificate with DNS challenge
  • Verify TXT record deployment
  • Test certificate with openssl s_client
  • Configure Nginx/Apache to use the certificate
  • Test all subdomains with HTTPS
  • Run certbot renew --dry-run to verify auto-renewal
  • Set up monitoring/alerts for certificate expiry (optional)

On this page