1. The problem I’m having:
Hello!
I am trying to apply the following logic in my Caddy Server configuration. I want to be able to configure different domains/addresses using the automatic TLS provided by Let’s Encrypt to get wildcard certificates (integrating it with Cloudflare). For all those domains/IPs or blocks that I don’t explicitly define in the configuration that may come to point to my server, I want to configure it to serve a custom (self-signed) certificate by default (as a fallback).
In order to address the above, I have created the following configuration.
{
debug
email {$TLS__EMAIL}
}
:443 {
tls /security/certificates/selfsigned.crt /security/certificates/selfsigned.key
respond "Hello, world (fallback)!" 200
}
*.example.com, example.com {
tls {$TLS__EMAIL} {
dns cloudflare {$TLS__CLOUDFLARE_API_TOKEN}
resolvers 1.1.1.1 8.8.8.8 8.8.4.4
}
respond "Hello, world (example.com)!" 200
}
~ ❯ curl https://test.example.com
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
~ ❯ curl -k https://test.example.com
Hello, world (example.com)!%
~ ❯ curl https://test.anotherdomain.com
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
~ ❯ curl -k https://test.anotherdomain.com
Hello, world (fallback)!%
What is the problem? If I apply this configuration on my server, despite having explicitly defined the tls
configuration for my domains, they are all served with the custom (self-signed) certifcate. What I would expect is that the domains would use the tls
configuration specified for them, obtaining and serving a specific or adhoc generated wildcard certificate. On the other hand, if other unidentified HTTPS requests come to my server (through an unregistered domain pointing to the server, through the server IP, etc.) the intention is to serve the custom certificate.
Is this behavior not supported by Caddy Server?
Thank you very much!
2. Error messages and/or full log output:
ingress__caddy | {"level":"debug","ts":1739897695.673702,"logger":"events","msg":"event","name":"tls_get_certificate","id":"ffcc3e75-f663-4e09-b616-aa3a9e19d04f","origin":"tls","data":{"client_hello":{"CipherSuites":[4867,4866,4865,52393,52392,52394,49200,49196,49192,49188,49172,49162,159,107,57,65413,196,136,129,157,61,53,192,132,49199,49195,49191,49187,49171,49161,158,103,51,190,69,156,60,47,186,65,49169,49159,5,4,49170,49160,22,10,255],"ServerName":"test.example.com","SupportedCurves":[29,23,24,25],"SupportedPoints":"AA==","SignatureSchemes":[2054,1537,1539,2053,1281,1283,2052,1025,1027,513,515],"SupportedProtos":["h2","http/1.1"],"SupportedVersions":[772,771,770,769],"RemoteAddr":{"IP":"37.11.133.51","Port":59759,"Zone":""},"LocalAddr":{"IP":"172.18.0.2","Port":443,"Zone":""}}}}
ingress__caddy | {"level":"debug","ts":1739897695.6739562,"logger":"tls.handshake","msg":"no matching certificate; will choose from all certificates","identifier":"test.example.com"}
ingress__caddy | {"level":"debug","ts":1739897695.6739671,"logger":"tls.handshake","msg":"choosing certificate","identifier":"test.example.com","num_choices":3}
ingress__caddy | {"level":"debug","ts":1739897695.673991,"logger":"tls.handshake","msg":"custom certificate selection results","identifier":"test.example.com","subjects":["clancy"],"managed":false,"issuer_key":"","hash":"caaa6fb80b03135330bff9b4c62ddb51d08c0070bb2c288734aef1dd1558e4f7"}
ingress__caddy | {"level":"debug","ts":1739897695.674003,"logger":"tls.handshake","msg":"matched certificate in cache","remote_ip":"37.11.133.51","remote_port":"59759","subjects":["clancy"],"managed":false,"expiration":2055242426,"hash":"caaa6fb80b03135330bff9b4c62ddb51d08c0070bb2c288734aef1dd1558e4f7"}
3. Caddy version:
v2.9.1 h1:OEYiZ7DbCzAWVb6TNEkjRcSCRGHVoZsJinoDR/n9oaY=
4. How I installed and ran Caddy:
Using docker with the following image:
caddy:latest
a. System environment:
- OS:
Ubuntu 24.04
- Docker Version: `Docker version 27.3.1, build ce12230``
b. Command:
docker compose up
c. Service/unit/compose file:
services:
caddy:
image: caddy:latest
container_name: caddy
ports:
- 80:80
- 443:443
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./certificates:/security/certificates
d. My complete Caddy config:
{
debug
email {$TLS__EMAIL}
}
:443 {
tls /security/certificates/selfsigned.crt /security/certificates/selfsigned.key
respond "Hello, world (fallback)!" 200
}
*.example.com, example.com {
tls {$TLS__EMAIL} {
dns cloudflare {$TLS__CLOUDFLARE_API_TOKEN}
resolvers 1.1.1.1 8.8.8.8 8.8.4.4
}
respond "Hello, world (example.com)!" 200
}
5. Links to relevant resources:
N/A