# How to Set Up a Reverse Proxy with WebSocket Support for TREK Production Deployments

> Set up TREK with a reverse proxy and WebSocket support for production. Learn to configure Nginx or Caddy for secure, scalable deployments including WebSocket upgrades and large body limits.

- Repository: [Maurice/TREK](https://github.com/mauriceboe/TREK)
- Tags: how-to-guide
- Published: 2026-07-11

---

**To deploy TREK behind a reverse proxy, you must configure WebSocket upgrades for the `/ws` endpoint and increase the body size limit to at least 500 MiB to support backup-restore operations.**

TREK is a real-time collaboration platform that requires a persistent WebSocket connection for live features. When running production deployments behind Nginx or Caddy, proper proxy configuration ensures the Express application receives the correct headers and maintains long-lived connections. This guide covers the exact environment variables and proxy directives required based on the TREK source code.

## Understanding TREK's WebSocket Requirements

TREK exposes its real-time collaboration layer at the **`/ws`** endpoint implemented in [`server/src/websocket.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/websocket.ts). The application expects the reverse proxy to handle transport-layer security while preserving the connection characteristics needed for WebSocket handshakes.

### The /ws Endpoint

The WebSocket handler requires HTTP/1.1 protocol upgrades to remain persistent. Unlike standard HTTP requests, these connections must stay open for extended periods—up to 24 hours in production environments—to maintain real-time synchronization between clients.

### Large Payload Handling

Backup and restore operations in TREK transmit archives that can exceed **500 MiB**. The default proxy body size limits (typically 1 MiB in Nginx) will block these operations unless explicitly raised.

## Required Environment Variables

TREK reads specific environment variables to adapt its behavior behind a TLS-terminating proxy. Configure these in your production environment or [`docker-compose.yml`](https://github.com/mauriceboe/TREK/blob/main/docker-compose.yml):

| Variable | Purpose | Production Value |
|----------|---------|------------------|
| `FORCE_HTTPS` | Enables HTTP to HTTPS redirects and HSTS headers | `true` |
| `TRUST_PROXY` | Sets trusted hop count for Express to read real client IP from `X-Forwarded-For` | `1` |
| `COOKIE_SECURE` | Sets `Secure` flag on `trek_session` cookie (auto-enabled when `FORCE_HTTPS` or `NODE_ENV=production` is set) | `true` |
| `ALLOWED_ORIGINS` | CORS whitelist for cross-origin requests | `https://your.trek.domain` |

These variables are documented in [[`wiki/Environment-Variables.md`](https://github.com/mauriceboe/TREK/blob/main/wiki/Environment-Variables.md)](https://github.com/mauriceboe/TREK/blob/main/wiki/Environment-Variables.md).

## Nginx Configuration for TREK

The following configuration handles TLS termination, WebSocket proxying, and large file uploads. Key directives include `proxy_read_timeout 86400` to keep connections alive and `client_max_body_size 500m` for backup operations.

```nginx

# 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;

    # Paths to your TLS certificate and private key

    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;
    }
}

```

According to the [[`wiki/Reverse-Proxy.md`](https://github.com/mauriceboe/TREK/blob/main/wiki/Reverse-Proxy.md)](https://github.com/mauriceboe/TREK/blob/main/wiki/Reverse-Proxy.md) documentation, the `X-Forwarded-Proto $scheme` header is critical for TREK's `FORCE_HTTPS` logic to determine the original request protocol.

## Caddy Configuration for TREK

Caddy automatically handles WebSocket upgrades, making the configuration significantly shorter. You only need to specify the body size limit and upstream address.

```caddy
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 terminate TLS upstream in a load balancer, omit the `tls` directive while keeping the `request_body` limit to ensure backup-restore functionality remains intact.

## Key Implementation Files

Understanding these source files helps debug proxy configuration issues:

- **[`server/src/websocket.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/websocket.ts)** – Implements the `/ws` endpoint and defines the WebSocket path used by the proxy.
- **[`client/vite.config.js`](https://github.com/mauriceboe/TREK/blob/main/client/vite.config.js)** – Contains development proxy settings for `/ws` that mirror production requirements.
- **[`docker-compose.yml`](https://github.com/mauriceboe/TREK/blob/main/docker-compose.yml)** – Demonstrates production environment variable injection for TLS-ready deployments.
- **[`wiki/Reverse-Proxy.md`](https://github.com/mauriceboe/TREK/blob/main/wiki/Reverse-Proxy.md)** – Official documentation with additional Nginx and Caddy examples.

## Summary

- **WebSocket support** requires forwarding `Upgrade` and `Connection` headers with extended timeouts (24 hours) for the `/ws` endpoint.
- **Body size limits** must be set to at least 500 MiB in both Nginx (`client_max_body_size`) and Caddy (`request_body max_size`) to handle backup-restore operations.
- **Environment variables** including `FORCE_HTTPS`, `TRUST_PROXY`, and `ALLOWED_ORIGINS` must be configured so TREK trusts the proxy and generates secure cookies.
- **Header forwarding** via `X-Forwarded-Proto` and `X-Forwarded-For` ensures TREK correctly identifies client IPs and protocol schemes.

## Frequently Asked Questions

### Why does TREK require a 24-hour proxy timeout?

TREK maintains persistent WebSocket connections for real-time collaboration features. The `proxy_read_timeout 86400` directive in Nginx (or equivalent in Caddy) prevents the proxy from closing idle connections, ensuring users stay synchronized without frequent reconnections.

### Can I use a different body size limit than 500 MiB?

While you can adjust the limit, 500 MiB is the recommended minimum based on the backup-restore archive sizes supported by TREK. Setting this lower in `client_max_body_size` or `request_body` will cause HTTP 413 errors when users attempt to restore large project archives.

### How does TREK handle HTTPS behind a reverse proxy?

When `FORCE_HTTPS` is set to `true`, TREK relies on the `X-Forwarded-Proto` header to determine if the original request used HTTPS. This header must be forwarded by your proxy (as shown in the Nginx example) to trigger HSTS headers and secure cookie flags correctly.

### Does Caddy require explicit WebSocket headers?

No. Caddy automatically detects WebSocket upgrade requests and handles the `Upgrade` and `Connection` headers internally. You only need to ensure the `request_body max_size` is configured for large uploads, making Caddy configurations significantly shorter than Nginx equivalents.