new acme ssl system insufficient for handling domain name changes

Thank you, I don't have that config specified so it is still the default. I do understand that this case is a bit strange ;)

However: if my nameservers were used and someone removed the 'pop/smtp' DNS entry. With "preferer wildcard" turned off. What would happen then? I tried doing this with a test domain, and this is what I see after removing the DNS entries and removing the existing certificate:

1789638208407.png

And when clicking "provision now" I indeed see that is it trying "pop/smtp". But (as expected) that fails.

2026-09-17T11:44:13.562399396+02:00 ERROR Error error="renew certificate: could not obtain the certificate for \"beefyvm.com\": resolver: one or more domains had a problem: [pop.beefyvm.com: invalid authorization: acme: error: 400 :: urn:ietf:params:acme:error:dns :: DNS problem: NXDOMAIN looking up A for pop.beefyvm.com - check that a DNS record exists for this domain; DNS problem: NXDOMAIN looking up AAAA for pop.beefyvm.com - check that a DNS record exists for this domain] [smtp.beefyvm.com: invalid authorization: acme: error: 400 :: urn:ietf:params:acme:error:dns :: DNS problem: NXDOMAIN looking up A for smtp.beefyvm.com - check that a DNS record exists for this domain; DNS problem: NXDOMAIN looking up AAAA for smtp.beefyvm.com - check that a DNS record exists for this domain]"

So: let's say an end user has this case he can only get a cerficicate if he:
- goes for DNS validation
- re-adds pop/smtp
- asks me the server admin to remove pop/smtp from the letsencypt_list

That seems a bit strange right? Or is it possible to set the letsencypt_list to nothing? Does that allow the user to pick?
 
The new ACME system performs the HTTP challenge test for each subdomain before it runs the lego tool.

I think the local dns resolver still have the records pop subdomain in the cache. So local http test was successful, however the LE servers rejected it. If you retry the same test after a while or clear DNS resolver cache th DA will stop trying issuing certificate for the non functional subdomain.
 
TTL is set to 3600 it has been 2 hours and 15 minutes.

A `dig` from the DA machine informs me that the `pop` record does not exist. However I still see the same when requesting a certificate. Turning ACME off and on again also does not help.

Does it have a separate cache or something?

---

And may I suggest re-adding some feature to pick yourself. This is very hard to explain to a customer if he wants to to some maintenance (e.g. remove unused DNS entries) and must wait till some cache is expired before requesting a SSL certificate.
 
Last edited:
There is no additional caching inside DA.

What DA does under the hood is something similar to create /var/www/html/.well-known/{rand-name} file and the make a request to curl http://sub.example.com/.well-known/acme-challenge/{rand-name}. In other words it does the same HTTP challenge test that ACME would perform but everything is executed locally (inside the server).

This means there are multiple ways you could trick this test into being successful even if the subdomain from outside the server is non-functional. For example:
  • Adding records for subdomains to /etc/hosts.
  • Using locally running bind as local recursive resolver (having nameserver 127.0.0.1 in the /etc/resolv.conf) and using external nameservers for this domain.
  • Using 3rd-party caching recursive resolver that returns stale data.
If you want to find the root cause why the certificate provisioning assumes pop.domain.com is functional, the first step would be a simple curl test from the local server. If you are unable to find the problem you can create a support ticket and we will investigate it further.

On servers without configuration problems local HTTP challenge test works just as well as external HTTP challenge test (from ACME server). In practice users never encounter the DNS caching problems. If domain never had functional subdomain record, the test fails and ACME system will not try to issue cert for it. If they were once functional, it means they already have a valid cert for it. Next time certificate needs to be renewed the non-functional subdomains are omitted.

The situation when domain was functional 5 minutes ago but now is not functional happens only when testing things out or if server have some problems and the local HTTP challenge test can not be performed reliably.
 
So, I waited a few days just to see what would happen. But no: still the same.

Your reply however is very insightful, thanks! Let's take my example domain:

Code:
root@vps:~# curl http://beefyvm.com/.well-known/acme-challenge/foobar
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
<snip>
</body></html>

Well, so far so good!

But now something that does not exists (e.g. pop)

Code:
root@vps:~# curl http://pop.beefyvm.com/.well-known/acme-challenge/foobar
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
<snip>
</body></html>

Well that is interesting! So I do get an reply (from localhost).

Now let's test the DNS (as in DA the record does not exist)

Code:
root@vps:~# dig A pop.beefyvm.com @localhost
; <<>> DiG 9.18.49-1~deb12u2-Debian <<>> A pop.beefyvm.com @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 45962
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 7fb32a290a0b247f010000006ab40f2b87e54aaf9bdde89a (good)
;; QUESTION SECTION:
;pop.beefyvm.com.               IN      A

;; AUTHORITY SECTION:
beefyvm.com.            1800    IN      SOA     ns1.xxxxxx. hostmaster.beefyvm.com. 2026091700 3600 3600 1209600 1800

