* feat: add response compression middleware for HTTP responses Add compression middleware to Express server with SSE route exclusion and 1KB threshold. Reduces bandwidth for non-streaming API responses (history, sessions, files, static assets) by 60-80%. Closes #928 * fix: harden proxy compression and proxy docs --------- Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
8.0 KiB
8.0 KiB
Reverse Proxy Setup
Use this guide when running OpenChamber behind Nginx, Nginx Proxy Manager, Caddy, Cloudflare, or another reverse proxy.
Before you proxy it
- Confirm OpenChamber works directly first.
- Open
http://<server-ip>:3000or your custom port from the same network. - Only add the reverse proxy after the direct connection works.
What the proxy must support
- WebSockets for live message transport:
/api/event/ws/api/global/event/ws/api/terminal/ws
- SSE without buffering:
/api/event/api/global/event/api/notifications/stream/api/openchamber/events/api/terminal/:sessionId/stream
- Large request bodies for attachments and file operations
- Long-lived read timeouts for live streams and terminal sessions
Rules that matter
- Enable WebSocket proxying.
- Disable buffering on SSE routes.
- Disable gzip on the proxy if OpenChamber is already compressing responses.
- Keep compression enabled in only one layer.
- Forward normal proxy headers such as
Host,X-Forwarded-For, andX-Forwarded-Proto. - Increase body size limits if users upload files.
Quick checklist
- OpenChamber reachable directly on LAN
- WebSockets enabled in the proxy
- SSE routes have buffering off
gzip offon the proxy host, or proxy compression disabled another wayclient_max_body_sizelarge enough for attachmentsproxy_read_timeoutlong enough for streams
Example: Nginx
Show example config
client_max_body_size 50M;
client_body_buffer_size 50M;
proxy_request_buffering off;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
gzip off;
location = /api/terminal/ws {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location = /api/global/event/ws {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location = /api/event/ws {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location ~ ^/api/(event|global/event|notifications/stream|openchamber/events)$ {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Accept "text/event-stream";
proxy_set_header Cache-Control "no-cache";
proxy_buffering off;
proxy_cache off;
gzip off;
add_header X-Accel-Buffering "no" always;
add_header Cache-Control "no-cache, no-transform" always;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location ~ ^/api/terminal/.+/stream$ {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Accept "text/event-stream";
proxy_set_header Cache-Control "no-cache";
proxy_buffering off;
proxy_cache off;
gzip off;
add_header X-Accel-Buffering "no" always;
add_header Cache-Control "no-cache, no-transform" always;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location /api {
proxy_pass http://127.0.0.1:3000;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location / {
proxy_pass http://127.0.0.1:3000;
}
Example: Nginx Proxy Manager
Show Advanced tab example
client_max_body_size 50M;
client_body_buffer_size 50M;
proxy_request_buffering off;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
gzip off;
location = /api/terminal/ws {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_connect_timeout 30s;
}
location = /api/global/event/ws {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_connect_timeout 30s;
}
location = /api/event/ws {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_connect_timeout 30s;
}
location = /api/event {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Accept "text/event-stream";
proxy_set_header Cache-Control "no-cache";
proxy_buffering off;
proxy_cache off;
gzip off;
add_header X-Accel-Buffering "no" always;
add_header Cache-Control "no-cache, no-transform" always;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_connect_timeout 30s;
}
location = /api/global/event {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Accept "text/event-stream";
proxy_set_header Cache-Control "no-cache";
proxy_buffering off;
proxy_cache off;
gzip off;
add_header X-Accel-Buffering "no" always;
add_header Cache-Control "no-cache, no-transform" always;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_connect_timeout 30s;
}
location = /api/notifications/stream {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Accept "text/event-stream";
proxy_set_header Cache-Control "no-cache";
proxy_buffering off;
proxy_cache off;
gzip off;
add_header X-Accel-Buffering "no" always;
add_header Cache-Control "no-cache, no-transform" always;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_connect_timeout 30s;
}
location = /api/openchamber/events {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Accept "text/event-stream";
proxy_set_header Cache-Control "no-cache";
proxy_buffering off;
proxy_cache off;
gzip off;
add_header X-Accel-Buffering "no" always;
add_header Cache-Control "no-cache, no-transform" always;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_connect_timeout 30s;
}
location ~ ^/api/terminal/.+/stream$ {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Accept "text/event-stream";
proxy_set_header Cache-Control "no-cache";
proxy_buffering off;
proxy_cache off;
gzip off;
add_header X-Accel-Buffering "no" always;
add_header Cache-Control "no-cache, no-transform" always;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_connect_timeout 30s;
}
location /api {
proxy_pass http://127.0.0.1:3000;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_connect_timeout 30s;
}
location / {
proxy_pass http://127.0.0.1:3000;
}
Also enable Websockets Support in Nginx Proxy Manager for this host.
Common failure signs
Page loads, but sending messages fails
- WebSockets are not enabled in the proxy
/api/event/wsor/api/global/event/wsis not passing through correctly
Notifications or live status do not update
- one of the SSE routes is buffered or cached
X-Accel-Buffering "no"is missing
File uploads fail
client_max_body_sizeis too small
Everything works locally, but breaks only behind the proxy
- the proxy is compressing and buffering live traffic
- the proxy is missing WebSocket support
Website docs
- Website version:
packages/docs/content/docs/reverse-proxy.mdx