SSL & Certs Intermediate

Troubleshooting Certbot DNS-01 Challenge TXT Records Mismatch on Ubuntu 22.04 LTS

Resolve Certbot DNS-01 challenge failures due to TXT record mismatches. Diagnose and fix propagation, incorrect records, and timing issues for successful SSL issuance.

👨‍💻
Senior Systems Architect • Verified in Staging Labs

Resolve Certbot DNS-01 challenge failures due to TXT record mismatches. Diagnose and fix propagation, incorrect records, and timing issues for successful SSL issuance.

When attempting to obtain or renew an SSL certificate from Let's Encrypt using Certbot with the DNS-01 challenge method, you might encounter an error indicating a mismatch in the _acme-challenge TXT record. This typically prevents Certbot from verifying domain ownership, leading to a failed certificate issuance or renewal. This guide provides a highly technical, step-by-step approach to diagnose and resolve this common issue on Ubuntu 22.04 LTS systems.

Symptom & Error Signature

The primary symptom is Certbot failing to complete the certificate challenge, presenting an error message in the terminal and its logs. You'll usually see output similar to this:

Saving debug log to /var/log/letsencrypt/letsencrypt.log

An unexpected error occurred:
The following errors were reported by the ACME server:

Domain: example.com
Type: unauthorized
Detail: Incorrect TXT record "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" found at _acme-challenge.example.com. Expected "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"

To fix this, make sure that your domain's DNS provider has the correct TXT record set for _acme-challenge.example.com.

