Wildcard ACME DNS challenge successful but can't access subdomains

My domain name contains my very rare full name so I redacted it.

1. The problem I’m having:

I’m running Caddy on a remote server with a dedicated IP4 + IP6 address in a docker container.
In my Caddyfile I have a block for the root domain and then a block for wildcard subdomains with the ACME DNS challenge.
The root domain works and returns the content with a valid cert but no subdomain is reachable despite the wildcard cert being granted.

2. Error messages and/or full log output:

    curl -vL foo.mydomain.dev
    * Could not resolve host: foo.mydomain.dev
    * Closing connection 0
    curl: (6) Could not resolve host: foo.mydomain.dev
WARN[0000] a network with name vaultwarden exists but was not created for project "caddy".
Set `external: true` to use an existing network 
[+] Running 1/1
 ✔ Container caddy_inwx  Created                                                                                                                                                                                                               0.1s 
Attaching to caddy_inwx
caddy_inwx  | {"level":"info","ts":1753215875.2804193,"msg":"maxprocs: Leaving GOMAXPROCS=2: CPU quota undefined"}
caddy_inwx  | {"level":"info","ts":1753215875.2813373,"msg":"GOMEMLIMIT is updated","package":"github.com/KimMachineGun/automemlimit/memlimit","GOMEMLIMIT":906323558,"previous":9223372036854775807}
caddy_inwx  | {"level":"info","ts":1753215875.2817318,"msg":"using config from file","file":"/etc/caddy/Caddyfile"}
caddy_inwx  | {"level":"info","ts":1753215875.2922359,"msg":"adapted config to JSON","adapter":"caddyfile"}
caddy_inwx  | {"level":"warn","ts":1753215875.293181,"msg":"Caddyfile input is not formatted; run 'caddy fmt --overwrite' to fix inconsistencies","adapter":"caddyfile","file":"/etc/caddy/Caddyfile","line":2}
caddy_inwx  | {"level":"info","ts":1753215875.3132775,"logger":"admin","msg":"admin endpoint started","address":"localhost:2019","enforce_origin":false,"origins":["//localhost:2019","//[::1]:2019","//127.0.0.1:2019"]}
caddy_inwx  | {"level":"info","ts":1753215875.31438,"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}
caddy_inwx  | {"level":"info","ts":1753215875.3144765,"logger":"http.auto_https","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
caddy_inwx  | {"level":"debug","ts":1753215875.3145814,"logger":"http.auto_https","msg":"adjusted config","tls":{"automation":{"policies":[{"subjects":["mydomain.dev"]},{"subjects":["*.mydomain.dev"]},{}]}},"http":{"servers":{"remaining_auto_https_redirects":{"listen":[":80"],"routes":[{},{}],"logs":{"logger_names":{"mydomain.dev":["log0"]},"skip_hosts":["*.mydomain.dev"]}},"srv0":{"listen":[":443"],"routes":[{"handle":[{"handler":"subroute","routes":[{"handle":[{"handler":"headers","response":{"deferred":true,"delete":["Server"],"set":{"Strict-Transport-Security":["max-age=31536000;"],"X-Frame-Options":["DENY"],"X-Robots-Tag":["none"],"X-Xss-Protection":["1; mode=block"]}}},{"encodings":{"gzip":{}},"handler":"encode","prefer":["gzip"]},{"body":"🦐","handler":"static_response"}]}]}],"terminal":true},{"handle":[{"handler":"subroute","routes":[{"group":"group4","handle":[{"handler":"subroute","routes":[{"handle":[{"body":"Foo!","handler":"static_response"}]}]}],"match":[{"host":["foo.mydomain.dev"]}]},{"group":"group4","handle":[{"handler":"subroute","routes":[{"handle":[{"body":"Bar!","handler":"static_response"}]}]}],"match":[{"host":["bar.mydomain.dev"]}]},{"group":"group4","handle":[{"handler":"subroute","routes":[{"handle":[{"body":"TEST","handler":"static_response"}]}]}]}]}],"terminal":true}],"tls_connection_policies":[{}],"automatic_https":{},"logs":{"logger_names":{"mydomain.dev":["log0"]},"skip_hosts":["*.mydomain.dev"]}}}}}
caddy_inwx  | {"level":"info","ts":1753215875.3187873,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc000686480"}
caddy_inwx  | {"level":"debug","ts":1753215875.319458,"logger":"http","msg":"starting server loop","address":"[::]:443","tls":true,"http3":false}
caddy_inwx  | {"level":"info","ts":1753215875.3197365,"logger":"http","msg":"enabling HTTP/3 listener","addr":":443"}
caddy_inwx  | {"level":"info","ts":1753215875.3203478,"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."}
caddy_inwx  | {"level":"info","ts":1753215875.3211339,"logger":"http.log","msg":"server running","name":"srv0","protocols":["h1","h2","h3"]}
caddy_inwx  | {"level":"debug","ts":1753215875.3215818,"logger":"http","msg":"starting server loop","address":"[::]:80","tls":false,"http3":false}
caddy_inwx  | {"level":"warn","ts":1753215875.3217592,"logger":"http","msg":"HTTP/2 skipped because it requires TLS","network":"tcp","addr":":80"}
caddy_inwx  | {"level":"warn","ts":1753215875.3218677,"logger":"http","msg":"HTTP/3 skipped because it requires TLS","network":"tcp","addr":":80"}
caddy_inwx  | {"level":"info","ts":1753215875.3219812,"logger":"http.log","msg":"server running","name":"remaining_auto_https_redirects","protocols":["h1","h2","h3"]}
caddy_inwx  | {"level":"info","ts":1753215875.3221974,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["*.mydomain.dev","mydomain.dev"]}
caddy_inwx  | {"level":"warn","ts":1753215875.324783,"logger":"tls","msg":"stapling OCSP","error":"no OCSP stapling for [*.mydomain.dev]: no OCSP server specified in certificate","identifiers":["*.mydomain.dev"]}
caddy_inwx  | {"level":"debug","ts":1753215875.3251655,"logger":"tls.cache","msg":"added certificate to cache","subjects":["*.mydomain.dev"],"expiration":1760974385,"managed":true,"issuer_key":"acme-v02.api.letsencrypt.org-directory","hash":"1592a10e7031cf68f5a77bbb2291b36509c6149c8d0b8ab8f6f0b5ac898f2101","cache_size":1,"cache_capacity":10000}
caddy_inwx  | {"level":"debug","ts":1753215875.3253133,"logger":"events","msg":"event","name":"cached_managed_cert","id":"86adf7a3-38ba-47b5-8b22-9a1440c51e13","origin":"tls","data":{"sans":["*.mydomain.dev"]}}
caddy_inwx  | {"level":"info","ts":1753215875.3248372,"logger":"tls","msg":"storage cleaning happened too recently; skipping for now","storage":"FileStorage:/data/caddy","instance":"353d6c16-ac3a-4a39-90fd-7124de315bff","try_again":1753302275.3248324,"try_again_in":86399.999999075}
caddy_inwx  | {"level":"info","ts":1753215875.3260918,"logger":"tls","msg":"finished cleaning storage units"}
caddy_inwx  | {"level":"debug","ts":1753215875.3263664,"logger":"tls","msg":"loading managed certificate","domain":"mydomain.dev","expiration":1760974384,"issuer_key":"acme-v02.api.letsencrypt.org-directory","storage":"FileStorage:/data/caddy"}
caddy_inwx  | {"level":"warn","ts":1753215875.3269284,"logger":"tls","msg":"stapling OCSP","error":"no OCSP stapling for [mydomain.dev]: no OCSP server specified in certificate","identifiers":["mydomain.dev"]}
caddy_inwx  | {"level":"debug","ts":1753215875.327122,"logger":"tls.cache","msg":"added certificate to cache","subjects":["mydomain.dev"],"expiration":1760974384,"managed":true,"issuer_key":"acme-v02.api.letsencrypt.org-directory","hash":"ac2e8963454df8507992e760787ac8487720339d7a13c2116154ed109cd2f43a","cache_size":2,"cache_capacity":10000}
caddy_inwx  | {"level":"debug","ts":1753215875.3272395,"logger":"events","msg":"event","name":"cached_managed_cert","id":"4e68d3c9-3b23-47f5-a785-a186b640aafb","origin":"tls","data":{"sans":["mydomain.dev"]}}
caddy_inwx  | {"level":"debug","ts":1753215875.3273563,"logger":"events","msg":"event","name":"started","id":"d9669937-afb8-4d61-bb1b-7910a7c82aca","origin":"","data":null}
caddy_inwx  | {"level":"info","ts":1753215875.3277988,"msg":"autosaved config (load with --resume flag)","file":"/config/caddy/autosave.json"}
caddy_inwx  | {"level":"info","ts":1753215875.327928,"msg":"serving initial configuration"}

3. Caddy version:

caddy:2.10.0-alpine

4. How I installed and ran Caddy:

create the Docker file:

FROM caddy:2.10.0-builder-alpine AS builder

RUN xcaddy build \
    --with github.com/caddy-dns/inwx@v0.4.0

FROM caddy:2.10.0-alpine

COPY --from=builder /usr/bin/caddy /usr/bin/caddy

then create the image:
docker build -t caddy:inwx.
then create the compose.yml:

services:
  caddy:
    build: .
    image: caddy:inwx
    container_name: caddy_inwx
    restart: unless-stopped
    ports:
      - 80:80
      - 443:443
      - 443:443/udp
    networks:
      - vaultwarden
    volumes:
      - ./volumes/Caddyfile:/etc/caddy/Caddyfile:ro
      - ./volumes/config:/config
      - ./volumes/data:/data
    environment:
      #- DOMAIN=https://mydomain.dev
      - EMAIL=admin@mydomain.dev
      - LOG_FILE=/data/access.log

networks:
  vaultwarden:
    name: vaultwarden

then run the container:
sudo docker compose up -d

a. System environment:

OS: CentOS Stream 9
Arch: x86
SystemD: systemd 252 (252-53.el9)
Docker: Docker version 28.3.2, build 578ccf6

b. Command:

sudo docker compose up -d

c. Service/unit/compose file:

Dockerfile:

FROM caddy:2.10.0-builder-alpine AS builder

RUN xcaddy build \
    --with github.com/caddy-dns/inwx@v0.4.0

FROM caddy:2.10.0-alpine

COPY --from=builder /usr/bin/caddy /usr/bin/caddy

d. My complete Caddy config:

{
debug
}

mydomain.dev:443 {
	log {
		level INFO
		output file /var/log/caddy {
			roll_size 10MB
			roll_keep 100
		}
	}

	# Get a cert by using the ACME HTTP-01 challenge.
	tls {$EMAIL}

	encode gzip

	# Headers to improve security.
	header {
		# Enable HSTS
		Strict-Transport-Security "max-age=31536000;"
		# Enable cross-site filter (XSS)
		X-XSS-Protection "1; mode=block"
		# Disallow the site to be rendered within a frame (clickjacking protection)
		X-Frame-Options "DENY"
		# Prevent search engines from indexing
		X-Robots-Tag "none"
		# Remove Caddy branding
		-Server
	}

	respond "🦐"
}

*.mydomain.dev {
	tls {
		dns inwx {
			username ********
			password ********
		}
	}

	@foo host foo.mydomain.dev
	handle @foo {
		respond "Foo!"
	}

	@bar host bar.mydomain.dev
	handle @bar {
		respond "Bar!"
	}

	# Fallback for otherwise unhandled domains
	handle {
		respond "TEST"
	}

}

5. Links to relevant resources:

Try changing this:

to this:

*.mydomain.dev {
	tls {
		dns inwx {
			username ********
			password ********
		}
	}

	# Fallback for otherwise unhandled domains
	respond "TEST"
}

foo.mydomain.dev {
	respond "Foo!"
}

bar.mydomain.dev {
	respond "Bar!"
}

With v2.10.0, both foo.mydomain.dev and bar.mydomain.dev should automatically use the certificate issued for *.mydomain.dev.

However, this:

looks like a DNS problem. And since you’ve redacted your domain name, I can’t help with that.

Edit:

Make sure you have a wildcard DNS entry in your DNS zone:

Either

*.mydomain.dev.   IN   A   YOUR_IP

or

*.mydomain.dev.   IN   CNAME   mydomain.dev.
mydomain.dev.     IN       A   YOUR_IP
1 Like

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