Caddy failing to obtain cert when using a subdomain

1. The problem I’m having:

Caddy when i use a subdomain, seems to fail while obtaining the TLS certificate, and if navigated to will throw a 502, and can not figure out if its a caddy/debian config problem or a Cloudflare problem.

however, i can use caddy just fine on another similar VM with my main domain https://vera-woof.com with all the same cloudflare tunnel, and DNS settings (except needed for the subdomain)

(output of curl -vL

* Host git.vera-woof.com:443 was resolved.
* IPv6: (none)
* IPv4: 104.21.43.171, 172.67.182.138
*   Trying 104.21.43.171:443...
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* SSL Trust Anchors:
*   CAfile: /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / X25519MLKEM768 / id-ecPublicKey
* ALPN: server accepted h2
* Server certificate:
*   subject: CN=vera-woof.com
*   start date: Jun  7 22:20:53 2026 GMT
*   expire date: Sep  5 23:17:26 2026 GMT
*   issuer: C=US; O=Google Trust Services; CN=WE1
*   Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA256
*   Certificate level 1: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA384
*   Certificate level 2: Public key type EC/secp384r1 (384/192 Bits/secBits), signed using ecdsa-with-SHA384
*   subjectAltName: "git.vera-woof.com" matches cert's "*.vera-woof.com"
* SSL certificate verified via OpenSSL.
* Established connection to git.vera-woof.com (104.21.43.171 port 443) from 192.168.8.191 port 37554 
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://git.vera-woof.com/
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: git.vera-woof.com]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.18.0]
* [HTTP/2] [1] [accept: */*]
> GET / HTTP/2
> Host: git.vera-woof.com
> User-Agent: curl/8.18.0
> Accept: */*
> 
* Request completely sent off
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
< HTTP/2 502 
< date: Mon, 20 Jul 2026 19:23:30 GMT
< content-type: text/plain; charset=UTF-8
< content-length: 16
< cache-control: private, max-age=0, no-store, no-cache, must-revalidate, post-check=0, pre-check=0
< expires: Thu, 01 Jan 1970 00:00:01 GMT
< referrer-policy: same-origin
< x-frame-options: SAMEORIGIN
< server: cloudflare
< cf-ray: a1e457385a6f2d03-ORD
< alt-svc: h3=":443"; ma=86400
< 
error code: 502
* Connection #0 to host git.vera-woof.com:443 left intact

cloudflare TLS is in Full mode but not Full (strict)

2. Error messages and/or full log output:

2026/07/20 18:48:06.512 INFO    maxprocs: Leaving GOMAXPROCS=4: CPU quota undefined
2026/07/20 18:48:06.512 INFO    GOMEMLIMIT is updated   {"GOMEMLIMIT": 7314717081, "previous": 9223372036854775807}
2026/07/20 18:48:06.512 INFO    using adjacent Caddyfile
2026/07/20 18:48:06.512 INFO    adapted config to JSON  {"adapter": "caddyfile"}
2026/07/20 18:48:06.514 INFO    admin   admin endpoint started  {"address": "localhost:2019", "enforce_origin": false, "origins": ["//localhost:2019", "//[::1]:2019", "//127.0.0.1:2019"]}
2026/07/20 18:48:06.514 INFO    http.auto_https 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}
2026/07/20 18:48:06.514 INFO    http.auto_https enabling automatic HTTP->HTTPS redirects        {"server_name": "srv0"}
2026/07/20 18:48:06.514 INFO    tls.cache.maintenance   started background certificate maintenance      {"cache": "0x28c7365c5e80"}
2026/07/20 18:48:06.515 WARN    http    HTTP/2 skipped because it requires TLS  {"network": "tcp", "addr": ":80"}
2026/07/20 18:48:06.515 WARN    http    HTTP/3 skipped because it requires TLS  {"network": "tcp", "addr": ":80"}
2026/07/20 18:48:06.515 INFO    http.log        server running  {"name": "remaining_auto_https_redirects", "protocols": ["h1", "h2", "h3"]}
2026/07/20 18:48:06.515 INFO    http    enabling HTTP/3 listener        {"addr": ":443"}
2026/07/20 18:48:06.515 INFO    http.log        server running  {"name": "srv0", "protocols": ["h1", "h2", "h3"]}
2026/07/20 18:48:06.515 INFO    http    enabling automatic TLS certificate management   {"domains": ["git.vera-woof.com"]}
2026/07/20 18:48:06.517 INFO    autosaved config (load with --resume flag)      {"file": "/root/.config/caddy/autosave.json"}
2026/07/20 18:48:06.517 INFO    serving initial configuration
2026/07/20 18:48:06.565 INFO    tls.obtain      acquiring lock  {"identifier": "git.vera-woof.com"}
2026/07/20 18:48:06.588 INFO    tls     cleaning storage unit   {"storage": "FileStorage:/root/.local/share/caddy"}
2026/07/20 18:48:06.610 INFO    tls.obtain      lock acquired   {"identifier": "git.vera-woof.com"}
2026/07/20 18:48:06.610 INFO    tls.obtain      obtaining certificate   {"identifier": "git.vera-woof.com"}
2026/07/20 18:48:06.611 INFO    http    creating new account because no account for configured email is known to us   {"email": "", "ca": "https://acme-v02.api.letsencrypt.org/directory", "error": "open /root/.local/share/caddy/acme/acme-v02.api.letsencrypt.org-directory/users/default/default.json: no such file or directory"}
2026/07/20 18:48:06.612 INFO    http    ACME account has empty status; registering account with ACME server  {"contact": [], "location": ""}
2026/07/20 18:48:06.632 INFO    tls     finished cleaning storage units
2026/07/20 18:48:06.655 INFO    http    creating new account because no account for configured email is known to us   {"email": "", "ca": "https://acme-v02.api.letsencrypt.org/directory", "error": "open /root/.local/share/caddy/acme/acme-v02.api.letsencrypt.org-directory/users/default/default.json: no such file or directory"}
2026/07/20 18:48:07.072 INFO    http    new ACME account registered     {"contact": [], "status": "valid"}
2026/07/20 18:48:07.132 INFO    http    waiting on internal rate limiter        {"identifiers": ["git.vera-woof.com"], "ca": "https://acme-v02.api.letsencrypt.org/directory", "account": ""}
2026/07/20 18:48:07.132 INFO    http    done waiting on internal rate limiter   {"identifiers": ["git.vera-woof.com"], "ca": "https://acme-v02.api.letsencrypt.org/directory", "account": ""}
2026/07/20 18:48:07.132 INFO    http    using ACME account      {"account_id": "https://acme-v02.api.letsencrypt.org/acme/acct/3552334225", "account_contact": []}
2026/07/20 18:48:07.283 INFO    http.acme_client        trying to solve challenge       {"identifier": "git.vera-woof.com", "challenge_type": "http-01", "ca": "https://acme-v02.api.letsencrypt.org/directory"}
2026/07/20 18:48:08.143 ERROR   http.acme_client        challenge failed        {"identifier": "git.vera-woof.com", "challenge_type": "http-01", "problem": {"type": "urn:ietf:params:acme:error:unauthorized", "title": "", "detail": "2606:4700:3037::ac43:b68a: Invalid response from http://git.vera-woof.com/.well-known/acme-challenge/w4Joa_GSDt2lRPBOvJhASYxoxArJRENJeWfrBI-73UM: 502", "instance": "", "subproblems": null}}
2026/07/20 18:48:08.143 ERROR   http.acme_client        validating authorization        {"identifier": "git.vera-woof.com", "problem": {"type": "urn:ietf:params:acme:error:unauthorized", "title": "", "detail": "2606:4700:3037::ac43:b68a: Invalid response from http://git.vera-woof.com/.well-known/acme-challenge/w4Joa_GSDt2lRPBOvJhASYxoxArJRENJeWfrBI-73UM: 502", "instance": "", "subproblems": null}, "order": "https://acme-v02.api.letsencrypt.org/acme/order/3552334225/534614614875", "attempt": 1, "max_attempts": 3}
2026/07/20 18:48:09.294 INFO    http.acme_client        trying to solve challenge       {"identifier": "git.vera-woof.com", "challenge_type": "tls-alpn-01", "ca": "https://acme-v02.api.letsencrypt.org/directory"}
2026/07/20 18:48:09.717 ERROR   http.acme_client        challenge failed        {"identifier": "git.vera-woof.com", "challenge_type": "tls-alpn-01", "problem": {"type": "urn:ietf:params:acme:error:unauthorized", "title": "", "detail": "Cannot negotiate ALPN protocol \"acme-tls/1\" for tls-alpn-01 challenge", "instance": "", "subproblems": null}}
2026/07/20 18:48:09.717 ERROR   http.acme_client        validating authorization        {"identifier": "git.vera-woof.com", "problem": {"type": "urn:ietf:params:acme:error:unauthorized", "title": "", "detail": "Cannot negotiate ALPN protocol \"acme-tls/1\" for tls-alpn-01 challenge", "instance": "", "subproblems": null}, "order": "https://acme-v02.api.letsencrypt.org/acme/order/3552334225/534614624185", "attempt": 2, "max_attempts": 3}
2026/07/20 18:48:09.717 ERROR   tls.obtain      could not get certificate from issuer   {"identifier": "git.vera-woof.com", "issuer": "acme-v02.api.letsencrypt.org-directory", "error": "HTTP 403 urn:ietf:params:acme:error:unauthorized - Cannot negotiate ALPN protocol \"acme-tls/1\" for tls-alpn-01 challenge"}
2026/07/20 18:48:09.717 ERROR   tls.obtain      will retry      {"error": "[git.vera-woof.com] Obtain: [git.vera-woof.com] solving challenge: git.vera-woof.com: [git.vera-woof.com] authorization failed: HTTP 403 urn:ietf:params:acme:error:unauthorized - Cannot negotiate ALPN protocol \"acme-tls/1\" for tls-alpn-01 challenge (ca=https://acme-v02.api.letsencrypt.org/directory)", "attempt": 1, "retrying_in": 60, "elapsed": 3.107094532, "max_duration": 2592000}
^C2026/07/20 18:48:20.570       INFO    shutting down   {"signal": "SIGINT"}
2026/07/20 18:48:20.570 WARN    exiting; byeee!! 👋     {"signal": "SIGINT"}
2026/07/20 18:48:20.570 INFO    http    servers shutting down with eternal grace period
2026/07/20 18:48:20.571 INFO    tls.obtain      releasing lock  {"identifier": "git.vera-woof.com"}
2026/07/20 18:48:20.571 INFO    admin   stopped previous server {"address": "localhost:2019"}
2026/07/20 18:48:20.571 INFO    shutdown complete       {"signal": "SIGINT", "exit_code": 0}

3. Caddy version:

v2.11.4 h1:XKxkMTgNSizEvKG6QHue6cAsFOteU2qA61w2tKkCWi0=

4. How I installed and ran Caddy:

through APT disabling the linux service for testing

a. System environment:

Fresh Debian 13 x86_64 VM

b. Command:

sudo caddy run

c. Service/unit/compose file:

d. My complete Caddy config:

(tested with git.vera-woof.com as well as the https:// listed)

https://git.vera-woof.com {

        respond "test"

}

5. Links to relevant resources:

Is the DNS pointing to your Caddy instance? Ports are open to Caddy?

Are you in a Cloudflare tunnel?

For my reverse proxy, I leave off the protocol in the caddyfile block, e.g. git.vera-woof.com {

You might want to put an e-mail address in your caddyfile; the error log implies it is not necessary, though, which I find odd.

im behind a cloudflare tunnel, with essentially the same configuration as a cloudflare tunnel i use on a website that works

You need to configure Caddy to use the DNS-01 challenge to get the certificate since you have the host behind the Cloudflare proxy. Right now LetsEncrypt is trying to connect to you to complete the challenge but it’s of course connecting to Cloudflare instead.