The DNS-01 challenge in Let's Encrypt's ACME protocol allows domain validation by creating a specific TXT record in your DNS zone. This method is particularly useful when:
- You can't expose HTTP/HTTPS ports (common in internal systems)
- You want to issue wildcard certificates (*.example.com)
- You need automation without web server access
Before proceeding, ensure you have:
1. A domain with DNS management access
2. Certbot 0.22.0+ installed
3. API access to your DNS provider (if automating)
4. Proper TXT record propagation time (typically 1-5 minutes)
For manual validation using Certbot:
certbot certonly \
--manual \
--preferred-challenges=dns \
--manual-auth-hook /path/to/auth-hook.sh \
-d example.com \
-d *.example.com
Certbot will pause and display the required TXT record:
_acme-challenge.example.com. 300 IN TXT "gfj9Xq...Rg85nM"
For popular DNS providers, use existing plugins:
# For Cloudflare
certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials ~/.secrets/cloudflare.ini \
-d example.com
# For Route53
certbot certonly \
--dns-route53 \
-d example.com
For unsupported providers, create an auth hook:
#!/bin/bash
# auth-hook.sh
DOMAIN="_acme-challenge.$CERTBOT_DOMAIN"
TXT_VALUE="$CERTBOT_VALIDATION"
# Use your DNS provider's API to add TXT record
curl -X POST "https://api.example-dns.com/records" \
-H "Authorization: Bearer $API_KEY" \
-d '{"type":"TXT","name":"'"$DOMAIN"'","content":"'"$TXT_VALUE"'"}'
To obtain a wildcard certificate:
certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials ~/.secrets/cloudflare.ini \
-d *.example.com \
-d example.com
After setting the TXT record, verify propagation:
dig TXT _acme-challenge.example.com +short
Common issues include:
- DNS propagation delays
- Incorrect TXT record format
- API rate limiting
- Permission issues with DNS provider
For automatic renewal, add to crontab:
0 0 * * * certbot renew \
--dns-cloudflare \
--dns-cloudflare-credentials ~/.secrets/cloudflare.ini \
--post-hook "systemctl reload nginx"
The DNS-01 challenge is an alternative to HTTP-01 validation in Let's Encrypt's ACME protocol. Instead of placing a file on your web server, you prove domain ownership by creating a specific TXT record in your domain's DNS zone.
Before using DNS-01 validation, ensure you have:
- Control over your domain's DNS records
- Certbot 0.9.3 or later installed
- API access to your DNS provider (if automating)
Here's how to manually complete DNS-01 validation:
certbot certonly --manual --preferred-challenges dns -d example.com
Certbot will prompt you to add a TXT record like:
_acme-challenge.example.com. 300 IN TXT "gfj9Xq...Rg85nM"
For automated renewals, use a DNS plugin. Example for Cloudflare:
certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials ~/.secrets/cloudflare.ini \
-d example.com -d *.example.com
Create a configuration file for automated renewals:
# /etc/letsencrypt/cli.ini
authenticator = dns-cloudflare
dns-cloudflare-credentials = /path/to/cloudflare.ini
preferred-challenges = dns
email = your@email.com
domains = example.com, *.example.com
Problem: DNS propagation delays
Solution: Add --dns-cloudflare-propagation-seconds 60
to wait longer
Problem: Wildcard certificates
Solution: DNS-01 is required for wildcards. Use the same process but include -d *.example.com
For more flexibility, consider acme.sh:
acme.sh --issue --dns dns_cf -d example.com -d *.example.com \
--yes-I-know-dns-manual-mode-enough-go-ahead-please
Always secure your DNS API credentials:
- Store credentials in files with 600 permissions
- Use API tokens with minimal permissions
- Consider IP restrictions for API access
Set up automatic renewal with cron:
0 0 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"