Waiting for solver before continuing: Cant create a wildcard certificate

I’m not really sure what’s going on. I followed this guide:

First Created this token with Zone.DNS.Edit

Second I used this Cloudflare plugin to create a Dockerfile:

FROM caddy:builder AS builder
RUN xcaddy build \
  --with github.com/caddy-dns/cloudflare

FROM caddy:latest
COPY --from=builder /usr/bin/caddy /usr/bin/caddy

And finally set this in Caddyfile

www.example.com {
  tls {
                dns cloudflare TOKEN_HASH
        }
   respond "Hello world"
}

Debug logs:

{"level":"info","ts":1723134951.0599442,"logger":"tls.obtain","msg":"obtaining certificate","identifier":" www.example.com"}
{"level":"debug","ts":1723134951.0601518,"logger":"events","msg":"event","name":"cert_obtaining","id":"ad49c093-209f-441c-acff-9b81367a9f20","origin":"tls","data":{"identifier":" www.example.com"}}
{"level":"debug","ts":1723134951.0606673,"logger":"tls.obtain","msg":"trying issuer 1/1","issuer":"acme-v02.api.letsencrypt.org-directory"}
{"level":"info","ts":1723134951.0614405,"logger":"tls.issuance.acme","msg":"waiting on internal rate limiter","identifiers":[" www.example.com"],"ca":"https://acme-v02.api.letsencrypt.org/directory","account":""}
{"level":"info","ts":1723134951.0614672,"logger":"tls.issuance.acme","msg":"done waiting on internal rate limiter","identifiers":[" www.example.com"],"ca":"https://acme-v02.api.letsencrypt.org/directory","account":""}
{"level":"info","ts":1723134951.061483,"logger":"tls.issuance.acme","msg":"using ACME account","account_id":"https://acme-v02.api.letsencrypt.org/acme/acct/1875290417","account_contact":[]}
{"level":"debug","ts":1723134951.5227635,"logger":"tls.issuance.acme.acme_client","msg":"http request","method":"GET","url":"https://acme-v02.api.letsencrypt.org/directory","headers":{"User-Agent":["Caddy/2.8.4 CertMagic acmez (linux; amd64)"]},"response_headers":{"Cache-Control":["public, max-age=0, no-cache"],"Content-Length":["746"],"Content-Type":["application/json"],"Date":["Thu, 08 Aug 2024 16:35:51 GMT"],"Server":["nginx"],"Strict-Transport-Security":["max-age=604800"],"X-Frame-Options":["DENY"]},"status_code":200}
{"level":"debug","ts":1723134951.523017,"logger":"tls.issuance.acme.acme_client","msg":"creating order","account":"https://acme-v02.api.letsencrypt.org/acme/acct/1875290417","identifiers":[" www.example.com"]}
{"level":"debug","ts":1723134951.6764255,"logger":"tls.issuance.acme.acme_client","msg":"http request","method":"HEAD","url":"https://acme-v02.api.letsencrypt.org/acme/new-nonce","headers":{"User-Agent":["Caddy/2.8.4 CertMagic acmez (linux; amd64)"]},"response_headers":{"Cache-Control":["public, max-age=0, no-cache"],"Date":["Thu, 08 Aug 2024 16:35:51 GMT"],"Link":["<https://acme-v02.api.letsencrypt.org/directory>;rel=\"index\""],"Replay-Nonce":["cgBcsAuLOj4gvW--rJyh3_4oxPK-ad-ZBJoLOFAsds2sdyKTM3k"],"Server":["nginx"],"Strict-Transport-Security":["max-age=604800"],"X-Frame-Options":["DENY"]},"status_code":200}
{"level":"debug","ts":1723134951.9200969,"logger":"tls.issuance.acme.acme_client","msg":"http request","method":"POST","url":"https://acme-v02.api.letsencrypt.org/acme/new-order","headers":{"Content-Type":["application/jose+json"],"User-Agent":["Caddy/2.8.4 CertMagic acmez (linux; amd64)"]},"response_headers":{"Boulder-Requester":["1875290417"],"Cache-Control":["public, max-age=0, no-cache"],"Content-Length":["346"],"Content-Type":["application/json"],"Date":["Thu, 08 Aug 2024 16:35:51 GMT"],"Link":["<https://acme-v02.api.letsencrypt.org/directory>;rel=\"index\""],"Location":["https://acme-v02.api.letsencrypt.org/acme/order/1875290417/3243141234123"],"Replay-Nonce":["..."],"Server":["nginx"],"Strict-Transport-Security":["max-age=604800"],"X-Frame-Options":["DENY"]},"status_code":201}
{"level":"debug","ts":1723134952.0787663,"logger":"tls.issuance.acme.acme_client","msg":"http request","method":"POST","url":"https://acme-v02.api.letsencrypt.org/acme/authz-v3/387725450456","headers":{"Content-Type":["application/jose+json"],"User-Agent":["Caddy/2.8.4 CertMagic acmez (linux; amd64)"]},"response_headers":{"Boulder-Requester":["1875290417"],"Cache-Control":["public, max-age=0, no-cache"],"Content-Length":["804"],"Content-Type":["application/json"],"Date":["Thu, 08 Aug 2024 16:35:52 GMT"],"Link":["<https://acme-v02.api.letsencrypt.org/directory>;rel=\"index\""],"Replay-Nonce":["cgBcsAuLaCxEE75upD4PPUIE0UJM7B16hXtLgXT6EgdEHNmsFks"],"Server":["nginx"],"Strict-Transport-Security":["max-age=604800"],"X-Frame-Options":["DENY"]},"status_code":200}
{"level":"debug","ts":1723134952.0789962,"logger":"tls.issuance.acme.acme_client","msg":"no solver configured","challenge_type":"tls-alpn-01"}
{"level":"debug","ts":1723134952.0790045,"logger":"tls.issuance.acme.acme_client","msg":"no solver configured","challenge_type":"http-01"}
{"level":"info","ts":1723134952.0790095,"logger":"tls.issuance.acme.acme_client","msg":"trying to solve challenge","identifier":" www.example.com","challenge_type":"dns-01","ca":"https://acme-v02.api.letsencrypt.org/directory"}
{"level":"debug","ts":1723134953.5648632,"logger":"tls.issuance.acme.acme_client","msg":"waiting for solver before continuing","identifier":" www.example.com","challenge_type":"dns-01"}
{"level":"debug","ts":1723134963.2078462,"logger":"tls.handshake","msg":"no matching certificates and no custom selection logic","identifier":"*.com"}
{"level":"debug","ts":1723134963.207852,"logger":"tls.handshake","msg":"no matching certificates and no custom selection logic","identifier":"*.*"}

