How to Configure Nginx or Caddy Reverse Proxy with WebSocket Support for TREK
To run TREK behind a reverse proxy, you must enable WebSocket upgrades on the /ws endpoint, set proxy_read_timeout to 86400 in Nginx (or rely on Caddy’s automatic handling), and increase body size limits to 500 MiB to support backup restores.
TREK relies on a persistent WebSocket connection at the /ws endpoint for real-time collaboration features. When placing TREK behind a TLS-terminating reverse proxy, you must ensure that Upgrade and Connection headers are forwarded correctly and that timeout settings accommodate long-lived connections. The application also requires specific environment variables to interpret forwarded headers and enforce secure cookies.
Environment Variables for Proxy Configuration
TREK reads several environment variables to function correctly behind a reverse proxy. These are documented in [wiki/Environment-Variables.md](https://github.com/mauriceboe/TREK/blob/main/wiki/Environment-Variables.md).
FORCE_HTTPS: Forces HTTP to HTTPS redirects and enables HSTS. Set totruein production.TRUST_PROXY: Specifies the number of trusted proxy hops for Express to read the real client IP fromX-Forwarded-For. Typically set to1.COOKIE_SECURE: Automatically enables theSecureflag on thetrek_sessioncookie whenFORCE_HTTPSis true orNODE_ENVis set toproduction.ALLOWED_ORIGINS: CORS whitelist for accepted origins. Set to your domain, e.g.,https://your.trek.domain.
Nginx Reverse Proxy Configuration
For Nginx, you must explicitly handle the WebSocket upgrade headers and extend the read timeout to prevent connection drops. The configuration is documented in [wiki/Reverse-Proxy.md](https://github.com/mauriceboe/TREK/blob/main/wiki/Reverse-Proxy.md).
# HTTP → HTTPS redirect (optional, but recommended)
server {
listen 80;
server_name trek.yourdomain.com;
return 301 https://$host$request_uri;
}
# TLS-enabled reverse-proxy
server {
listen 443 ssl http2;
server_name trek.yourdomain.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
# -------------------------------------------------
# WebSocket endpoint – /ws
# -------------------------------------------------
location /ws {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
# Keep the WS connection alive (24 h)
proxy_read_timeout 86400;
# Allow large backup-restore uploads
client_max_body_size 500m;
}
# -------------------------------------------------
# All other HTTP traffic
# -------------------------------------------------
location / {
proxy_pass http://localhost:3000;
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;
# Large uploads (e.g. backup restores)
client_max_body_size 500m;
}
}
Critical directives explained:
proxy_read_timeout 86400: Keeps the WebSocket connection alive for up to 24 hours, preventing timeouts during idle periods.client_max_body_size 500m: Lifts the default 1 MiB limit, which is required for backup restore archives that can exceed 500 MiB.X-Forwarded-Proto $scheme: Tells TREK whether the original request was HTTPS, enabling proper behavior whenFORCE_HTTPSis active.
Caddy Reverse Proxy Configuration
Caddy automatically handles WebSocket upgrades, making the configuration significantly simpler. You only need to specify the body size limit for large restores.
trek.yourdomain.com {
# Enable TLS (Caddy obtains/renews certs automatically)
tls you@example.com
# Large backup-restore payloads
request_body max_size 500mb
# Reverse-proxy all traffic to the TREK backend
reverse_proxy localhost:3000
}
If you prefer to terminate TLS elsewhere (e.g., at a load balancer), omit the tls block. Caddy will still correctly proxy WebSocket traffic to /ws without additional header configuration.
Core Implementation Details
Understanding the source files helps verify that your proxy configuration matches the application's expectations.
- [
server/src/websocket.ts](https://github.com/mauriceboe/TREK/blob/main/server/src/websocket.ts): Implements the/wsendpoint and logs the WebSocket server startup. This confirms the exact path (/ws) that requires proxying. - [
client/vite.config.js](https://github.com/mauriceboe/TREK/blob/main/client/vite.config.js): Contains the development proxy configuration for/ws, useful for debugging proxy behavior locally. - [
docker-compose.yml](https://github.com/mauriceboe/TREK/blob/main/docker-compose.yml): Demonstrates production-ready environment variable injection for TLS-ready deployments.
Summary
- WebSocket Path: TREK uses
/wsfor real-time collaboration; this endpoint must passUpgradeandConnectionheaders. - Nginx Requirements: Explicitly set
proxy_http_version 1.1, forward upgrade headers, and configureproxy_read_timeout 86400andclient_max_body_size 500m. - Caddy Simplicity: Caddy auto-detects WebSocket upgrades; only
request_body max_size 500mbis required. - Environment Variables: Set
FORCE_HTTPS=true,TRUST_PROXY=1, andALLOWED_ORIGINSto ensure TREK correctly handles secure cookies and client IPs.
Frequently Asked Questions
Why does TREK require WebSocket support on the /ws endpoint?
TREK implements real-time collaboration features through a persistent WebSocket connection handled in [server/src/websocket.ts](https://github.com/mauriceboe/TREK/blob/main/server/src/websocket.ts). Without proper WebSocket proxying, the application cannot synchronize data between clients.
What is the minimum client_max_body_size required for Nginx?
You must set client_max_body_size 500m (or higher) in Nginx. TREK’s backup and restore functionality handles archives that can be 500 MiB or larger, and the default 1 MiB limit will cause upload failures.
Does Caddy require manual WebSocket header configuration?
No. Caddy automatically detects the Upgrade: websocket header and handles the connection upgrade without manual proxy_set_header directives. You only need to configure the request_body max_size and reverse_proxy directives.
How does TREK enforce HTTPS when behind a reverse proxy?
When you set FORCE_HTTPS=true, TREK uses the X-Forwarded-Proto header to determine if the original request was HTTPS. If the header indicates HTTP, the application redirects to HTTPS and sets the Secure flag on session cookies.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →