1. The problem I’m having:
Hello all,
I’m trying to get Caddy up and running with a wildcard certificate through the DNS challenge to allow for it to be a reverse proxy internally on my network and make things a bit nicer when I’m on Tailscale remotely. Previously I was using the acme_dns
global option (commented out in my Caddyfile), however it was timing out while waiting for the record propagation, so I switched to using the tls
directive instead and fed it Quad9 as a resolver as I have Technitium operating as my DNS server on the network, and it’s pointing back at the Caddy server itself in anticipation of it working, with an A
record for the domain itself, and CNAME
records set up for all the subdomains I have listed in the Caddyfile.
After the change from global option to directive, the logs appear to be showing that Caddy now cannot actually place the DNS challenge record with my registrar (Namesilo) with an HTTP/400 error. I just reissued a new API token this morning and replaced it in my .env file, so it’s up to date and should be working. Is there an issue with my tls
directive, or some issue elsewhere with my setup? I’d like to avoid exposing/forwarding ports if I can, I want to keep this rather isolated if feasible.
2. Error messages and/or full log output:
{"level":"info","ts":1723471655.2210047,"msg":"using config from file","file":"/etc/caddy/Caddyfile"}
{"level":"info","ts":1723471655.2344685,"msg":"adapted config to JSON","adapter":"caddyfile"}
{"level":"warn","ts":1723471655.2347314,"msg":"Caddyfile input is not formatted; run 'caddy fmt --overwrite' to fix inconsistencies","adapter":"caddyfile","file":"/etc/caddy/Caddyfile","line":3}
{"level":"info","ts":1723471655.2388623,"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":1723471655.2392488,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc0003e9d00"}
{"level":"info","ts":1723471655.239563,"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":1723471655.2461364,"logger":"http.auto_https","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
{"level":"info","ts":1723471655.2546184,"logger":"http","msg":"enabling HTTP/3 listener","addr":":443"}
{"level":"info","ts":1723471655.2547846,"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":1723471655.2820082,"logger":"http.log","msg":"server running","name":"srv0","protocols":["h1","h2","h3"]}
{"level":"info","ts":1723471655.2935047,"logger":"http.log","msg":"server running","name":"remaining_auto_https_redirects","protocols":["h1","h2","h3"]}
{"level":"info","ts":1723471655.2935338,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["*.hermnet.org"]}
{"level":"info","ts":1723471655.2938173,"msg":"autosaved config (load with --resume flag)","file":"/config/caddy/autosave.json"}
{"level":"info","ts":1723471655.2938337,"msg":"serving initial configuration"}
{"level":"info","ts":1723471655.2941442,"logger":"tls.obtain","msg":"acquiring lock","identifier":"*.hermnet.org"}
{"level":"info","ts":1723471655.2988243,"logger":"tls","msg":"storage cleaning happened too recently; skipping for now","storage":"FileStorage:/data/caddy","instance":"f19ca2e2-900c-4592-b4ca-8d854e9ffae6","try_again":1723558055.298815,"try_again_in":86399.999999314}
{"level":"info","ts":1723471655.298946,"logger":"tls","msg":"finished cleaning storage units"}
{"level":"info","ts":1723471655.40907,"logger":"tls.obtain","msg":"lock acquired","identifier":"*.hermnet.org"}
{"level":"info","ts":1723471655.409277,"logger":"tls.obtain","msg":"obtaining certificate","identifier":"*.hermnet.org"}
{"level":"info","ts":1723471655.420125,"logger":"tls.issuance.acme","msg":"waiting on internal rate limiter","identifiers":["*.hermnet.org"],"ca":"https://acme-v02.api.letsencrypt.org/directory","account":"certificates@hermnet.org"}
{"level":"info","ts":1723471655.4201841,"logger":"tls.issuance.acme","msg":"done waiting on internal rate limiter","identifiers":["*.hermnet.org"],"ca":"https://acme-v02.api.letsencrypt.org/directory","account":"certificates@hermnet.org"}
{"level":"info","ts":1723471655.4202483,"logger":"tls.issuance.acme","msg":"using ACME account","account_id":"https://acme-v02.api.letsencrypt.org/acme/acct/1887056136","account_contact":["mailto:certificates@hermnet.org"]}
{"level":"info","ts":1723471656.8095036,"logger":"tls.issuance.acme.acme_client","msg":"trying to solve challenge","identifier":"*.hermnet.org","challenge_type":"dns-01","ca":"https://acme-v02.api.letsencrypt.org/directory"}
{"level":"error","ts":1723471668.344679,"logger":"tls.issuance.acme.acme_client","msg":"challenge failed","identifier":"*.hermnet.org","challenge_type":"dns-01","problem":{"type":"urn:ietf:params:acme:error:dns","title":"","detail":"DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hermnet.org - check that a DNS record exists for this domain","instance":"","subproblems":[]}}
{"level":"error","ts":1723471668.344839,"logger":"tls.issuance.acme.acme_client","msg":"validating authorization","identifier":"*.hermnet.org","problem":{"type":"urn:ietf:params:acme:error:dns","title":"","detail":"DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hermnet.org - check that a DNS record exists for this domain","instance":"","subproblems":[]},"order":"https://acme-v02.api.letsencrypt.org/acme/order/1887056136/295649641826","attempt":1,"max_attempts":3}
{"level":"error","ts":1723471668.3449442,"logger":"tls.obtain","msg":"could not get certificate from issuer","identifier":"*.hermnet.org","issuer":"acme-v02.api.letsencrypt.org-directory","error":"HTTP 400 urn:ietf:params:acme:error:dns - DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hermnet.org - check that a DNS record exists for this domain"}
{"level":"error","ts":1723471668.345086,"logger":"tls.obtain","msg":"will retry","error":"[*.hermnet.org] Obtain: [*.hermnet.org] solving challenge: *.hermnet.org: [*.hermnet.org] authorization failed: HTTP 400 urn:ietf:params:acme:error:dns - DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hermnet.org - check that a DNS record exists for this domain (ca=https://acme-v02.api.letsencrypt.org/directory)","attempt":1,"retrying_in":60,"elapsed":12.935936235,"max_duration":2592000}
{"level":"info","ts":1723471728.3474252,"logger":"tls.obtain","msg":"obtaining certificate","identifier":"*.hermnet.org"}
{"level":"info","ts":1723471728.348348,"logger":"tls.issuance.acme","msg":"using ACME account","account_id":"https://acme-staging-v02.api.letsencrypt.org/acme/acct/159090673","account_contact":["mailto:certificates@hermnet.org"]}
{"level":"info","ts":1723471729.2994294,"logger":"tls.issuance.acme.acme_client","msg":"trying to solve challenge","identifier":"*.hermnet.org","challenge_type":"dns-01","ca":"https://acme-staging-v02.api.letsencrypt.org/directory"}
{"level":"error","ts":1723471740.2394154,"logger":"tls.issuance.acme.acme_client","msg":"challenge failed","identifier":"*.hermnet.org","challenge_type":"dns-01","problem":{"type":"urn:ietf:params:acme:error:dns","title":"","detail":"DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hermnet.org - check that a DNS record exists for this domain","instance":"","subproblems":[]}}
{"level":"error","ts":1723471740.2395508,"logger":"tls.issuance.acme.acme_client","msg":"validating authorization","identifier":"*.hermnet.org","problem":{"type":"urn:ietf:params:acme:error:dns","title":"","detail":"DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hermnet.org - check that a DNS record exists for this domain","instance":"","subproblems":[]},"order":"https://acme-staging-v02.api.letsencrypt.org/acme/order/159090673/18367562143","attempt":1,"max_attempts":3}
{"level":"error","ts":1723471740.239645,"logger":"tls.obtain","msg":"could not get certificate from issuer","identifier":"*.hermnet.org","issuer":"acme-v02.api.letsencrypt.org-directory","error":"HTTP 400 urn:ietf:params:acme:error:dns - DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hermnet.org - check that a DNS record exists for this domain"}
{"level":"error","ts":1723471740.2398028,"logger":"tls.obtain","msg":"will retry","error":"[*.hermnet.org] Obtain: [*.hermnet.org] solving challenge: *.hermnet.org: [*.hermnet.org] authorization failed: HTTP 400 urn:ietf:params:acme:error:dns - DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hermnet.org - check that a DNS record exists for this domain (ca=https://acme-staging-v02.api.letsencrypt.org/directory)","attempt":2,"retrying_in":120,"elapsed":84.830652777,"max_duration":2592000}
{"level":"info","ts":1723471860.242474,"logger":"tls.obtain","msg":"obtaining certificate","identifier":"*.hermnet.org"}
{"level":"info","ts":1723471860.243069,"logger":"tls.issuance.acme","msg":"using ACME account","account_id":"https://acme-staging-v02.api.letsencrypt.org/acme/acct/159090673","account_contact":["mailto:certificates@hermnet.org"]}
{"level":"info","ts":1723471860.6415124,"logger":"tls.issuance.acme.acme_client","msg":"trying to solve challenge","identifier":"*.hermnet.org","challenge_type":"dns-01","ca":"https://acme-staging-v02.api.letsencrypt.org/directory"}
{"level":"error","ts":1723471871.6830816,"logger":"tls.issuance.acme.acme_client","msg":"challenge failed","identifier":"*.hermnet.org","challenge_type":"dns-01","problem":{"type":"urn:ietf:params:acme:error:dns","title":"","detail":"DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hermnet.org - check that a DNS record exists for this domain","instance":"","subproblems":[]}}
{"level":"error","ts":1723471871.6832235,"logger":"tls.issuance.acme.acme_client","msg":"validating authorization","identifier":"*.hermnet.org","problem":{"type":"urn:ietf:params:acme:error:dns","title":"","detail":"DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hermnet.org - check that a DNS record exists for this domain","instance":"","subproblems":[]},"order":"https://acme-staging-v02.api.letsencrypt.org/acme/order/159090673/18367597613","attempt":1,"max_attempts":3}
{"level":"error","ts":1723471871.683271,"logger":"tls.obtain","msg":"could not get certificate from issuer","identifier":"*.hermnet.org","issuer":"acme-v02.api.letsencrypt.org-directory","error":"HTTP 400 urn:ietf:params:acme:error:dns - DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hermnet.org - check that a DNS record exists for this domain"}
{"level":"error","ts":1723471871.6833751,"logger":"tls.obtain","msg":"will retry","error":"[*.hermnet.org] Obtain: [*.hermnet.org] solving challenge: *.hermnet.org: [*.hermnet.org] authorization failed: HTTP 400 urn:ietf:params:acme:error:dns - DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hermnet.org - check that a DNS record exists for this domain (ca=https://acme-staging-v02.api.letsencrypt.org/directory)","attempt":3,"retrying_in":120,"elapsed":216.274225456,"max_duration":2592000}
{"level":"info","ts":1723471991.6870887,"logger":"tls.obtain","msg":"obtaining certificate","identifier":"*.hermnet.org"}
{"level":"info","ts":1723471991.6879714,"logger":"tls.issuance.acme","msg":"using ACME account","account_id":"https://acme-staging-v02.api.letsencrypt.org/acme/acct/159090673","account_contact":["mailto:certificates@hermnet.org"]}
{"level":"info","ts":1723471992.0073411,"logger":"tls.issuance.acme.acme_client","msg":"trying to solve challenge","identifier":"*.hermnet.org","challenge_type":"dns-01","ca":"https://acme-staging-v02.api.letsencrypt.org/directory"}
{"level":"error","ts":1723472003.087248,"logger":"tls.issuance.acme.acme_client","msg":"challenge failed","identifier":"*.hermnet.org","challenge_type":"dns-01","problem":{"type":"urn:ietf:params:acme:error:dns","title":"","detail":"DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hermnet.org - check that a DNS record exists for this domain","instance":"","subproblems":[]}}
{"level":"error","ts":1723472003.0873575,"logger":"tls.issuance.acme.acme_client","msg":"validating authorization","identifier":"*.hermnet.org","problem":{"type":"urn:ietf:params:acme:error:dns","title":"","detail":"DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hermnet.org - check that a DNS record exists for this domain","instance":"","subproblems":[]},"order":"https://acme-staging-v02.api.letsencrypt.org/acme/order/159090673/18367635023","attempt":1,"max_attempts":3}
{"level":"error","ts":1723472003.087397,"logger":"tls.obtain","msg":"could not get certificate from issuer","identifier":"*.hermnet.org","issuer":"acme-v02.api.letsencrypt.org-directory","error":"HTTP 400 urn:ietf:params:acme:error:dns - DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hermnet.org - check that a DNS record exists for this domain"}
{"level":"error","ts":1723472003.087474,"logger":"tls.obtain","msg":"will retry","error":"[*.hermnet.org] Obtain: [*.hermnet.org] solving challenge: *.hermnet.org: [*.hermnet.org] authorization failed: HTTP 400 urn:ietf:params:acme:error:dns - DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hermnet.org - check that a DNS record exists for this domain (ca=https://acme-staging-v02.api.letsencrypt.org/directory)","attempt":4,"retrying_in":300,"elapsed":347.6783249,"max_duration":2592000}
{"level":"info","ts":1723472303.0886636,"logger":"tls.obtain","msg":"obtaining certificate","identifier":"*.hermnet.org"}
{"level":"info","ts":1723472303.0898333,"logger":"tls.issuance.acme","msg":"using ACME account","account_id":"https://acme-staging-v02.api.letsencrypt.org/acme/acct/159090673","account_contact":["mailto:certificates@hermnet.org"]}
{"level":"info","ts":1723472303.8862467,"logger":"tls.issuance.acme.acme_client","msg":"trying to solve challenge","identifier":"*.hermnet.org","challenge_type":"dns-01","ca":"https://acme-staging-v02.api.letsencrypt.org/directory"}
{"level":"error","ts":1723472314.9992726,"logger":"tls.issuance.acme.acme_client","msg":"challenge failed","identifier":"*.hermnet.org","challenge_type":"dns-01","problem":{"type":"urn:ietf:params:acme:error:dns","title":"","detail":"DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hermnet.org - check that a DNS record exists for this domain","instance":"","subproblems":[]}}
{"level":"error","ts":1723472314.9993832,"logger":"tls.issuance.acme.acme_client","msg":"validating authorization","identifier":"*.hermnet.org","problem":{"type":"urn:ietf:params:acme:error:dns","title":"","detail":"DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hermnet.org - check that a DNS record exists for this domain","instance":"","subproblems":[]},"order":"https://acme-staging-v02.api.letsencrypt.org/acme/order/159090673/18367711753","attempt":1,"max_attempts":3}
{"level":"error","ts":1723472314.9994605,"logger":"tls.obtain","msg":"could not get certificate from issuer","identifier":"*.hermnet.org","issuer":"acme-v02.api.letsencrypt.org-directory","error":"HTTP 400 urn:ietf:params:acme:error:dns - DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hermnet.org - check that a DNS record exists for this domain"}
{"level":"error","ts":1723472314.9995546,"logger":"tls.obtain","msg":"will retry","error":"[*.hermnet.org] Obtain: [*.hermnet.org] solving challenge: *.hermnet.org: [*.hermnet.org] authorization failed: HTTP 400 urn:ietf:params:acme:error:dns - DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hermnet.org - check that a DNS record exists for this domain (ca=https://acme-staging-v02.api.letsencrypt.org/directory)","attempt":5,"retrying_in":600,"elapsed":659.590403945,"max_duration":2592000}
3. Caddy version:
v2.8.4
4. How I installed and ran Caddy:
a. System environment:
Kubuntu 24.04 via Docker
b. Command:
docker compose up -d
c. Service/unit/compose file:
caddy:
build: ./dockerfile-caddy
container_name: caddy
hostname: caddy
env_file: .env
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
#- ./site:/srv
- ./caddy_data:/data
- ./caddy_config:/config
Dockerfile used to build my Caddy image
FROM caddy:2.8.4-builder AS builder
RUN xcaddy build --with github.com/caddy-dns/namesilo
FROM caddy:2.8.4
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
d. My complete Caddy config:
My domain is within the .env file and so is hidden within the Caddyfile, it’s hermnet.org
# Global Options. Includes email, and ACME challenge details
{
log log-main {
format json
output file /data/logs/caddy_access.log {
roll_size 20mb
roll_keep 10
roll_keep_for 365d
}
}
email certificates@hermnet.org
#acme_dns namesilo {$NAMESILO_API_TOKEN}
}
# Site block. Used for, theoretically, grabbing a cert and controlling all things for the reverse proxy related to the subdomains.
*.hermnet.org {
log {
format json
output file /data/logs/caddy_access.log {
roll_size 20mb
roll_keep 10
roll_keep_for 365d
}
}
tls {
issuer acme {
dns namesilo {$NAMESILO_API_TOKEN}
propagation_delay 10s
propagation_timeout -1
resolvers 9.9.9.9
}
#issuer zerossl {
# dns namesilo {$NAMESILO_API_TOKEN}
# propagation_delay 10s
# propagation_timeout -1
# resolvers 9.9.9.9
#}
}
@pve host pve.{$MY_DOMAIN}
handle @pve {
reverse_proxy https://192.168.1.41:8006 {
transport http {
tls
tls_insecure_skip_verify
}
}
}
@pbs host pbs.{$MY_DOMAIN}
handle @pbs {
reverse_proxy https://192.168.2.212:8007 {
transport http {
tls
tls_insecure_skip_verify
}
}
}
@opnsense host opnsense.{$MY_DOMAIN}
handle @opnsense {
reverse_proxy https://192.168.1.47 {
transport http {
tls
tls_insecure_skip_verify
}
}
}
@omv host omv.{$MY_DOMAIN}
handle @omv {
reverse_proxy 192.168.2.188:80
}
@technitium host technitium.{MY_DOMAIN}
handle @technitium {
reverse_proxy 192.168.2.189:53443
}
@pi host pi.{$MY_DOMAIN}
handle @pi {
reverse_proxy 192.168.1.77/admin
}
@openbooks host openbooks.{$MY_DOMAIN}
handle @openbooks {
reverse_proxy 192.168.2.205:8080/openbooks/
}
handle {
abort
}
}