TXT record is updated but manual verification fails

manual-auth-hook is running twice because I have -d "example.com" -d "*.example.com" (just an example) but both times it runs $CERTBOT_IDENTIFIER equals example.com so the second run does the same thing as the first. Is it necessary to run twice?

Do I miss something in the process? In the manual-auth-hook I update the _acme-challenge TXT to be $CERTBOT_VALIDATION using the API from the DNS host. The script runs both times and updates the TXT record each time. I can see it worked using dig and using the DNS host API. But certificates don't get created.

Waiting for verification...
Challenge failed for domain example.com

dns-01 challenge for Identifier(typ=IdentifierType(dns), value='example.com')

Certbot failed to authenticate some domains (authenticator: manual). The Certificate Authority reported these problems:
  Identifier: example.com
  Type:   unauthorized
  Detail: No TXT record found at _acme-challenge.example.com

Hint: The Certificate Authority failed to verify the DNS TXT records created by the --manual-auth-hook. Ensure that this hook is functioning correctly and that it waits a sufficient duration of time for DNS propagation. Refer to "certbot --help manual" and the Certbot User Guide.

The hint says the hook should wait but I do wait. At the end of my script I put sleep 100 because TTL is 100 so it has enough time to propagate. Sometimes the error says there's no TXT record and sometimes it says the TXT record is wrong and it shows the earlier value.

Do I need to sleep much longer at the end of the script?

Is there an example of how to use manual certonly with wildcard DNS challenge that uses an API to update the TXT record?

Yes, once for each identifier in the cert. The example.com and *.example.com are different identifiers even though they are validated using the same name for the DNS TXT record. DNS does not allow * in the name.

Well, Let's Encrypt queries the authoritative DNS servers directly. They have to sync worldwide but LE is not affected by TTL. If TTL affects your DNS server sync process that's fine. Just wanted to be clear about TTL and LE.

There are a number of DNS providers supported by Certbot. Some directly and some as third-party packages. See the Certbot docs: User Guide — Certbot 5.7.0.dev0 documentation

There are other ACME Clients that support a wider variety of DNS provider APIs. Had you provided your actual domain name like was requested I could have given more specific advice. But, look at the lego acme client which supports a large variety of DNS provider APIs and often gets support for new features promptly.

Also, I changed the domain name in your first post to example.com assuming it was a sample.

But, the domain name you used is a valid domain owned by someone. If you actually own it I apologize. Let me know and I will revert my change. If not, please do not use other people's domain names in posts.

If it is your domain your solution is easy as its DNS provider is Cloudflare which is readily supported by Certbot's plugin. See Certbot docs link I provided in prior post.

Two basic questions:

  1. Are these requests for a public domain?
  2. Are you checking all the authoritative DNS servers for the TXT record(s) before continuing?

Does LE see changes immediately? Some DNS plugins have a wait time of minutes --dns-linode-propagation-seconds 120.

If my DNS TTL is 100 what sleep should I put at the end of manual-auth-hook?

The DNS host doesn't have a plugin for certbot or lego so I am using their API.

TTL is not relevant.
It needs to sleep longer than it takes all your authoritative name servers time to sync with each other.

Yes but for DNS validation does it make a difference if it's an internal host if the DNS host for it is public?

I tried dig TXT _acme-challenge.example.com and it shows both TXT values. Is there a DNS server I should use with dig TXT @$DNS_SERVER _acme-challenge.example.com?

Do I need to ask my DNS host provider for their authoritative name servers?

You can find that out yourself by running dig -t NS <your-domain>.

dig -t NS example.com has 2 name servers ns01.dnshost.com and ns02.dnshost.com. Are these the 2 commands to check?

dig -t TXT @ns01.dnshost.com _acme-challenge.example.com
dig -t TXT @ns02.dnshost.com _acme-challenge.example.com

Yes, assuming that there are only two physical servers i.e. they're not running an anycast or load balancing setup.

Is there a way to know if they are or should I keep increasing the sleep until it works?

The IP addresses do not appear to be in an anycast network and load balancers for DNS servers aren't typically used, so the challenge should be able to succeed as soon as the records appear.

How can I check that for any name server?

I'd lookup the nameserver and the autonomous system which they're in using https://bgp.tools and looking for the anycast tag.

Turns out your nameserver is in an anycast autonomous system so there might be some propagation delay which you can't see.

I'd start by checking the SOA records:
dig -t SOA @ns01.dnshost.com [your.domain]
dig -t SOA @ns02.dnshost.com [your.domain]

Check the SOA versions:

  • before you update
  • while it is syncing
  • after the sync

do that a few times and note about how long it takes for the sync to complete.
use that sync time plus 5, or 10, seconds for your sleep timer.

@56629 If that's the actual DNS server is your registrar Dynadot?

Because acme lego has a DNS provider for that. Maybe just use that instead of developing your own?

Or, is this another case of you using a domain name not related to you? :slight_smile:

On these commands I will wait for the TXT records to be updated to $CERTBOT_VALIDATION.

dig -t TXT @ns01.dnshost.com _acme-challenge.example.com
dig -t TXT @ns02.dnshost.com _acme-challenge.example.com

On these commands what will I see when it's ready? Do I do use example.com or _acme-challenge.example.com?

dig -t SOA @ns01.dnshost.com example.com
dig -t SOA @ns02.dnshost.com example.com

It was an example I should have used ns01.example.com.

I put ns01.dnshost.com in bgp.tools. Do I click the ASN under A or Nameservers to look for the anycast tag?

You click on the ASN under the A records header. If you were looking up your host directly, then you would use the ASNs under the nameserver header.