The error clearly indicates that the ACME server (Let's Encrypt) found a TXT record for _acme-challenge.example.com that did not match the value it expected. The letsencrypt.log file (/var/log/letsencrypt/letsencrypt.log) will contain more detailed information, including potential stack traces or specific API responses from your DNS provider if using an automated plugin.

Root Cause Analysis

The "TXT records mismatch" error stems from the ACME server's inability to retrieve the exact _acme-challenge TXT record it expects within its verification window. Several underlying factors can contribute to this:

  1. DNS Propagation Delays: This is the most frequent culprit. After you (or a Certbot DNS plugin) add or update a TXT record, it takes time for these changes to propagate across the global DNS infrastructure. Let's Encrypt's validation servers might query your domain's authoritative DNS servers before the new record has fully propagated to all regions.
  2. Incorrect TXT Record Value: A simple typo, an extra space, or an incorrect copy-paste operation when manually entering the TXT record can lead to a mismatch. The value must be an exact, byte-for-byte match to what Certbot provides.
  3. Stale or Duplicate TXT Records: If there are multiple _acme-challenge TXT records for the same domain (e.g., from previous failed attempts or other services), Certbot's validation process might pick up an outdated or incorrect one, causing the mismatch.
  4. Wrong DNS Zone or Subdomain: The TXT record might have been inadvertently added to the wrong DNS zone (e.g., example.com instead of sub.example.com for a sub.example.com certificate request) or a sub-domain when it should be at the apex, or vice-versa.
  5. Certbot Timing Issues (Automated DNS Plugins): For Certbot DNS plugins (e.g., certbot-dns-cloudflare, certbot-dns-route53), the plugin might attempt to verify the record too quickly after adding it, before sufficient propagation time has elapsed.
  6. DNS Caching: Local DNS resolvers (on your server or your ISP's network) might cache older records, making it seem like the new record hasn't propagated even if it has on authoritative servers.
  7. DNS Provider API Issues: Less common, but temporary outages, rate limits, or incorrect API credentials/permissions with your DNS provider can prevent automated plugins from setting or verifying records correctly.

Step-by-Step Resolution

Follow these steps to systematically diagnose and resolve the Certbot DNS-01 challenge TXT record mismatch.

1. Verify DNS Propagation and TXT Record Content Manually

The first step is to independently verify what _acme-challenge TXT records are actually visible for your domain.

  1. Identify the Expected TXT Value: Look at the Certbot error output for the "Expected" value. If it's not clear, run Certbot with --dry-run (see Step 6) to obtain the value without making actual changes.

  2. Query DNS Using dig: Use the dig utility on your Ubuntu server to query for the TXT record.

    # Replace example.com with your actual domain
    dig -t TXT _acme-challenge.example.com +short
    

    The output should show the TXT record(s) currently published. Compare this exactly with the value Certbot expects. If you see multiple records, or an incorrect one, this is a strong indicator of the problem.

  3. Use Online DNS Checkers: Leverage public online tools like whatsmydns.net or dnschecker.org. Enter _acme-challenge.example.com (or _acme-challenge.sub.example.com for a subdomain) and select TXT record type. This provides a global perspective on propagation.

    Ensure the exact expected value from Certbot matches the propagated value. Case sensitivity, quotation marks, and any trailing spaces matter. A single character difference will cause failure.

2. Remove Stale or Duplicate _acme-challenge TXT Records

Multiple _acme-challenge TXT records can confuse the ACME server or Certbot's validation.

  1. Access Your DNS Provider: Log in to your domain's DNS management interface (e.g., Cloudflare, Route 53, Namecheap, GoDaddy).

  2. Locate TXT Records: Navigate to the DNS records section for your domain.

  3. Identify and Delete: Look for any TXT records with the name _acme-challenge.example.com (or _acme-challenge if your provider automatically appends the domain). Delete all existing _acme-challenge TXT records that do not match the currently expected value from Certbot, or any old/stale ones. Ideally, there should only be one _acme-challenge record at a time for the challenge.

    Deleting legitimate TXT records used by other services (e.g., SPF, DKIM, DMARC for email authentication, or other service verification records) can cause service disruptions. Always double-check the record name and value before deletion.

3. Adjust Certbot's Propagation Delay (for DNS Plugins)

If you are using a Certbot DNS plugin (e.g., --dns-cloudflare, --dns-route53), the default propagation delay might not be sufficient for your DNS provider or network conditions.

  1. Identify Plugin Options: Check the documentation for your specific Certbot DNS plugin. Most support a --dns-PLUGIN-propagation-seconds flag.

  2. Increase Delay: Rerun Certbot with an increased propagation delay. Start with 60 seconds, and increase to 120 or even 180 if needed.

    # Example for Cloudflare plugin, increase to 60 seconds
    sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials /path/to/cloudflare.ini 
      -d example.com -d www.example.com --dns-cloudflare-propagation-seconds 60
    

4. Confirm DNS Provider API Credentials and Permissions (for DNS Plugins)

Incorrect or expired API credentials, or insufficient permissions for the API token, will prevent Certbot's DNS plugin from successfully adding or updating the TXT record.

  1. Locate Credentials File: The path to your credentials file is usually specified with --dns-PLUGIN-credentials. For Cloudflare, it might be /etc/letsencrypt/cloudflare.ini.

  2. Verify Contents: Open the file and ensure the API token/key and email (if applicable) are correct and up-to-date.

    # Example: /etc/letsencrypt/cloudflare.ini
    dns_cloudflare_email = [email protected]
    dns_cloudflare_api_key = YOUR_CLOUDFLARE_GLOBAL_API_KEY_OR_TOKEN
    
  3. Check API Permissions: Log in to your DNS provider's console and verify that the API token/key used by Certbot has the necessary permissions to manage (read, write, delete) TXT records for the specific domain zone.

    Always use restricted API tokens with the minimum necessary permissions instead of global API keys, especially in production environments, to minimize security risks.

5. Use Certbot's --dry-run and Manual Steps for Diagnosis

For intricate issues or non-plugin users, performing a manual challenge with a dry run provides granular control and diagnostic opportunities.

  1. Perform a Dry Run: This command will simulate the challenge without actually contacting Let's Encrypt for a real certificate. Certbot will pause and instruct you to add the TXT record.

    sudo certbot certonly --manual --preferred-challenges dns -d example.com -d www.example.com --dry-run
    
  2. Add TXT Record: When Certbot prompts you, it will display the TXT record name (_acme-challenge.example.com) and the value to add. Manually add this record to your DNS provider's control panel.

  3. Verify Propagation: Before pressing Enter to continue the certbot --dry-run command, use dig (as in Step 1) or an online DNS checker to confirm the record has propagated. This isolates propagation issues from Certbot's process.

  4. Complete Dry Run (Optional): Once propagated, press Enter in the Certbot prompt to let it attempt verification. If it succeeds, your manual process and record are correct.

  5. Run for Real: If the dry run was successful and you've removed all stale records, run the command again without --dry-run.

    sudo certbot certonly --manual --preferred-challenges dns -d example.com -d www.example.com
    

    Follow the prompts, manually add the TXT record, and wait for propagation before confirming.

6. Review System Logs for Deeper Insights

Certbot's debug log is your best friend for detailed diagnostics.

  1. Tail the Log: While running Certbot, open another terminal and tail the log file.

    sudo tail -f /var/log/letsencrypt/letsencrypt.log
    
  2. Analyze Output: Look for specific error messages, HTTP response codes from DNS provider APIs, or any warnings that might indicate the root cause beyond the generic mismatch error.

7. Retrying Certbot

After implementing the solutions above and verifying that the _acme-challenge TXT record is correctly propagated, retry Certbot.

  1. For Renewals:

    sudo certbot renew --force-renewal
    
  2. For New Certificates (or specific authenticators):

    # Example using Nginx authenticator/installer with DNS-01 for certain domains, or if you had a previous issue
    sudo certbot --nginx -d example.com -d www.example.com
    

By systematically working through these steps, you should be able to identify and resolve the Certbot DNS-01 challenge TXT records mismatch, successfully obtaining or renewing your Let's Encrypt SSL certificate on Ubuntu 22.04 LTS.

👨‍💻

Johnathon Wheeler

Senior Systems Architect & DevOps Engineer • Austin, TX

Connect on LinkedIn

Johnathon has over 16 years of hands-on experience designing, debugging, and scaling Linux web hosting stacks, container clusters, and high-availability database architectures. Every guide on ButItWorkedLocal is independently tested against Debian 12, Ubuntu 24.04/22.04 LTS, Rocky Linux, and Docker environments to guarantee reproducibility in production.

🛡️

Our Production Verification Guarantee

Encountering a bug not covered here or running a non-standard kernel configuration? Our solutions are continually refined against real production incidents. Submit an environment trace for our editorial team to replicate.