I’ve switched to

example.com, www.example.com {
...
}

I’m not planning to use example.com but just to check what happens becuase I read in another post that someone was able to activate the wildcard with something like this

Here are the new logs

{"level":"info","ts":1723154406.7206,"msg":"using config from file","file":"/etc/caddy/Caddyfile"}
{"level":"info","ts":1723154406.7268448,"msg":"adapted config to JSON","adapter":"caddyfile"}
{"level":"warn","ts":1723154406.726967,"msg":"Caddyfile input is not formatted; run 'caddy fmt --overwrite' to fix inconsistencies","adapter":"caddyfile","file":"/etc/caddy/Caddyfile","line":2}
{"level":"info","ts":1723154406.7307386,"logger":"admin","msg":"admin endpoint started","address":"localhost:2019","enforce_origin":false,"origins":["//localhost:2019","//[::1]:2019","//127.0.0.1:2019"]}
{"level":"info","ts":1723154406.731412,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc000680f80"}
{"level":"info","ts":1723154406.7315674,"logger":"http.auto_https","msg":"server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS","server_name":"srv0","https_port":443}
{"level":"info","ts":1723154406.731672,"logger":"http.auto_https","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
{"level":"info","ts":1723154406.739218,"logger":"http","msg":"enabling HTTP/3 listener","addr":":443"}
{"level":"info","ts":1723154406.744439,"msg":"failed to sufficiently increase receive buffer size (was: 208 kiB, wanted: 7168 kiB, got: 416 kiB). See https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes for details."}
{"level":"info","ts":1723154406.7466772,"logger":"http.log","msg":"server running","name":"srv0","protocols":["h1","h2","h3"]}
{"level":"info","ts":1723154406.7472432,"logger":"http.log","msg":"server running","name":"remaining_auto_https_redirects","protocols":["h1","h2","h3"]}
{"level":"info","ts":1723154406.747387,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["www.example.com","example.com"]}
{"level":"info","ts":1723154406.748283,"logger":"tls.obtain","msg":"acquiring lock","identifier":"www.example.com"}
{"level":"info","ts":1723154406.7719047,"msg":"autosaved config (load with --resume flag)","file":"/config/caddy/autosave.json"}
{"level":"info","ts":1723154406.772089,"msg":"serving initial configuration"}
{"level":"info","ts":1723154406.7731857,"logger":"tls","msg":"storage cleaning happened too recently; skipping for now","storage":"FileStorage:/data/caddy","instance":"d416e8ac-2130-4fa6-9a82-09de519950fc","try_again":1723240806.773182,"try_again_in":86399.999999151}
{"level":"info","ts":1723154406.7742338,"logger":"tls.obtain","msg":"lock acquired","identifier":"www.example.com"}
{"level":"info","ts":1723154406.7744253,"logger":"tls.obtain","msg":"obtaining certificate","identifier":"www.example.com"}
{"level":"info","ts":1723154406.7758377,"logger":"tls","msg":"finished cleaning storage units"}
{"level":"info","ts":1723154406.7778163,"logger":"tls.issuance.acme","msg":"waiting on internal rate limiter","identifiers":["www.example.com"],"ca":"https://acme-v02.api.letsencrypt.org/directory","account":""}
{"level":"info","ts":1723154406.7779412,"logger":"tls.issuance.acme","msg":"done waiting on internal rate limiter","identifiers":["www.example.com"],"ca":"https://acme-v02.api.letsencrypt.org/directory","account":""}
{"level":"info","ts":1723154406.778088,"logger":"tls.issuance.acme","msg":"using ACME account","account_id":"https://acme-v02.api.letsencrypt.org/acme/acct/1875290417","account_contact":[]}
{"level":"info","ts":1723154407.7503505,"logger":"tls.issuance.acme.acme_client","msg":"trying to solve challenge","identifier":"www.example.com","challenge_type":"dns-01","ca":"https://acme-v02.api.letsencrypt.org/directory"}

The only big difference is that now the TXT DNS is created in Cloudflare. Also a single domain certificate for example.com is also created, but not the wildcard for www.

I’m worried because I’ve been re-issuing too much the single certificate for example.com many times, so probably it wont have many opportunities left :frowning:

I’ve also tried with

*.example.com {
...
} 

And the logs are exactly the same as the above (with the *.example.com

Does it have Zone.Zone:Read as well? (See: GitHub - caddy-dns/cloudflare: Caddy module: dns.providers.cloudflare)

I would recommend manually swapping to the LetsEncrypt staging endpoint while you’re testing this deployment.

You won’t get trusted certificates from the staging endpoint, but the rate limits are greatly relaxed there and you can test away until you get a good result before swapping back to the production endpoint for real certs.

I believe Caddy can do this automatically if it detects a certain amount of failures but it’s best to be nice to the ACME server here and avoid the risk of a rate limit for yourself in the process.

3 Likes

Thanks for the test part, yesterday I was checking the docs pages but I could only find the json part.

About the Read part, it seems that it was the problem. I was reading some docs and only mentioned the Edit part and for some reason I wrongly assumed that Edit had Read implicit.

Now I can see there is a new directory like wildcard_.example.com

But I wonder why example.com now throwing a certificate error. I thought that wildcard certificates from letsencrypt included the naked domain.

Maybe its required to do

example.com, *.example.com {
...
}

To get both a single certificate with both naked and wildcard at the same time?

Technically, a wildcard for *.example.com will not cover example.com because the number of elements matter. The former has 3 elements: com, example, and any one extra. The latter only has two elements.

Some wildcard providers will issue a certificate with both *.example.com and example.com on the same certificate.

Caddy specifically avoids this as you are generally better served having separate certificates in general. The philosophy behind Caddy is strongly opinionated that instead of consolidating certificates into one in order to reduce the maintenance burden, you should instead automate the certificate maintenance until there is no difference between keeping one certificate or a hundred (or a few hundred thousand).

My understanding is that even if you throw both addresses on the same site block, Caddy would simply requisition a wildcard and a regular certificate.

3 Likes

Ok, it makes sense. Maybe I would add a little reference to this in this section

The fact that *.example.com doesn’t apply to example.com is not something specific to Caddy, that’s just how web PKI works.

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.