# How to Configure Nginx or Caddy Reverse Proxy with WebSocket Support for TREK

> Configure Nginx or Caddy reverse proxy for TREK to enable WebSocket support. Learn to set timeouts and body size limits for seamless operation.

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

---

**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)](https://github.com/mauriceboe/TREK/blob/main/wiki/Environment-Variables.md).

- **`FORCE_HTTPS`**: Forces HTTP to HTTPS redirects and enables HSTS. Set to `true` in production.
- **`TRUST_PROXY`**: Specifies the number of trusted proxy hops for Express to read the real client IP from `X-Forwarded-For`. Typically set to `1`.
- **`COOKIE_SECURE`**: Automatically enables the `Secure` flag on the `trek_session` cookie when `FORCE_HTTPS` is true or `NODE_ENV` is set to `production`.
- **`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)](https://github.com/mauriceboe/TREK/blob/main/wiki/Reverse-Proxy.md).

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

    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 when `FORCE_HTTPS` is 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.

```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 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)](https://github.com/mauriceboe/TREK/blob/main/server/src/websocket.ts)**: Implements the `/ws` endpoint 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)](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)](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 `/ws` for real-time collaboration; this endpoint must pass `Upgrade` and `Connection` headers.
- **Nginx Requirements**: Explicitly set `proxy_http_version 1.1`, forward upgrade headers, and configure `proxy_read_timeout 86400` and `client_max_body_size 500m`.
- **Caddy Simplicity**: Caddy auto-detects WebSocket upgrades; only `request_body max_size 500mb` is required.
- **Environment Variables**: Set `FORCE_HTTPS=true`, `TRUST_PROXY=1`, and `ALLOWED_ORIGINS` to 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)](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.