NEXT_PUBLIC_SOCKET_URL | client (runtime) | No | http://localhost:3001 | URL the browser uses to reach the signaling server. Read at runtime, so changing it needs only docker compose up -d, no rebuild. Set it empty when both services share one origin behind a reverse proxy; the browser then uses its own. See how the client finds the server. |
FLOE_IMAGE_TAG | compose | No | latest | Which published image tag to run, for example 1.9.1, 1.9, main, or sha-fed7ebb. See Container Images. Not to be confused with FLOE_VERSION, which belongs to the CLI installer and carries a leading v. |
NEXT_PUBLIC_SITE_URL | client (build) | No | (none) | Canonical public origin of your client (e.g. https://app.your-domain.com), used for canonical, Open Graph, JSON-LD, and sitemap URLs. Inlined at build time, so the published image cannot carry it and omits those tags instead of claiming floe.one. Set it only when building the client yourself. |
PORT | server | No | 3001 | Host port the signaling server is published on. Inside the container it always listens on 3001; Docker Compose maps ${PORT} to it. Change this and you must also update NEXT_PUBLIC_SOCKET_URL and rebuild the client, or browsers keep dialing the old port. |
CLIENT_PORT | client | No | 3000 | Host port the web client is published on. Inside the container it always listens on 3000. Compose-only; it has no effect outside Docker. |
NODE_ENV | server | No | development | Standard Node.js runtime flag. The Docker image sets this to production for you, so this default only applies when you run the server directly with Node. Set it to production if you do: Express only suppresses stack traces in its built-in error responses when the value is exactly production, and blank counts as unset. |
CLIENT_URL | server | Yes (prod) | (none) | Frontend origin allowed by CORS. Matched exactly, including scheme and with no trailing slash. Use https://floe.example.com for a one-domain deployment, or https://app.your-domain.com when the client has its own subdomain. |
TRUSTED_PROXY_COUNT | server | No | 1 | Number of trusted reverse-proxy hops in front of the server, used for correct X-Forwarded-For parsing and per-IP rate limiting. Use 1 behind a single reverse proxy, 2 behind a proxy plus a CDN, and 0 when the server is exposed directly with no proxy. Docker Compose passes 0 explicitly, because publishing container ports directly is its default. Setting it above your real hop count lets clients forge X-Forwarded-For and bypass the rate limits, so set it to 0 deliberately rather than leaving it unset on a directly exposed host. |
MAX_CONNECTIONS_PER_IP | server | No | 30 | Maximum new connections allowed per IP per 60-second window, shared across Socket.IO and WebSocket. Raise this in staging or test environments that drive many connections from a single IP. |
MAX_TURN_REQUESTS_PER_IP | server | No | 20 | Maximum GET /api/turn-credentials requests per IP per 60-second window. Requests over the cap get 429, and the client silently falls back to STUN-only. Raise this in CI or staging suites that start many transfers from one IP. |
MAX_CODE_REQUESTS_PER_IP | server | No | 60 | Maximum requests per IP per 60-second window against the room-code endpoints, shared across POST /api/code and GET /api/code/:code. Requests over the cap get 429. Raise this in CI or staging suites that mint many codes from one IP. |
MAX_ACTIVE_CODES | server | No | 10000 | Maximum number of simultaneously-live room codes. Once this cap is reached, POST /api/code returns 503 until existing codes expire (10-minute TTL) or are consumed. Bounds memory use of the code registry; raise it only if you legitimately expect more than ten thousand pending transfers at once. |
CLOUDFLARE_TURN_KEY_ID | server | No | (none) | Turn Token ID of a Cloudflare Realtime TURN key. With the API token below, the server mints short-lived TURN credentials from Cloudflare’s managed network, so you need no public IP, extra ports, or TLS certificates. Takes precedence over the coturn variables. |
CLOUDFLARE_TURN_KEY_API_TOKEN | server | No | (none) | API token that pairs with CLOUDFLARE_TURN_KEY_ID. Keep it secret. |
TURN_SECRET | server | No | (none) | Shared HMAC secret for self-hosted coturn credentials, used only when the Cloudflare variables are unset. If no TURN option is configured, the server returns STUN-only and no relay is offered. Must match coturn’s static-auth-secret. |
TURN_DOMAIN | server | No | (none) | Public hostname of your self-hosted TURN server (e.g. turn.your-domain.com). Must match coturn’s realm. |
UPSTASH_REDIS_REST_URL | server | No | (none) | REST URL of an Upstash Redis database, used to durably persist the global transfer counter shown on the homepage. If empty, the counter runs in memory only and resets to 0 on every restart. |
UPSTASH_REDIS_REST_TOKEN | server | No | (none) | REST token that pairs with UPSTASH_REDIS_REST_URL. Both must be set together for durable stats. Use the read+write token (the default one in the Upstash console), not the read-only token. The server needs write access to increment the counter; with a read-only token, writes are silently rejected and the total never persists. |
MAX_REPORT_BYTES | server | No | 5497558138880 (5 TB) | Maximum bytes accepted in a single POST /api/stats/report request. Rejects implausibly large single-transfer reports. |