1. The problem I’m having:
I am trying to setup a websocket connection between two endpoints with caddy in between. I am using socketio for my server-client communication and everything runs on same host. I already verified the issue is not with the endpoints since direct communication between them works, and they are able to exchange messages using websocket. I enabled debug logs on the client-server endpoints and on caddy. The only thing that I can see that looks like an error, is a streaming error coming from caddy. I tried playing around with the flush_interval, and stream_timeout directives but that didn’t help.
For reference, I use flask-socketio==5.4.1 on the server and python-socketio==5.11.4 on the client. They are compatible so the issue seems to be on caddy side.
2. Error messages and/or full log output:
{"level":"debug","ts":1729413823.2205856,"logger":"http.handlers.reverse_proxy","msg":"selected upstream","dial":"server:5000","total_upstreams":1}
{"level":"debug","ts":1729413823.2251806,"logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":"server:5000","duration":0.004468,"request":{"remote_ip":"192.168.65.1","remote_port":"25122","client_ip":"192.168.65.1","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/socket.io/?transport=websocket&EIO=4&t=1729413823.186603","headers":{"Sec-Websocket-Version":["13"],"Upgrade":["websocket"],"X-Forwarded-For":["192.168.65.1"],"X-Forwarded-Proto":["http"],"Origin":["http://localhost"],"Sec-Websocket-Key":["WQ8YIfX7kTZnQtoX+Wz+4Q=="],"Connection":["Upgrade"],"User-Agent":[""],"X-Forwarded-Host":["localhost"]}},"headers":{"Upgrade":["websocket"],"Connection":["Upgrade"],"Sec-Websocket-Accept":["rY2qxKxQMRpb2SQPtbKvqd+dA9w="]},"status":101}
{"level":"debug","ts":1729413823.2252693,"logger":"http.handlers.reverse_proxy","msg":"upgrading connection","upstream":"server:5000","duration":0.004468,"request":{"remote_ip":"192.168.65.1","remote_port":"25122","client_ip":"192.168.65.1","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/socket.io/?transport=websocket&EIO=4&t=1729413823.186603","headers":{"Sec-Websocket-Version":["13"],"Upgrade":["websocket"],"X-Forwarded-For":["192.168.65.1"],"X-Forwarded-Proto":["http"],"Origin":["http://localhost"],"Sec-Websocket-Key":["WQ8YIfX7kTZnQtoX+Wz+4Q=="],"Connection":["Upgrade"],"User-Agent":[""],"X-Forwarded-Host":["localhost"]}}}
{"level":"debug","ts":1729413823.2885013,"logger":"http.handlers.reverse_proxy","msg":"streaming error","upstream":"server:5000","duration":0.004468,"request":{"remote_ip":"192.168.65.1","remote_port":"25122","client_ip":"192.168.65.1","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/socket.io/?transport=websocket&EIO=4&t=1729413823.186603","headers":{"Sec-Websocket-Version":["13"],"Upgrade":["websocket"],"X-Forwarded-For":["192.168.65.1"],"X-Forwarded-Proto":["http"],"Origin":["http://localhost"],"Sec-Websocket-Key":["WQ8YIfX7kTZnQtoX+Wz+4Q=="],"Connection":["Upgrade"],"User-Agent":[""],"X-Forwarded-Host":["localhost"]}}}
{"level":"debug","ts":1729413823.2887127,"logger":"http.handlers.reverse_proxy","msg":"connection closed","upstream":"server:5000","duration":0.004468,"request":{"remote_ip":"192.168.65.1","remote_port":"25122","client_ip":"192.168.65.1","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/socket.io/?transport=websocket&EIO=4&t=1729413823.186603","headers":{"Sec-Websocket-Version":["13"],"Upgrade":["websocket"],"X-Forwarded-For":["192.168.65.1"],"X-Forwarded-Proto":["http"],"Origin":["http://localhost"],"Sec-Websocket-Key":["WQ8YIfX7kTZnQtoX+Wz+4Q=="],"Connection":["Upgrade"],"User-Agent":[""],"X-Forwarded-Host":["localhost"]}},"duration":0.063309333}
3. Caddy version:
v2.8.4 h1:q3pe0wpBj1OcHFZ3n/1nl4V4bxBrYoSoab7rL9BMYNk=
4. How I installed and ran Caddy:
a. System environment:
Server: Docker Desktop 4.29.0 (145265)
Engine:
Version: 26.0.0
API version: 1.45 (minimum version 1.24)
Go version: go1.21.8
OS/Arch: linux/arm64
Experimental: false
b. Command:
docker compose up
c. Service/unit/compose file:
services:
caddy:
container_name: "caddy"
build:
context: ./src/
dockerfile: Dockerfile
args:
APP_URL: http://localhost
BE_URL: server
docker image:
caddy:2.8.4-alpine
d. My complete Caddy config:
{
debug
admin :2019
servers {
metrics
}
}
# Remove http:// to enable TLS
{$APP_URL}
# Set this path to your site's directory.
root * /html/
route {
@notStatic {
path /api/* /socket.io/*
}
root * static/
reverse_proxy @notStatic {$BE_URL}:5000 {
flush_interval -1
stream_close_delay 5m
}
try_files {path} {path}.html html/{path}.html
file_server
}
log {
output file /var/log/access.log {
roll_size 150mb
roll_keep_for 48h
roll_keep 5
}
format json
level DEBUG
}
metrics /metrics