soli-sfu

Running in production

One binary, one TOML file, two ports. Because it keeps no state on disk, most operational questions have short answers.

Configuration

KeyDefaultMeaning
public_ip127.0.0.1The address put in every answer. Browsers reach it over UDP, so in production it is the machine's public IP.
udp_port3478The single media port. Open it in the firewall; never proxy it.
control_addr127.0.0.1:9300Where the HTTP API listens. Keep it on loopback behind soli-proxy.
secretThe token secret. Prefer the environment variable.
allow_unauthenticatedfalseDevelopment only: accept unsigned dev.* tokens.
audio_slots, video_slots8, 4Receive 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.target

soli-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.

LoadAudio only, ~40 kbpsPlus 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 that public_ip is right; it is what goes into the answer.
  • Audio one way only: check both people's peers first, then the speaker's track in chrome://webrtc-internals.
  • More detail: RUST_LOG=soli_sfu=debug logs slot binding, keyframe requests and each session's lifecycle.
  • Who is connected: GET /v1/stats with a token for the room you are looking at.