Skip to main content
Floe has two services, but your users do not need two addresses. Put both behind one reverse proxy and everything lives at https://floe.example.com. This is the recommended production layout. It means one certificate, one DNS record, one value to configure, and share links that work without any extra setup.

Route table

The client and the signaling server claim different paths, so they coexist on one origin with no conflicts. Send these paths to the signaling server and everything else to the client.
/ws is matched by exact string equality on the signaling server. A trailing slash or a path prefix will not match, and the connection is dropped with no error. If you proxy from a subpath, strip the prefix so the server still sees exactly /ws.

Proxy configuration

Caddy handles HTTPS certificates and WebSocket upgrades automatically, so the whole config is a handful of lines.

Floe configuration

Leave the socket URL empty. The browser then talks to whatever host it was loaded from, which behind this proxy is already the right answer.
NEXT_PUBLIC_SITE_URL is the only build-time value here. The published image cannot carry it, so canonical links and share previews are omitted rather than pointed somewhere wrong. See Container Images to build the client with your own domain baked in.
CLIENT_URL is matched exactly, including the scheme and with no trailing slash. https://floe.example.com and https://www.floe.example.com are different origins to the CORS check, so use whichever one your users actually visit.
TRUSTED_PROXY_COUNT must equal the number of proxy hops in front of the signaling server. One reverse proxy means 1. A CDN in front of that proxy means 2. Setting it higher than your real hop count lets clients forge X-Forwarded-For and slip past the per-IP rate limits.

Using the CLI with a one-domain instance

One address is all the CLI needs. The share link it prints resolves to the same origin, so it opens the web client correctly with no extra flag:
The --web flag only exists for split deployments where the client lives on a different hostname than the signaling server.

TURN does not go through the proxy

If you run the optional coturn relay, its ports stay directly exposed. TURN is not HTTP, so a reverse proxy cannot carry it. See TURN Relay for the port list and firewall rules.

Verify it works

Then open https://floe.example.com in a browser. The connection badge should read Ready. If it stays disconnected, the /socket.io/ route is the first thing to check.

Prefer two subdomains?

Splitting the client and server across app.your-domain.com and api.your-domain.com is still fully supported. See Production Deployment.