Use your own proxy
By default, Fluxer uses ports 80 and 443 and gets its own certificate from Let's Encrypt. If another web server on the machine already uses those ports, Fluxer can serve plain HTTP on a local port for your proxy to forward to.
Serve plain HTTP for your proxy
Section titled “Serve plain HTTP for your proxy”rexctl proxy onFluxer then listens on 127.0.0.1:8080. Pass --bind to rexctl proxy on to use another address or port.
rexctl proxy on --bind 127.0.0.1:8081On a new machine, pass --behind-proxy to rexctl install to start in this mode.
Go back to HTTPS
Section titled “Go back to HTTPS”rexctl proxy offFluxer goes back to serving HTTPS with its own certificate, and ports 80 and 443 need to be open to the machine again.
Run the proxy on another machine
Section titled “Run the proxy on another machine”Bind an address the proxy machine can connect to, and only let the proxy connect to that port.
rexctl proxy on --bind 10.0.0.5:8080By default, Fluxer trusts X-Forwarded-For only from private addresses. If the proxy connects from a public address, set edge.trusted_proxies to that address, which replaces the default.
rexctl config set edge.trusted_proxies 203.0.113.10Until you do, everyone who uses your instance shows up with your proxy's address, and they share its rate limits and bans.
What your proxy needs to do
Section titled “What your proxy needs to do”- Serve your domain over HTTPS with TLS 1.2 and TLS 1.3 turned on, because video playback in the mobile apps needs TLS 1.2.
- Forward WebSocket connections.
- Set
X-Forwarded-Forto the address the request came from, and drop any value the visitor sent. - Accept request bodies of at least 512 MB for uploads.
- Keep idle connections open for an hour.
- Don't add a
Content-Security-Policyheader, because Fluxer sends its own. - Forward every path and query string unchanged.
- Use
/_healthas the health check if your proxy has one.
map $http_upgrade $connection_upgrade { default upgrade; '' close;}
server { listen 80; listen [::]:80; server_name chat.example.com; return 301 https://$host$request_uri;}
server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name chat.example.com;
ssl_certificate /etc/letsencrypt/live/chat.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/chat.example.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3;
client_max_body_size 512m;
location / { proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1;
proxy_set_header Host $host; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header X-Forwarded-For $remote_addr;
proxy_read_timeout 3600s; proxy_send_timeout 3600s; proxy_request_buffering off; proxy_buffering off; }}Don't change $remote_addr to $proxy_add_x_forwarded_for, which keeps the value the visitor sent and lets anyone pretend to come from another address.
chat.example.com { reverse_proxy 127.0.0.1:8080}Caddy's defaults do everything in the list above, and Caddy gets a certificate for your domain itself.
Cloudflare
Section titled “Cloudflare”If Cloudflare proxies your domain, change these settings in the Cloudflare dashboard.
- Turn Rocket Loader off, because the web app shows a blank page with it on.
- Don't let a Cache Rule store HTML pages, or people get an old version of the web app after you upgrade.
- Turn Bot Fight Mode off and don't add challenges for
/api/,/gatewayor/livekit/. The desktop and mobile apps can't solve a challenge. - Set the SSL/TLS encryption mode to "Full (strict)".
Purging deleted media
Section titled “Purging deleted media”Cloudflare keeps serving cached copies of media after someone deletes it, until the cached copy expires. Fluxer can ask Cloudflare to purge those copies right away. Create an API token with the Zone Cache Purge permission for your zone, find the zone ID on the zone's overview page, and set these variables.
rexctl config set FLUXER_CACHE_PURGE_ADAPTER httprexctl config set FLUXER_CACHE_PURGE_HTTP_ENDPOINT https://api.cloudflare.com/client/v4/zones/<zone id>/purge_cacherexctl config set FLUXER_CACHE_PURGE_HTTP_TOKEN <api token>Fluxer sends at most 100 prefixes per request, which is the most Cloudflare accepts. See Environment variables for the other cache purge settings.
Voice and video
Section titled “Voice and video”Call audio and video don't go through your proxy. They connect directly to the machine on TCP port 7881 and UDP port 7882, and both ports need to be open. A tunnel such as Cloudflare Tunnel can't forward them.
Extra voice servers on this machine from rexctl voice add use paths on your domain, such as /livekit-default-server-2/. A proxy that forwards every path already passes them. Their media ports skip the proxy too. Open each server's TCP and UDP port as well.
Voice behind a tunnel
Section titled “Voice behind a tunnel”If you only serve Fluxer through a tunnel, calls need a TURN server. It relays call media between people's devices and LiveKit. Run one on a machine with a public address, such as coturn on a small VPS, and open its port there, usually UDP port 3478.
Then give LiveKit the relay as a JSON array in FLUXER_LIVEKIT_TURN_SERVERS.
rexctl config set FLUXER_LIVEKIT_TURN_SERVERS '[{"host":"turn.example.com","port":3478,"protocol":"udp","username":"fluxer","credential":"a-long-password"}]'Without rexctl, put the same value in .env between single quotes and run docker compose up -d.
LiveKit hands the relay to browsers and apps when they join a call, and they use it when they can't connect to LiveKit directly. Voice servers that rexctl adds or joins hand out the same relays. See TURN servers. Keep FLUXER_LIVEKIT_USE_EXTERNAL_IP at true so LiveKit tells them its public address. LiveKit opens the path to the relay from its own side, which most routers let through without open ports. If calls still don't connect, your router probably blocks this and you need to open TCP port 7881 and UDP port 7882 after all.
On Kubernetes, add the relay to livekit.extraConfig in your values file.
livekit: extraConfig: rtc: turn_servers: - host: turn.example.com port: 3478 protocol: udp username: fluxer credential: a-long-password