;; Query time: 0 msec
;; SERVER: ::1#53(localhost) (UDP)
;; WHEN: Wed Sep 23 19:40:59 CEST 2026
;; MSG SIZE  rcvd: 140

So: the DNS record does NOT exist. Then why do I get a 404 returned? If I do the curl call from a different host I get the expected "host not found".

Nothing strange in my /etc/hosts, no localhost in my resolv.conf

Code:
root@vps:~# cat /etc/resolv.conf
nameserver ip.v4.number.1
nameserver ip.v4.number.2
nameserver ip.v6.number.3
nameserver ip.v6.number.4

root@vps:~# dig A pop.beefyvm.com @ip.v4.number.1

; <<>> DiG 9.18.49-1~deb12u2-Debian <<>> A pop.beefyvm.com @ip.v4.number.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 39176
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
; EDE: 29: (Result from negative cache for entire name)
;; QUESTION SECTION:
;pop.beefyvm.com.               IN      A

;; AUTHORITY SECTION:
beefyvm.com.            1224    IN      SOA     ns1.xxx. hostmaster.beefyvm.com. 2026091700 3600 3600 1209600 1800

;; Query time: 0 msec
;; SERVER: ip.v4.number.1#53(ip.v4.number.1) (UDP)
;; WHEN: Wed Sep 23 19:45:17 CEST 2026
;; MSG SIZE  rcvd: 160

root@vps:~# dig A pop.beefyvm.com @ip.v4.number.2

; <<>> DiG 9.18.49-1~deb12u2-Debian <<>> A pop.beefyvm.com @ip.v4.number.2
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 9346
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;pop.beefyvm.com.               IN      A

;; AUTHORITY SECTION:
beefyvm.com.            1800    IN      SOA     ns1.xxx. hostmaster.beefyvm.com. 2026091700 3600 3600 1209600 1800

;; Query time: 132 msec
;; SERVER: ip.v4.number.2#53(ip.v4.number.2) (UDP)
;; WHEN: Wed Sep 23 19:45:23 CEST 2026
;; MSG SIZE  rcvd: 112

root@vps:~# dig A pop.beefyvm.com @ip.v6.number.3

; <<>> DiG 9.18.49-1~deb12u2-Debian <<>> A pop.beefyvm.com @ip.v6.number.3
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 47547
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
; EDE: 29: (Result from negative cache for entire name)
;; QUESTION SECTION:
;pop.beefyvm.com.               IN      A

;; AUTHORITY SECTION:
beefyvm.com.            1212    IN      SOA     ns1.xxx.nl. hostmaster.beefyvm.com. 2026091700 3600 3600 1209600 1800

;; Query time: 0 msec
;; SERVER: ip.v6.number.3#53(ip.v6.number.3) (UDP)
;; WHEN: Wed Sep 23 19:45:29 CEST 2026
;; MSG SIZE  rcvd: 160

root@vps:~# dig A pop.beefyvm.com @ip.v6.number.4

; <<>> DiG 9.18.49-1~deb12u2-Debian <<>> A pop.beefyvm.com @ip.v6.number.4
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 45511
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;pop.beefyvm.com.               IN      A

;; AUTHORITY SECTION:
beefyvm.com.            1787    IN      SOA     ns1.xxx. hostmaster.beefyvm.com. 2026091700 3600 3600 1209600 1800

;; Query time: 4 msec
;; SERVER: ip.v6.number.4#53(ip.v6.number.4) (UDP)
;; WHEN: Wed Sep 23 19:45:36 CEST 2026
;; MSG SIZE  rcvd: 112

So that all checks out? I am still at a loss here. But at least it is clear that DA is not doing something strange (well: at least on the ACME page part)
 
Ah, I found something!

Code:
root@vps:~# getent hosts pop.beefyvm.com
1234:1234:1234:1234::1 pop.beefyvm.com.xxx.nl

Code:
root@vps:~# getent hosts this-should-not-even-exist
2a04:52c0:101:9ce::1 this-should-not-even-exist.xxx.nl

I guess that curl uses / falls-back to that!

I don't have a "search" in my resolv.conf so I guess it uses my hostname as default "search". My main domain has a wildcard added so that can explain why it hits. I really have no need for a wildcard there so I can just go and remove that (or add a "search ." to the resolv.conf)

Well this was a journey! I will now have to wait for a moment for DNS to propagate but I will report back if this fixes is.
 
Yes!

1790187105282.png

This is more like it :) Well that was a very interesting issue I must say. Thank you for the pointer in the right direction. I hope this also helps other people.

It might be interesting for DA to change the curl command to
Code:
LOCALDOMAIN=. curl [...]

That will make sure any "search" is not used. Although I don't know if there would be a valid case for it to actually use it.
 
  • Like
Reactions: fln
Thanks for sharing @Mattie. We have recently solved similar problem in our ticketing system. The culprit was a search clause in resolv.conf that points to a domain with wildcard CNAME record.

Internally DA does not use curl, but it uses default system resolver for name resolution, so it is affected by global system resolver configuration.
 
Back
Top