Skip to main content

DNS-01 Challenge

The DNS-01 Challenge validates domain control through a TXT record in DNS, without requiring an accessible web server.

This is the only method that allows generating wildcard certificates (*.domain.com), which automatically work for all subdomains of your domain - whether api.domain.com, blog.domain.com, admin.domain.com, or any other you create in the future.

How does it work?​

Understanding the flow:

The diagram above shows communication between three components: the ACME Client (like Certbot or acme.sh), the Let's Encrypt server, and your domain's DNS Server.

  1. Initial request: The ACME client (running on any machine with internet access) requests a certificate for the desired domain

  2. DNS challenge: Let's Encrypt responds with a unique token and instructs: "prove you control this domain by creating a specific TXT record"

  3. Record creation: The ACME client uses your DNS provider's API (Cloudflare, Route53, etc.) to automatically create the TXT record _acme-challenge.domain.com with the received token

  4. Verification: Let's Encrypt queries public DNS servers to verify the TXT record exists and contains the correct token

  5. Issuance: After successful validation, Let's Encrypt issues the certificate and sends it to the ACME client

  6. Cleanup: The TXT record can be removed after issuance (the ACME client usually does this automatically)

Certbot runs separately

The ACME client (Certbot) doesn't need to run on the same server as your applications. It only needs:

  • Internet access to communicate with Let's Encrypt
  • Your DNS provider's API credentials to create/remove TXT records
  • A location to save the generated certificates

After issuance, you distribute the certificates to the servers that need them (via rsync, NFS, Kubernetes Secrets, etc.).

DNS record example​

# TXT record that needs to be created
_acme-challenge.domain.com. 300 IN TXT "gfj9Xq...Rg85nM"

When to use DNS-01?​

ScenarioWhy use DNS-01?
Wildcard CertificatesOnly method that supports *.domain.com
Internal serversDoesn't require public exposure on port 80
Multiple serversOne certificate for several servers
Port 80 blockedFirewall or ISP blocks HTTP

Automation with DNS Providers​

The biggest challenge with DNS-01 is automation. Creating TXT records manually doesn't scale. The solution is to use plugins that integrate with your DNS provider's API.

Certbot with DNS plugins​

# Cloudflare
sudo apt install python3-certbot-dns-cloudflare
certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials ~/.secrets/cloudflare.ini \
-d "*.domain.com" -d domain.com

# Route53 (AWS)
sudo apt install python3-certbot-dns-route53
certbot certonly --dns-route53 -d "*.domain.com"

# Google Cloud DNS
sudo apt install python3-certbot-dns-google
certbot certonly --dns-google \
--dns-google-credentials ~/.secrets/google.json \
-d "*.domain.com"

Credentials file (Cloudflare example)​

# ~/.secrets/cloudflare.ini
dns_cloudflare_api_token = your_token_here
# Secure permissions
chmod 600 ~/.secrets/cloudflare.ini

acme.sh (lightweight alternative)​

acme.sh is an ACME client in pure shell script, lighter than Certbot.

# Example: Wildcard certificate with Cloudflare
export CF_Token="your_token"
acme.sh --issue --dns dns_cf -d "*.domain.com" -d domain.com

# Example: Wildcard certificate with AWS Route53
export AWS_ACCESS_KEY_ID="xxx"
export AWS_SECRET_ACCESS_KEY="xxx"
acme.sh --issue --dns dns_aws -d "*.domain.com"
Wildcard Security

A compromised wildcard certificate affects all subdomains. Consider specific certificates for critical subdomains (api, admin, etc).

DNS Propagation​

DNS-01 depends on TXT record propagation:

# Check if the record has propagated
dig TXT _acme-challenge.domain.com

# Typical propagation time
# - Cloudflare: seconds
# - Route53: 60 seconds
# - Traditional registrars: up to 48 hours
Common problem: validation fails due to propagation

Scenario: Certbot creates the TXT record and immediately asks Let's Encrypt to verify. But Let's Encrypt queries DNS servers that haven't yet received the update β†’ validation fails.

Solution: Use --dns-cloudflare-propagation-seconds 60 to force Certbot to wait 60 seconds after creating the record before requesting verification. Adjust the value according to your DNS provider.

Advantages and Disadvantages​

Advantages:

  • Supports wildcard certificates
  • Works with internal servers (not exposed to internet)
  • Doesn't require port 80 open
  • One certificate can serve multiple servers

Disadvantages:

  • Requires DNS provider API access
  • DNS propagation can take time
  • More complex to configure initially
  • DNS credentials are sensitive

Distribution to multiple servers​

When you have multiple machines in separate environments, there are different strategies to distribute certificates:

By increasing complexity​

ScenarioRecommended solution
Few servers, same networkrsync/scp with cron
Multi-cloud or isolated networksHashiCorp Vault or AWS Secrets Manager
Kubernetescert-manager (issues directly in cluster)
CDN/Load BalancerCentralized TLS termination

1. rsync/scp (simple)​

# On server with Certbot, after renewal
certbot renew --deploy-hook "rsync -avz /etc/letsencrypt/ user@server2:/etc/letsencrypt/"

2. HashiCorp Vault (multi-environment)​

# Store certificate in Vault
vault kv put secret/certs/wildcard \
cert=@/etc/letsencrypt/live/domain.com/fullchain.pem \
key=@/etc/letsencrypt/live/domain.com/privkey.pem

# Each server fetches from Vault
vault kv get -field=cert secret/certs/wildcard > /etc/ssl/cert.pem

3. Kubernetes cert-manager​

For Kubernetes, cert-manager is the standard solution - it issues certificates directly in the cluster:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: [email protected]
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: cloudflare-api-token
key: api-token

4. Centralized TLS termination​

The simplest approach for multiple servers: centralize TLS at the load balancer.

Backend servers don't need the certificate - internal communication can be HTTP (in private network) or mTLS.

Supported DNS providers​

Certbot and acme.sh support various providers:

  • Popular: Cloudflare, AWS Route53, Google Cloud DNS, DigitalOcean
  • Registrars: GoDaddy, Namecheap, OVH, Gandi
  • Others: Azure DNS, Linode, Vultr, DNSimple

Consult the ACME client documentation for the complete list of available plugins.