1. The problem I’m having:
I built a web app using the Rust framework Axum and am trying to use Caddy as a reverse proxy, but I’m getting 502 errors on my domain https://wisderm.com/.
The web app is running so why is Caddy unable to establish a connection?
$ docker logs wisderm-app-1
Finished release [optimized] target(s) in 1.77s
warning: the following packages contain code that will be rejected by a future version of Rust: nom v5.1.2
note: to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 1`
Running `target/release/wisderm`
2. Error messages and/or full log output:
$ docker logs wisderm-caddy-1
{"level":"info","ts":1682517767.0923154,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
{"level":"warn","ts":1682517767.096441,"msg":"Caddyfile input is not formatted; run the 'caddy fmt' command to fix inconsistencies","adapter":"caddyfile","file":"/etc/caddy/Caddyfile","line":2}
{"level":"info","ts":1682517767.115291,"logger":"admin","msg":"admin endpoint started","address":"localhost:2019","enforce_origin":false,"origins":["//localhost:2019","//[::1]:2019","//127.0.0.1:2019"]}
{"level":"info","ts":1682517767.1181366,"logger":"http","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}
{"level":"info","ts":1682517767.1181595,"logger":"http","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
{"level":"info","ts":1682517767.1253803,"logger":"tls","msg":"cleaning storage unit","description":"FileStorage:/data/caddy"}
{"level":"info","ts":1682517767.1365693,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc0003193b0"}
{"level":"info","ts":1682517767.1368098,"logger":"http","msg":"enabling HTTP/3 listener","addr":":443"}
{"level":"debug","ts":1682517767.1424606,"logger":"http","msg":"starting server loop","address":"[::]:443","tls":true,"http3":true}
{"level":"info","ts":1682517767.1424818,"logger":"http.log","msg":"server running","name":"srv0","protocols":["h1","h2","h3"]}
{"level":"debug","ts":1682517767.1425407,"logger":"http","msg":"starting server loop","address":"[::]:80","tls":false,"http3":false}
{"level":"info","ts":1682517767.142548,"logger":"http.log","msg":"server running","name":"remaining_auto_https_redirects","protocols":["h1","h2","h3"]}
{"level":"info","ts":1682517767.1425524,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["wisderm.com"]}
{"level":"debug","ts":1682517767.1448789,"logger":"tls","msg":"loading managed certificate","domain":"wisderm.com","expiration":1690017381,"issuer_key":"acme-v02.api.letsencrypt.org-directory","storage":"FileStorage:/data/caddy"}
{"level":"debug","ts":1682517767.1452851,"logger":"tls.cache","msg":"added certificate to cache","subjects":["wisderm.com"],"expiration":1690017381,"managed":true,"issuer_key":"acme-v02.api.letsencrypt.org-directory","hash":"2f38ba06585c3b4e70995538625361d3612d802cdf6926c964c37df4bccfe90a","cache_size":1,"cache_capacity":10000}
{"level":"debug","ts":1682517767.1455686,"logger":"events","msg":"event","name":"cached_managed_cert","id":"e58df294-4c0d-44bd-aa87-ff450fed4b49","origin":"tls","data":{"sans":["wisderm.com"]}}
{"level":"info","ts":1682517767.1466587,"msg":"autosaved config (load with --resume flag)","file":"/config/caddy/autosave.json"}
{"level":"info","ts":1682517767.1466744,"msg":"serving initial configuration"}
{"level":"info","ts":1682517767.1484466,"logger":"tls","msg":"finished cleaning storage units"}
{"level":"debug","ts":1682517825.305438,"logger":"events","msg":"event","name":"tls_get_certificate","id":"404df34d-8a99-403d-8420-f4ebd90ed410","origin":"tls","data":{"client_hello":{"CipherSuites":[39578,4865,4866,4867,49195,49199,49196,49200,52393,52392,49171,49172,156,157,47,53],"ServerName":"wisderm.com","SupportedCurves":[14906,29,23,24],"SupportedPoints":"AA==","SignatureSchemes":[1027,2052,1025,1283,2053,1281,2054,1537],"SupportedProtos":["h2","http/1.1"],"SupportedVersions":[14906,772,771],"Conn":{}}}}
{"level":"debug","ts":1682517825.3071008,"logger":"tls.handshake","msg":"choosing certificate","identifier":"wisderm.com","num_choices":1}
{"level":"debug","ts":1682517825.3073769,"logger":"tls.handshake","msg":"default certificate selection results","identifier":"wisderm.com","subjects":["wisderm.com"],"managed":true,"issuer_key":"acme-v02.api.letsencrypt.org-directory","hash":"2f38ba06585c3b4e70995538625361d3612d802cdf6926c964c37df4bccfe90a"}
{"level":"debug","ts":1682517825.3076131,"logger":"tls.handshake","msg":"matched certificate in cache","remote_ip":"121.6.14.20","remote_port":"34704","subjects":["wisderm.com"],"managed":true,"expiration":1690017381,"hash":"2f38ba06585c3b4e70995538625361d3612d802cdf6926c964c37df4bccfe90a"}
{"level":"debug","ts":1682517825.311837,"logger":"events","msg":"event","name":"tls_get_certificate","id":"bed4b58f-2e3b-4220-b277-f30d7312e09d","origin":"tls","data":{"client_hello":{"CipherSuites":[64250,4865,4866,4867,49195,49199,49196,49200,52393,52392,49171,49172,156,157,47,53],"ServerName":"wisderm.com","SupportedCurves":[27242,29,23,24],"SupportedPoints":"AA==","SignatureSchemes":[1027,2052,1025,1283,2053,1281,2054,1537],"SupportedProtos":["h2","http/1.1"],"SupportedVersions":[23130,772,771],"Conn":{}}}}
{"level":"debug","ts":1682517825.3120992,"logger":"tls.handshake","msg":"choosing certificate","identifier":"wisderm.com","num_choices":1}
{"level":"debug","ts":1682517825.3122845,"logger":"tls.handshake","msg":"default certificate selection results","identifier":"wisderm.com","subjects":["wisderm.com"],"managed":true,"issuer_key":"acme-v02.api.letsencrypt.org-directory","hash":"2f38ba06585c3b4e70995538625361d3612d802cdf6926c964c37df4bccfe90a"}
{"level":"debug","ts":1682517825.3124912,"logger":"tls.handshake","msg":"matched certificate in cache","remote_ip":"121.6.14.20","remote_port":"34688","subjects":["wisderm.com"],"managed":true,"expiration":1690017381,"hash":"2f38ba06585c3b4e70995538625361d3612d802cdf6926c964c37df4bccfe90a"}
{"level":"debug","ts":1682517825.5887516,"logger":"events","msg":"event","name":"tls_get_certificate","id":"584967a7-ba3b-4ec8-8314-582a91915142","origin":"tls","data":{"client_hello":{"CipherSuites":[23130,4865,4866,4867,49195,49199,49196,49200,52393,52392,49171,49172,156,157,47,53],"ServerName":"wisderm.com","SupportedCurves":[27242,29,23,24],"SupportedPoints":"AA==","SignatureSchemes":[1027,2052,1025,1283,2053,1281,2054,1537],"SupportedProtos":["h2","http/1.1"],"SupportedVersions":[47802,772,771],"Conn":{}}}}
{"level":"debug","ts":1682517825.589097,"logger":"tls.handshake","msg":"choosing certificate","identifier":"wisderm.com","num_choices":1}
{"level":"debug","ts":1682517825.5892577,"logger":"tls.handshake","msg":"default certificate selection results","identifier":"wisderm.com","subjects":["wisderm.com"],"managed":true,"issuer_key":"acme-v02.api.letsencrypt.org-directory","hash":"2f38ba06585c3b4e70995538625361d3612d802cdf6926c964c37df4bccfe90a"}
{"level":"debug","ts":1682517825.58943,"logger":"tls.handshake","msg":"matched certificate in cache","remote_ip":"121.6.14.20","remote_port":"34708","subjects":["wisderm.com"],"managed":true,"expiration":1690017381,"hash":"2f38ba06585c3b4e70995538625361d3612d802cdf6926c964c37df4bccfe90a"}
{"level":"debug","ts":1682517825.602956,"logger":"http.handlers.reverse_proxy","msg":"selected upstream","dial":":3000","total_upstreams":1}
{"level":"debug","ts":1682517825.603911,"logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":":3000","duration":0.000620755,"request":{"remote_ip":"121.6.14.20","remote_port":"34704","proto":"HTTP/2.0","method":"GET","host":"wisderm.com","uri":"/","headers":{"Accept-Encoding":["gzip, deflate, br"],"X-Forwarded-Host":["wisderm.com"],"Sec-Fetch-Dest":["document"],"X-Forwarded-For":["121.6.14.20"],"User-Agent":["Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8,zh-CN;q=0.7,zh;q=0.6"],"Sec-Ch-Ua":["\"Google Chrome\";v=\"111\", \"Not(A:Brand\";v=\"8\", \"Chromium\";v=\"111\""],"Sec-Fetch-Mode":["navigate"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["none"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"X-Forwarded-Proto":["https"],"Sec-Ch-Ua-Platform":["\"Linux\""],"Upgrade-Insecure-Requests":["1"],"Sec-Fetch-User":["?1"],"Cache-Control":["max-age=0"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"wisderm.com"}},"error":"dial tcp :3000: connect: connection refused"}
{"level":"error","ts":1682517825.605828,"logger":"http.log.error","msg":"dial tcp :3000: connect: connection refused","request":{"remote_ip":"121.6.14.20","remote_port":"34704","proto":"HTTP/2.0","method":"GET","host":"wisderm.com","uri":"/","headers":{"Accept-Encoding":["gzip, deflate, br"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8,zh-CN;q=0.7,zh;q=0.6"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Linux\""],"Upgrade-Insecure-Requests":["1"],"User-Agent":["Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"],"Sec-Fetch-User":["?1"],"Sec-Fetch-Dest":["document"],"Cache-Control":["max-age=0"],"Sec-Ch-Ua":["\"Google Chrome\";v=\"111\", \"Not(A:Brand\";v=\"8\", \"Chromium\";v=\"111\""],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Sec-Fetch-Site":["none"],"Sec-Fetch-Mode":["navigate"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"wisderm.com"}},"duration":0.003090089,"status":502,"err_id":"jw5m6qdmp","err_trace":"reverseproxy.statusError (reverseproxy.go:1299)"}
{"level":"debug","ts":1682518143.1216724,"logger":"events","msg":"event","name":"tls_get_certificate","id":"7b8cf641-70b4-4666-b690-090d7ff0dfed","origin":"tls","data":{"client_hello":{"CipherSuites":[4865,4866,4867],"ServerName":"wisderm.com","SupportedCurves":[29,23,24],"SupportedPoints":null,"SignatureSchemes":[1027,2052,1025,1283,2053,1281,2054,1537,513],"SupportedProtos":["h3"],"SupportedVersions":[772],"Conn":{}}}}
{"level":"debug","ts":1682518143.1220875,"logger":"tls.handshake","msg":"choosing certificate","identifier":"wisderm.com","num_choices":1}
{"level":"debug","ts":1682518143.1221685,"logger":"tls.handshake","msg":"default certificate selection results","identifier":"wisderm.com","subjects":["wisderm.com"],"managed":true,"issuer_key":"acme-v02.api.letsencrypt.org-directory","hash":"2f38ba06585c3b4e70995538625361d3612d802cdf6926c964c37df4bccfe90a"}
{"level":"debug","ts":1682518143.1221952,"logger":"tls.handshake","msg":"matched certificate in cache","remote_ip":"121.6.14.20","remote_port":"34870","subjects":["wisderm.com"],"managed":true,"expiration":1690017381,"hash":"2f38ba06585c3b4e70995538625361d3612d802cdf6926c964c37df4bccfe90a"}
{"level":"debug","ts":1682518143.6025012,"logger":"http.handlers.reverse_proxy","msg":"selected upstream","dial":":3000","total_upstreams":1}
{"level":"debug","ts":1682518143.6035635,"logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":":3000","duration":0.000639808,"request":{"remote_ip":"121.6.14.20","remote_port":"34870","proto":"HTTP/3.0","method":"GET","host":"wisderm.com","uri":"/","headers":{"X-Forwarded-Host":["wisderm.com"],"User-Agent":["Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"],"Sec-Fetch-Mode":["navigate"],"Sec-Ch-Ua-Mobile":["?0"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Sec-Fetch-User":["?1"],"Sec-Ch-Ua-Platform":["\"Linux\""],"X-Forwarded-For":["121.6.14.20"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8,zh-CN;q=0.7,zh;q=0.6"],"Accept-Encoding":["gzip, deflate, br"],"Sec-Ch-Ua":["\"Google Chrome\";v=\"111\", \"Not(A:Brand\";v=\"8\", \"Chromium\";v=\"111\""],"X-Forwarded-Proto":["https"],"Upgrade-Insecure-Requests":["1"],"Sec-Fetch-Site":["none"],"Sec-Fetch-Dest":["document"],"Cache-Control":["max-age=0"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h3","server_name":"wisderm.com"}},"error":"dial tcp :3000: connect: connection refused"}
{"level":"error","ts":1682518143.603932,"logger":"http.log.error","msg":"dial tcp :3000: connect: connection refused","request":{"remote_ip":"121.6.14.20","remote_port":"34870","proto":"HTTP/3.0","method":"GET","host":"wisderm.com","uri":"/","headers":{"Sec-Fetch-Mode":["navigate"],"Accept-Encoding":["gzip, deflate, br"],"Sec-Ch-Ua":["\"Google Chrome\";v=\"111\", \"Not(A:Brand\";v=\"8\", \"Chromium\";v=\"111\""],"Sec-Ch-Ua-Mobile":["?0"],"User-Agent":["Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Sec-Fetch-Site":["none"],"Sec-Fetch-User":["?1"],"Sec-Fetch-Dest":["document"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8,zh-CN;q=0.7,zh;q=0.6"],"Cache-Control":["max-age=0"],"Sec-Ch-Ua-Platform":["\"Linux\""],"Upgrade-Insecure-Requests":["1"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h3","server_name":"wisderm.com"}},"duration":0.001623581,"status":502,"err_id":"drsigmckk","err_trace":"reverseproxy.statusError (reverseproxy.go:1299)"}
3. Caddy version:
$ docker exec -it wisderm-caddy-1 caddy version
v2.6.4 h1:2hwYqiRwk1tf3VruhMpLcYTg+11fCdr8S3jhNAdnPy8=
4. How I installed and ran Caddy:
I installed and ran Caddy using docker compose.
a. System environment:
I’m using a Vultr VPS with 1 vCPU, 1 GB RAM and 25 GB SSD storage. The OS is Debian 11 x64 (bullseye).
b. Command:
docker compose -f docker-compose.yml up -d --build
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
c. Service/unit/compose file:
This is my docker-compose.yml.
version: '3.4'
services:
db:
image: postgres:15-alpine
env_file:
- .env
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
volumes:
- postgres:/var/lib/postgresql/data
meilisearch:
image: getmeili/meilisearch:v1.1
env_file:
- .env
environment:
MEILI_NO_ANALYTICS: true
MEILI_ENV: production
ports:
- "7700:7700"
volumes:
- meili:/meili_data
app:
build:
context: .
dockerfile: Dockerfile
target: development
volumes:
- .:/wisderm:cached
# Give access to ssh keys on the host (Is there a better way to do this?)
- ~/.ssh:/home/host-ssh:cached
# We need this so docker in docker works
- /var/run/docker.sock:/var/run/docker.sock
- target:/wisderm/target # Set target as a volume for performance.
- migration-target:/wisderm/migration/target
# Uncomment the next line to improve performance when using node.
- node_modules:/wisderm/node_modules
env_file:
- .env
ports:
- "3000:3000"
# Overrides default command so things don't shut down after the process ends.
command: sleep infinity
working_dir: /wisderm
depends_on:
- db
- meilisearch
caddy:
image: caddy:2.6-alpine
restart: unless-stopped
ports:
# HTTP
- "80:80"
# HTTPS
- "443:443"
# HTTP/3
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
volumes:
postgres:
meili:
caddy_data:
caddy_config:
target:
migration-target:
node_modules:
This is my docker-compose.prod.yml.
version: '3.4'
services:
app:
build:
context: .
dockerfile: Dockerfile
target: production
command: cargo run --release
restart: always
d. My complete Caddy config:
This is my Caddyfile.
https://wisderm.com:443
file_server /wisderm/static
reverse_proxy :3000