Running in production
One binary, one TOML file, two ports. Because it keeps no state on disk, most operational questions have short answers.
Configuration
| Key | Default | Meaning |
|---|---|---|
public_ip | 127.0.0.1 | The address put in every answer. Browsers reach it over UDP, so in production it is the machine's public IP. |
udp_port | 3478 | The single media port. Open it in the firewall; never proxy it. |
control_addr | 127.0.0.1:9300 | Where the HTTP API listens. Keep it on loopback behind soli-proxy. |
secret | The token secret. Prefer the environment variable. | |
allow_unauthenticated | false | Development only: accept unsigned dev.* tokens. |
audio_slots, video_slots | 8, 4 | Receive slots per person: how many voices and cameras one person can get at once. |
Environment overrides: SOLI_SFU_SECRET (or
SOLI_WEBHOOK_SECRET) and SOLI_SFU_PUBLIC_IP.
Logging follows RUST_LOG, by default
soli_sfu=info.
systemd
SIGTERM shuts down cleanly: the HTTP side stops, then the media thread finishes its turn and exits.
[Unit]
Description=soli-sfu media server
After=network-online.target
[Service]
ExecStart=/usr/local/bin/soli-sfu /etc/soli/sfu.toml
EnvironmentFile=/etc/soli/sfu.env
Environment=RUST_LOG=soli_sfu=info
Restart=on-failure
DynamicUser=yes
NoNewPrivileges=yes
# media is latency-sensitive
Nice=-5
[Install]
WantedBy=multi-user.targetsoli-proxy in front
Only the control plane goes through the proxy.
sfu.example.com -> http://127.0.0.1:9300
Do not put anything in the UDP path. Media goes from the browser to
public_ip:3478 directly; a proxy there breaks ICE and adds
latency.
Capacity
Forwarding costs bandwidth, not CPU. A group of n sends the
SFU n streams and receives n × (n − 1) back.
| Load | Audio only, ~40 kbps | Plus one camera, ~600 kbps |
|---|---|---|
| One group of 4 | ~0.5 Mbps out | ~2.3 Mbps out |
| One group of 8 | ~2.2 Mbps out | ~6.5 Mbps out |
| Ten groups of 6 | ~12 Mbps out | ~48 Mbps out |
A small VPS on a 1 Gbps port carries a whole company's office day.
When something is wrong
- No connection at all: the browser cannot reach
public_ip:udp_port. Check the firewall, and thatpublic_ipis right; it is what goes into the answer. - Audio one way only: check both people's
peersfirst, then the speaker's track inchrome://webrtc-internals. - More detail:
RUST_LOG=soli_sfu=debuglogs slot binding, keyframe requests and each session's lifecycle. - Who is connected:
GET /v1/statswith a token for the room you are looking at.