Certbot DNS-01 Challenge Failure: Troubleshooting TXT Records Mismatch
Resolve 'Certbot DNS-01 challenge verification failed TXT records mismatch' errors. This guide details root causes and step-by-step fixes for failed Let's Encrypt SSL certificate renewals and issuances.
When issuing or renewing Let’s Encrypt SSL certificates using Certbot’s DNS-01 challenge method, encountering a “TXT records mismatch” error can be a frustrating roadblock. This issue prevents Certbot from verifying domain ownership, leading to failed certificate operations and potentially expired SSL certificates, causing browser warnings for your users. This guide provides a deep dive into the underlying causes and offers a structured, step-by-step resolution process for experienced system administrators and DevOps engineers.
Symptom & Error Signature
You will typically observe this error in your terminal output when attempting to run certbot certonly, certbot renew, or similar commands, especially when using a DNS plugin (e.g., certbot-dns-cloudflare, certbot-dns-route53). The output will indicate that the challenge could not be verified because the expected TXT record value does not match what Certbot found, or no record was found at all.
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator dns-cloudflare, Installer nginx
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not due for renewal, but simulating renewal for dry run
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Renewing an existing certificate for example.com and www.example.com
Performing the following challenges:
dns-01 challenge for example.com
dns-01 challenge for www.example.com
Waiting for verification...
Challenge failed for domain example.com
Challenge failed for domain www.example.com
dns-01 challenge for example.com failed
dns-01 challenge for www.example.com failed
Cleaning up challenges
Failed to renew certificate example.com with error: Some challenges have failed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
IMPORTANT NOTES:
- The following errors were reported by the server:
Domain: example.com
Type: dns
Detail: DNS problem: NXDOMAIN looking up TXT for _acme-challenge.example.com -
DNS problem: SERVFAIL looking up TXT for _acme-challenge.example.com -
DNS problem: REFUSED looking up TXT for _acme-challenge.example.com -
DNS problem: query timed out looking up TXT for _acme-challenge.example.com -
DNS problem: CNAME record found for _acme-challenge.example.com
DNS problem: The key authorization was not found or has an incorrect value.
Expected: "SOME_EXPECTED_CHALLENGE_STRING_FROM_LE"
Got: "SOME_INCORRECT_OR_OLD_CHALLENGE_STRING" (order 1 of 1)
(Caused by: [('timed out',), ('NXDOMAIN',), ('SERVFAIL',), ('REFUSED',), ('CNAME',)])
Domain: www.example.com
Type: dns
Detail: The TXT record "_acme-challenge.www.example.com" does not match the
expected value. Expected: "ANOTHER_EXPECTED_CHALLENGE_STRING_FROM_LE".
Got: "ANOTHER_INCORRECT_OR_OLD_CHALLENGE_STRING"
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Root Cause Analysis
The DNS-01 challenge relies on Certbot instructing you (or its DNS plugin) to create a specific TXT record containing a unique challenge token at _acme-challenge.yourdomain.com. Let’s Encrypt’s servers then query the DNS for this record. If the record is found and its value matches the expected token, domain ownership is verified, and the certificate is issued or renewed.
A “TXT records mismatch” error indicates that Let’s Encrypt could not find the correct TXT record at the expected DNS name (_acme-challenge.yourdomain.com). This can stem from several underlying issues:
- DNS Propagation Delays: This is the most common cause. Changes made to DNS records, especially new ones, take time to propagate across the global DNS infrastructure. If Certbot verifies too quickly, Let’s Encrypt’s resolvers may query a DNS server that hasn’t yet updated.
- Incorrect TXT Record Value:
- Typos or extra characters: Simple human error when manually entering the value, or an issue with the DNS plugin.
- Leading/Trailing Spaces: Many DNS providers will silently strip these, but some may not, causing a mismatch.
- Incorrect Encoding: Rare, but possible with certain systems.
- Old Record Present: If a previous challenge failed, an old
_acme-challengeTXT record might still exist, causing a conflict with the new one.
- Incorrect TXT Record Name:
- Missing
_acme-challengeprefix: The record must be specifically_acme-challenge.yourdomain.com(or_acme-challenge.subdomain.yourdomain.com). - Wrong Subdomain: If renewing for
www.example.com, the challenge record must be_acme-challenge.www.example.com, not_acme-challenge.example.com. - Provider-Specific Naming: Some DNS providers might have slightly different conventions (e.g., only expecting
_acme-challengein the “Name” field, and appending the domain automatically).
- Missing
- Multiple Competing TXT Records: If you have more than one TXT record for
_acme-challenge.yourdomain.com, Let’s Encrypt might pick an incorrect one, or your DNS provider might handle multiple records differently. - DNS Provider API Issues (for plugin users):
- API Key/Secret Permissions: The credentials provided to Certbot’s DNS plugin might lack the necessary permissions to create, update, or delete TXT records.
- API Rate Limits: The DNS provider might be temporarily throttling API requests.
- Transient Provider Errors: Temporary outages or service degradation at the DNS provider.
- Caching: Your local DNS resolver cache, or your ISP’s recursive DNS cache, might be serving stale information.
- CNAME Interference: If
_acme-challenge.yourdomain.comis itself a CNAME record pointing to another domain, the TXT record needs to be on the target of the CNAME, not directly on_acme-challenge.yourdomain.com.
Step-by-Step Resolution
Follow these steps meticulously to diagnose and resolve the Certbot DNS-01 challenge failure.
1. Verify the TXT Record Manually
The first step is always to verify the actual state of your DNS records using independent tools.
-
Identify the expected challenge string: Rerun Certbot with
--dry-runand--debug-challenges(if available and not using a plugin that cleans up immediately) or observe the error message carefully. The error message usually tells you theExpected: "..."value.sudo certbot renew --dry-run -vvv # Or for a new cert: sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials ~/.secrets/cloudflare.ini -d example.com -d www.example.com --dry-run -vvvLook for lines like
_acme-challenge.example.com TXT "..."which might indicate what Certbot is trying to set. If you’re using a DNS plugin, Certbot will usually try to set it and then fail. The error message itself is often the best source for the expected value. -
Construct the full TXT record name: For
example.com, it’s_acme-challenge.example.com. Forwww.example.com, it’s_acme-challenge.www.example.com. -
Query DNS using
digornslookup:# For Linux/macOS dig TXT _acme-challenge.example.com +short # For Windows nslookup -type=TXT _acme-challenge.example.com[!TIP] Querying from different DNS resolvers (e.g., Google’s
8.8.8.8or Cloudflare’s1.1.1.1) can help confirm global propagation.dig TXT _acme-challenge.example.com @8.8.8.8 -
Compare “Got” vs. “Expected”:
- If
digreturns an empty result, the record might not exist or hasn’t propagated. - If
digreturns a value, compare it exactly to the “Expected” value from Certbot’s error output. Pay close attention to case sensitivity (though TXT record values are usually case-sensitive, domain names are not), leading/trailing spaces, and any special characters.
- If
2. Account for DNS Propagation Delays
DNS changes take time. The TTL (Time To Live) of your DNS records dictates how long recursive DNS servers should cache a record. Even if you set a very low TTL (e.g., 60-300 seconds), it can still take a few minutes up to an hour for changes to fully propagate worldwide, especially if older TTL values were high.
- Wait: After creating or modifying the TXT record at your DNS provider, wait for at least 5-15 minutes, or even longer if your domain previously had a high TTL.
- Retry Certbot: After waiting, attempt the Certbot command again.
sudo certbot renew # Or, if it's a new certificate issuance sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials ~/.secrets/cloudflare.ini -d example.com -d www.example.com - Automated Delay (for scripting): If you’re scripting Certbot calls with a DNS provider’s API, ensure your script includes a sufficient
sleepinterval after creating the record before triggering Certbot’s verification. Many Certbot DNS plugins handle this automatically, but custom scripts might not.
3. Inspect DNS Provider Configuration
Thoroughly review your DNS provider’s interface for the specific domain.
-
Record Name Accuracy: Ensure the “Name” or “Host” field for the TXT record is exactly
_acme-challenge(or_acme-challenge.subdomainif applicable). Most providers will automatically append your domain name.[!IMPORTANT] Do NOT enter
_acme-challenge.yourdomain.comin the “Name” field unless your DNS provider specifically instructs you to. Typically, you only enter the subdomain part,_acme-challenge. -
Record Value Accuracy: Double-check the value.
- No leading or trailing spaces.
- Exact match, including case.
- Ensure it’s the current expected value, not an old one.
-
One TXT Record Only: Verify that there is only one TXT record for
_acme-challenge.example.com. If multiple exist, delete the outdated or incorrect ones. -
Check for Other Services: Some services (e.g., Mailgun, SPF records) might also use TXT records. Ensure there’s no conflict, although
_acme-challengeis generally unique to Let’s Encrypt. -
DNS Provider API Credentials (if using plugins):
- Location: Ensure your API credentials file (e.g.,
~/.secrets/cloudflare.ini,/etc/letsencrypt/secrets/route53.ini) is correctly configured and has the correct permissions. - Permissions: Verify that the API key/token has the necessary permissions to modify TXT records for the specific domain. For example, Cloudflare API tokens need “Zone DNS:Edit” permission.
- Environment Variables: If credentials are passed via environment variables, ensure they are correctly set in the shell where Certbot runs.
# Example: ~/.secrets/cloudflare.ini dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKENsudo chown root:root ~/.secrets/cloudflare.ini sudo chmod 600 ~/.secrets/cloudflare.ini - Location: Ensure your API credentials file (e.g.,
4. Clear Local DNS Cache
If you’re repeatedly querying DNS and seeing old values, your local system’s DNS cache might be stale.
- Flush
systemd-resolvedcache (Ubuntu/Debian):sudo systemd-resolve --flush-caches sudo systemctl restart systemd-resolved - Flush
nscdcache (older systems or specific setups):sudo systemctl restart nscd - Flush browser DNS cache: If observing issues in a browser, clear its DNS cache.
5. Debug Certbot DNS Plugins
If you’re using a Certbot DNS plugin, enable verbose logging for more detailed insights.
-
Run with Verbosity: Add
-vvvto your Certbot command. This provides extensive debugging output.sudo certbot renew --dry-run -vvvExamine the logs in
/var/log/letsencrypt/letsencrypt.logfor specific API calls, responses from the DNS provider, and any errors reported by the plugin itself before the challenge verification step. -
Plugin-Specific Issues: Check the documentation for your specific Certbot DNS plugin. Some plugins might have unique configuration requirements or known issues.
6. Troubleshoot CNAME Interference
If dig TXT _acme-challenge.example.com returns a CNAME record instead of a TXT record, this is a problem.
- Identify CNAME:
If it points todig CNAME _acme-challenge.example.com +shortsome.other.domain.com, then the TXT record for the ACME challenge must be placed at_acme-challenge.some.other.domain.com, not_acme-challenge.example.com. - Remove or Correct CNAME: If the CNAME is unintentional or incorrect, remove it. If it’s intentional (e.g., for delegated ACME challenges), ensure the target domain properly hosts the TXT record.
7. Retrying Certbot
After making changes and allowing for propagation, retry Certbot.
-
Standard Renewal/Issuance:
sudo certbot renew --cert-name example.com # Or for a new cert sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials ~/.secrets/cloudflare.ini -d example.com -d www.example.com -
Forcing Renewal (if needed): If Certbot thinks the certificate is not yet due for renewal but you’ve fixed an underlying issue, you might use
--force-renewal. Use this sparingly.sudo certbot renew --force-renewal -
Cleanup Previous Challenges: In rare cases, if old challenge files or records are causing persistent issues, you might need to clean up.
- Manually delete old TXT records from your DNS provider.
- Certbot’s DNS plugins are designed to clean up, but if a process was interrupted, manual cleanup might be required.
[!WARNING] Be cautious with
certbot delete. It will remove the entire certificate and its configuration, requiring a full re-issue. Only use this if you are absolutely sure you want to start fresh and have backups of your Nginx/Apache configuration if Certbot modified it.
By systematically working through these troubleshooting steps, you should be able to identify and resolve the “Certbot DNS-01 challenge verification failed TXT records mismatch” error and successfully secure your domains with Let’s Encrypt SSL certificates.
