1. The problem I’m having:
I’m trying to set up reverse proxying for multiple hosts, some of them with client certificate authentication with certs from my own CA so I can give access to my friends. I want all hosts (mTLS or not) to present Let’s Encrypt wildcard certificates to users so they don’t have to install my CA’s certs. I don’t want to expose internal subdomains to the world by obtaining a subdomain-specific certificate for them.
My issue is that with my current config, Caddy doesn’t renew the certificate automatically when it expires. I assume this is because it knows the files are in use. If I delete the cert and key, Caddy just doesn’t start because it can’t find them. There must be a better way to reference the already obtained wildcard cert while also not “locking it”.
2. Error messages and/or full log output:
N/A
3. Caddy version:
v2.11.3
4. How I installed and ran Caddy:
Docker Compose on Linux
a. System environment:
Raspberry Pi OS (Debian 11)
Docker-ce 29.1.3
b. Command:
N/A
c. Service/unit/compose file:
services:
caddy:
image: ghcr.io/caddybuilds/caddy-cloudflare:2
restart: unless-stopped
environment:
CF_API_TOKEN: "${CF_API_TOKEN}"
cap_add:
- NET_ADMIN
ports:
- "80:80"
- "443:443"
- "443:443/udp"
dns:
- 1.1.1.1
- 1.0.0.1
volumes:
- $PWD/conf:/etc/caddy
- /mnt/caddy/data:/data
d. My complete Caddy config:
# Global options
{
# Disable HTTP to HTTPS redirects and handle them manually below in order to not leak Server headers
auto_https disable_redirects
cert_issuer acme {
profile shortlived
}
}
# Snippet to disable sending the Server and Via headers
(disable_headers) {
header -Server
header -Via
}
http:// {
import disable_headers
redir * https://{host}{uri} 308
}
*.mydomain.tld {
import disable_headers
# Deny access from public IPs
@denied not client_ip 192.168.11.0/24
respond @denied 403 {
close
}
@grafana host grafana.mydomain.tld
@zabbix host zabbix.mydomain.tld
@adguard host adguard.mydomain.tld
reverse_proxy @grafana 192.168.11.13:3002
reverse_proxy @zabbix 192.168.11.10:8083
reverse_proxy @adguard 192.168.11.10:8081
tls {
protocols tls1.2 tls1.3
dns cloudflare {env.CF_API_TOKEN}
resolvers 1.1.1.1 1.0.0.1
propagation_delay 1m
propagation_timeout 5m
}
}
send.mydomain.tld {
import disable_headers
tls /data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/wildcard_.mydomain.tld/wildcard_.mydomain.tld.crt /data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/wildcard_.mydomain.tld/wildcard_.mydomain.tld.key {
client_auth {
mode require_and_verify
trust_pool file /etc/caddy/mydomain_tld_client_auth_ca_chain.pem
}
}
reverse_proxy 192.168.11.10:50080
log
}
matrix.mydomain.tld {
import disable_headers
tls /data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/wildcard_.mydomain.tld/wildcard_.mydomain.tld.crt /data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/wildcard_.mydomain.tld/wildcard_.mydomain.tld.key {
client_auth {
mode require_and_verify
trust_pool file /etc/caddy/mydomain_tld_client_auth_ca_chain.pem
}
}
reverse_proxy 192.168.11.12:8448
log
}