Caddy dns01 challenge fails

Hey.
I recently become a deSEC user and everything was fine until my wildcard cert expired that was using DNS-01 challenge using Caddy and GitHub - caddy-dns/desec: deSEC module for Caddy

Caddy logs:

Jul 14 21:49:25 core caddy[49907]: {"level":"info","ts":1752522565.387346,"logger":"tls.obtain","msg":"obtaining certificate","identifier":"*.int.albert.lol"}
Jul 14 21:49:25 core caddy[49907]: {"level":"info","ts":1752522565.388084,"logger":"tls.issuance.acme","msg":"creating new account because no account for configured email is known to us","email":"","ca":"https://acme-staging-v02.api.letsencrypt.org/directory","error":"open /var/lib/caddy/.local/share/caddy/acme/acme-staging-v02.api.letsencrypt.org-directory/users/default/default.json: no such file or directory"}
Jul 14 21:49:25 core caddy[49907]: {"level":"info","ts":1752522565.388154,"logger":"tls.issuance.acme","msg":"ACME account has empty status; registering account with ACME server","contact":[],"location":""}
Jul 14 21:49:25 core caddy[49907]: {"level":"info","ts":1752522565.3913646,"logger":"tls.issuance.acme","msg":"creating new account because no account for configured email is known to us","email":"","ca":"https://acme-staging-v02.api.letsencrypt.org/directory","error":"open /var/lib/caddy/.local/share/caddy/acme/acme-staging-v02.api.letsencrypt.org-directory/users/default/default.json: no such file or directory"}
Jul 14 21:49:26 core caddy[49907]: {"level":"info","ts":1752522566.1723778,"logger":"tls.issuance.acme","msg":"new ACME account registered","contact":[],"status":"valid"}
Jul 14 21:49:26 core caddy[49907]: {"level":"info","ts":1752522566.1772244,"logger":"tls.issuance.acme","msg":"using ACME account","account_id":"https://acme-staging-v02.api.letsencrypt.org/acme/acct/212763434","account_contact":[]}
Jul 14 21:49:26 core caddy[49907]: {"level":"info","ts":1752522566.4926553,"msg":"trying to solve challenge","identifier":"*.int.albert.lol","challenge_type":"dns-01","ca":"https://acme-staging-v02.api.letsencrypt.org/directory"}
Jul 14 21:49:26 core caddy[49907]: {"level":"error","ts":1752522566.6146266,"msg":"cleaning up solver","identifier":"*.int.albert.lol","challenge_type":"dns-01","error":"no memory of presenting a DNS record for \"_acme-challenge.int.albert.lol\" (usually OK if presenting also failed)","stacktrace":"github.com/mholt/acmez/v3.(*Client).solveChallenges.func1\n\tgithub.com/mholt/acmez/v3@v3.1.2/client.go:318\ngithub.com/mholt/acmez/v3.(*Client).solveChallenges\n\tgithub.com/mholt/acmez/v3@v3.1.2/client.go:363\ngithub.com/mholt/acmez/v3.(*Client).ObtainCertificate\n\tgithub.com/mholt/acmez/v3@v3.1.2/client.go:136\ngithub.com/caddyserver/certmagic.(*ACMEIssuer).doIssue\n\tgithub.com/caddyserver/certmagic@v0.23.0/acmeissuer.go:489\ngithub.com/caddyserver/certmagic.(*ACMEIssuer).Issue\n\tgithub.com/caddyserver/certmagic@v0.23.0/acmeissuer.go:382\ngithub.com/caddyserver/caddy/v2/modules/caddytls.(*ACMEIssuer).Issue\n\tgithub.com/caddyserver/caddy/v2@v2.10.0/modules/caddytls/acmeissuer.go:288\ngithub.com/caddyserver/certmagic.(*Config).obtainCert.func2\n\tgithub.com/caddyserver/certmagic@v0.23.0/config.go:626\ngithub.com/caddyserver/certmagic.doWithRetry\n\tgithub.com/caddyserver/certmagic@v0.23.0/async.go:104\ngithub.com/caddyserver/certmagic.(*Config).obtainCert\n\tgithub.com/caddyserver/certmagic@v0.23.0/config.go:700\ngithub.com/caddyserver/certmagic.(*Config).ObtainCertAsync\n\tgithub.com/caddyserver/certmagic@v0.23.0/config.go:505\ngithub.com/caddyserver/certmagic.(*Config).manageOne.func1\n\tgithub.com/caddyserver/certmagic@v0.23.0/config.go:415\ngithub.com/caddyserver/certmagic.(*jobManager).worker\n\tgithub.com/caddyserver/certmagic@v0.23.0/async.go:73"}
Jul 14 21:49:26 core caddy[49907]: {"level":"error","ts":1752522566.7697377,"logger":"tls.obtain","msg":"could not get certificate from issuer","identifier":"*.int.albert.lol","issuer":"acme-v02.api.letsencrypt.org-directory","error":"[*.int.albert.lol] solving challenges: presenting for challenge: adding temporary record for zone \"int.albert.lol.\": writing RRSets: unexpected status code 404: {\"detail\":\"Not found.\"} (order=https://acme-staging-v02.api.letsencrypt.org/acme/order/212763434/26048877244) (ca=https://acme-staging-v02.api.letsencrypt.org/directory)"}
Jul 14 21:49:26 core caddy[49907]: {"level":"error","ts":1752522566.7698016,"logger":"tls.obtain","msg":"will retry","error":"[*.int.albert.lol] Obtain: [*.int.albert.lol] solving challenges: presenting for challenge: adding temporary record for zone \"int.albert.lol.\": writing RRSets: unexpected status code 404: {\"detail\":\"Not found.\"} (order=https://acme-staging-v02.api.letsencrypt.org/acme/order/212763434/26048877244) (ca=https://acme-staging-v02.api.letsencrypt.org/directory)","attempt":2,"retrying_in":120,"elapsed":62.601977679,"max_duration":2592000}

