1. The problem I’m having:
I’m trying to set the tls.ca directive conditionally based on an environment variable. Is this something that is possible or am I on a wild goose chase?
2. Error messages and/or full log output:
Here is what I’m trying:
*.example.com, example.com {
# Set the CA directory based on the environment type
map $ENVIRONMENT_TYPE {CA_DIRECTORY} {
~(prod|production|PROD|PRODUCTION) https://acme-v02.api.letsencrypt.org/directory
default https://acme-staging-v02.api.letsencrypt.org/directory
}
# Set TLS options for wildcard certificate
tls {
dns cloudflare {$CADDY_CLOUDFLARE_API_TOKEN}
resolvers 1.1.1.1 8.8.8.8
propagation_timeout 15m
ca {CA_DIRECTORY}
}
}
When I try that I get in the logs:
caddy-dev | {"level":"error","ts":1742306177.432562,"logger":"tls.obtain","msg":"could not get certificate from issuer","identifier":"*.example.com","issuer":"-{CA_DIRECTORY}","error":"parse \"https://{CA_DIRECTORY}\": invalid character \"{\" in host name"}
caddy-dev | {"level":"error","ts":1742306177.4325614,"logger":"tls.obtain","msg":"could not get certificate from issuer","identifier":"example.com","issuer":"-{CA_DIRECTORY}","error":"parse \"https://{CA_DIRECTORY}\": invalid character \"{\" in host name"}
caddy-dev | {"level":"error","ts":1742306177.4325862,"logger":"tls.obtain","msg":"will retry","error":"[*.example.com] Obtain: parse \"https://{CA_DIRECTORY}\": invalid character \"{\" in host name","attempt":1,"retrying_in":60,"elapsed":0.000776375,"max_duration":2592000}
caddy-dev | {"level":"error","ts":1742306177.4325912,"logger":"tls.obtain","msg":"will retry","error":"[example.com] Obtain: parse \"https://{CA_DIRECTORY}\": invalid character \"{\" in host name","attempt":1,"retrying_in":60,"elapsed":0.000784958,"max_duration":2592000}
Gracefully stopping... (press Ctrl+C again to force)
3. Caddy version:
v2.9.1
4. How I installed and ran Caddy:
Running Caddy in docker desktop on my arm mac book
b. Command:
docker compose up
c. Service/unit/compose file:
volumes:
caddy_data:
caddy_config:
services:
caddy:
image: serfriz/caddy-cloudflare-crowdsec:2
container_name: caddy-${ENVIRONMENT_TYPE}
restart: unless-stopped
environment:
- ENVIRONMENT_TYPE
- CADDY_ACME_EMAIL
- CADDY_CLOUDFLARE_API_TOKEN
# - CADDY_CROWDSEC_API_TOKEN
# - CADDY_CROWDSEC_API_HOST
# - CADDY_CROWDSEC_API_PORT
ports:
- 127.0.0.1:2019:2019/tcp
- 80:80/tcp
- 443:443/tcp
- 443:443/udp
volumes:
- caddy_data:/data
- caddy_config:/config
- ./caddy/Caddyfile:/etc/caddy/Caddyfile
- ./caddy/conf.d:/etc/caddy/conf.d
- ./caddy/sites.d:/etc/caddy/sites.d
d. My complete Caddy config:
{
# Email for Let's Encrypt
email {$CADDY_ACME_EMAIL}
# Set TLS verification option
acme_dns cloudflare {$CADDY_CLOUDFLARE_API_TOKEN}
servers {
# Set client IP headers
client_ip_headers X-Forwarded-For X-Real-IP CF-Connecting-IP
# Set trusted proxies to Cloudflare addresses
trusted_proxies cloudflare {
# Pull the Cloudflare IP addresses from the Cloudflare API every x hours
interval 12h
# Set timeout for the Cloudflare API request
timeout 15s
}
}
}
*.example.com, example.com {
# Set the CA directory based on the environment type
map $ENVIRONMENT_TYPE {CA_DIRECTORY} {
~(prod|production|PROD|PRODUCTION) https://acme-v02.api.letsencrypt.org/directory
default https://acme-staging-v02.api.letsencrypt.org/directory
}
# Set TLS options for wildcard certificate
tls {
dns cloudflare {$CADDY_CLOUDFLARE_API_TOKEN}
resolvers 1.1.1.1 8.8.8.8
propagation_timeout 15m
ca {CA_DIRECTORY}
}
}
5. Links to relevant resources:
I got the idea of trying to use a map from this: If/else (conditional) reverse_proxy