Hello!
1. The problem I’m having:
I’m using Caddy as a reverse proxy in front of an application serving HTTP and GRPC APIs.
I tried using the CLI, but GRPC didn’t work. I then tried to use a Caddyfile and it worked. What’s the difference between the two configuration methods?
2. Error messages and/or full log output:
With the CLI:
caddy-1 | {"level":"debug","ts":1730823380.2811732,"logger":"events","msg":"event","name":"tls_get_certificate","id":"170e4e6d-2193-4873-94e9-22037da0f9e4","origin":"tls","data":{"client_hello":{"CipherSuites":[49195,49199,49196,49200,52393,52392,4865,4866,4867],"ServerName":"localhost","SupportedCurves":[29,23,24,25],"SupportedPoints":"AA==","SignatureSchemes":[2052,1027,2055,2053,2054,1025,1281,1537,1283,1539,513,515],"SupportedProtos":["h2"],"SupportedVersions":[772,771],"RemoteAddr":{"IP":"10.89.0.32","Port":33628,"Zone":""},"LocalAddr":{"IP":"10.89.0.32","Port":8443,"Zone":""}}}}
caddy-1 | {"level":"debug","ts":1730823380.2814481,"logger":"tls.handshake","msg":"choosing certificate","identifier":"localhost","num_choices":1}
caddy-1 | {"level":"debug","ts":1730823380.2814696,"logger":"tls.handshake","msg":"default certificate selection results","identifier":"localhost","subjects":["localhost"],"managed":true,"issuer_key":"local","hash":"863ccab3bfda2b546430f0046f0486b1a5177add34621adfcd350aae5ee0d9f5"}
caddy-1 | {"level":"debug","ts":1730823380.2814777,"logger":"tls.handshake","msg":"matched certificate in cache","remote_ip":"10.89.0.32","remote_port":"33628","subjects":["localhost"],"managed":true,"expiration":1730866558,"hash":"863ccab3bfda2b546430f0046f0486b1a5177add34621adfcd350aae5ee0d9f5"}
caddy-1 | {"level":"debug","ts":1730823380.283846,"logger":"http.handlers.reverse_proxy","msg":"selected upstream","dial":"zitadel:8080","total_upstreams":1}
zitadel-1 | 2024/11/05 16:16:20 ERROR: Failed to extract ServerMetadata from context
With Caddyfile:
caddy-1 | {"level":"debug","ts":1730823667.8643844,"logger":"events","msg":"event","name":"tls_get_certificate","id":"ae770161-1da8-400c-9746-3fa5be50264d","origin":"tls","data":{"client_hello":{"CipherSuites":[49195,49199,49196,49200,52393,52392,4865,4866,4867],"ServerName":"localhost","SupportedCurves":[29,23,24,25],"SupportedPoints":"AA==","SignatureSchemes":[2052,1027,2055,2053,2054,1025,1281,1537,1283,1539,513,515],"SupportedProtos":["h2"],"SupportedVersions":[772,771],"RemoteAddr":{"IP":"10.89.0.41","Port":39032,"Zone":""},"LocalAddr":{"IP":"10.89.0.41","Port":8443,"Zone":""}}}}
caddy-1 | {"level":"debug","ts":1730823667.8644094,"logger":"tls.handshake","msg":"choosing certificate","identifier":"localhost","num_choices":1}
caddy-1 | {"level":"debug","ts":1730823667.8644223,"logger":"tls.handshake","msg":"default certificate selection results","identifier":"localhost","subjects":["localhost"],"managed":true,"issuer_key":"local","hash":"dbf33036f79f0b3085611b859715ffc4ecd15e6ce0f9f2fb72cecf63e782758c"}
caddy-1 | {"level":"debug","ts":1730823667.8644297,"logger":"tls.handshake","msg":"matched certificate in cache","remote_ip":"10.89.0.41","remote_port":"39032","subjects":["localhost"],"managed":true,"expiration":1730866753,"hash":"dbf33036f79f0b3085611b859715ffc4ecd15e6ce0f9f2fb72cecf63e782758c"}
caddy-1 | {"level":"debug","ts":1730823667.8665938,"logger":"http.handlers.reverse_proxy","msg":"selected upstream","dial":"zitadel:8080","total_upstreams":1}
caddy-1 | {"level":"debug","ts":1730823667.8687286,"logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":"zitadel:8080","duration":0.002089246,"request":{"remote_ip":"10.89.0.41","remote_port":"39032","client_ip":"10.89.0.41","proto":"HTTP/2.0","method":"POST","host":"localhost:8443","uri":"/grpc.reflection.v1.ServerReflection/ServerReflectionInfo","headers":{"Content-Type":["application/grpc"],"User-Agent":["grpcurl/v1.9.1 grpc-go/1.61.0"],"Te":["trailers"],"Grpc-Accept-Encoding":["gzip"],"X-Forwarded-For":["10.89.0.41"],"X-Forwarded-Proto":["https"],"X-Forwarded-Host":["localhost:8443"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"localhost"}},"headers":{"Content-Type":["application/grpc"],"X-Robots-Tag":["none"]},"status":200}
3. Caddy version:
v2.8.4 h1:q3pe0wpBj1OcHFZ3n/1nl4V4bxBrYoSoab7rL9BMYNk=
4. How I installed and ran Caddy:
Podman Compose
a. System environment:
Linux (Fedora Silverblue 41), x86_64, Podman 5.2.5
b. Command:
podman compose up
c. Service/unit/compose file:
docker-compose.yaml:
version: '3.8'
services:
caddy:
image: "caddy:latest"
volumes:
- './Caddyfile:/etc/caddy/Caddyfile:ro,z'
#command: 'caddy reverse-proxy --debug --access-log --to h2c://zitadel:8080 --from localhost:8443'
ports:
- "8443:8443"
networks:
- 'zitadel'
zitadel:
restart: 'always'
networks:
- 'zitadel'
image: 'ghcr.io/zitadel/zitadel:latest'
command: 'start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --tlsMode disabled'
environment:
- 'ZITADEL_DATABASE_POSTGRES_HOST=db'
- 'ZITADEL_DATABASE_POSTGRES_PORT=5432'
- 'ZITADEL_DATABASE_POSTGRES_DATABASE=zitadel'
- 'ZITADEL_DATABASE_POSTGRES_USER_USERNAME=zitadel'
- 'ZITADEL_DATABASE_POSTGRES_USER_PASSWORD=zitadel'
- 'ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE=disable'
- 'ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME=postgres'
- 'ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD=postgres'
- 'ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE=disable'
- 'ZITADEL_EXTERNALSECURE=false'
- 'ZITADEL_FIRSTINSTANCE_MACHINEKEYPATH=/machinekey/zitadel-admin-sa.json'
- 'ZITADEL_FIRSTINSTANCE_PATPATH=/machinekey/pat.json'
- 'ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINE_USERNAME=zitadel-admin-sa'
- 'ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINE_NAME=Admin'
- 'ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINEKEY_TYPE=1'
- 'ZITADEL_FIRSTINSTANCE_ORG_MACHINE_PAT_EXPIRATIONDATE=2025-01-01T00:00:00Z'
depends_on:
db:
condition: 'service_healthy'
ports:
- '8080:8080'
volumes:
- ./machinekey:/machinekey:z
db:
restart: 'always'
image: postgres:16-alpine
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
networks:
- 'zitadel'
healthcheck:
test: ["CMD-SHELL", "pg_isready", "-d", "db_prod"]
interval: '10s'
timeout: '30s'
retries: 5
start_period: '20s'
networks:
zitadel:
d. My complete Caddy config:
CLI:
caddy reverse-proxy --debug --access-log --to h2c://zitadel:8080 --from localhost:8443
Caddyfile:
{
debug
}
localhost:8443 {
reverse_proxy h2c://zitadel:8080
}