Relevant caddy config:

(int) {
        tls {
                dns desec {
                        token {env.DESEC_API_TOKEN}
                }
                resolvers 192.168.1.254
                propagation_timeout 300s
                propagation_delay 120s
        }
}

What do I do?

Thanks in advance.

Looks like deSEC’s API returns 404 when Caddy is trying to create the DNS challenge record. Can you confirm the domain exists in your account?

Best,
Nils

Hey,

absolutely, the zone “albert.lol” exists.

Yet here DNS Spy report for albert.lol and here Hardenize Report: albert.lol are showing cloudflare nameservers.

According to the error message, what Caddy is trying to do is

adding temporary record for zone \"int.albert.lol.\"

… which corresponds to a request to https://desec.io/api/v1/domains/int.albert.lol/, with subname *. If the domain in your account, as you say, really is albert.lol, then the request should be made to https://desec.io/api/v1/domains/albert.lol/ instead, with a subname field of *.int.

Is there configuration to determine which name Caddy identifies as the domain/zone name, for DNS purposes?

FWIW, our API facilitates determining the proper domain name, by making a GET request to /api/v1/domains/?owns_qname=*.int.albert.lol, as documented here: Domain Management — deSEC DNS API documentation

Stay secure,
Peter

1 Like

Oh yes, that’s indeed the bigger problem! :slight_smile:

Stay secure,
Peter

1 Like

Yeah I moved it back to Cloudflare because that was working before for years, since I assumed this was an error in either deSEC’s API or the Caddy module for it, it was faster than waiting for a fix.

This is how Caddy handles it

*.int.albert.lol {
  import int

  @test host test.int.albert.lol
  handle @test {
    reverse_proxy 192.168.1.2:3000
  }

}

This with a local dns server allowed me to use internal domains with valid certs, and Caddy will try to generate a cert for what’s the block called, in this case *.int.albert.lol.

So this is probably something wrong with libdns or caddy-dns/desec module.