Installing and Running Slyber SFU Server in Docker

Updated:
Author: Erkin Khidirov

The fastest way to deploy Slyber SFU Server on any Linux server or local developer machine is to run the official container from the GitHub Container Registry. The prebuilt ghcr.io/slyber-app/slyber-sfu-server:latest image is automatically built for linux/amd64 and linux/arm64 CPU architectures on lightweight Alpine 3.20. Inside the image is the static binary /usr/local/bin/slyber_sfu, verified against the SHA256SUMS checksum. If you prefer installing directly on the host operating system without containers, go to Binary Installation and systemd Service Setup.

Quick One-Command Launch via Docker CLI

You do not need to clone the repository, install the Go compiler, or write configuration files manually. Copy and run the following command in your terminal. It pulls the latest image, automatically detects your server's external IP address, generates three isolated cryptographic keys, starts the container in the background, and immediately runs built-in node self-diagnostics.

Bash
docker pull ghcr.io/slyber-app/slyber-sfu-server:latest
docker rm -f slyber-sfu-server 2>/dev/null || true

PUBLIC_IP=$(curl -fsSL4 --max-time 2 api.ipify.org 2>/dev/null || echo 127.0.0.1)
JWT_SECRET=$(head -c 24 /dev/urandom | od -An -tx1 | tr -d ' \n')
NODE_SECRET=$(head -c 24 /dev/urandom | od -An -tx1 | tr -d ' \n')

docker run -d \
  --name slyber-sfu-server \
  --restart unless-stopped \
  --network host \
  -e SFU_ENV="production" \
  -e PUBLIC_IP="${PUBLIC_IP}" \
  -e SFU_UDP_PORT="4443" \
  -e SFU_TCP_PORT="4443" \
  -e SFU_HTTP_PORT="8090" \
  -e AUTH_MODE="jwt" \
  -e JWT_SECRET="${JWT_SECRET}" \
  -e NODE_SECRET="${NODE_SECRET}" \
  ghcr.io/slyber-app/slyber-sfu-server:latest && \
  sleep 1 && \
  docker exec slyber-sfu-server slyber_sfu doctor && \
  echo "Public IP  : ${PUBLIC_IP}" && \
  echo "JWT Secret : ${JWT_SECRET}" && \
  echo "Node Secret: ${NODE_SECRET}" && \
  echo "Test Token : $(curl -fsS -H "X-Slyber-Node-Secret: ${NODE_SECRET}" "http://127.0.0.1:8090/auth/token?room=test-room&user=user-1")"

Immediately after running the command, a green report from the slyber_sfu doctor utility and the generated secret keys will appear in the console, ready to copy into your backend configuration or the Slyber Inspector visual test bench.

How the Container Works Internally and Why It Is Secure

The official Docker image is engineered to production security standards.

  • Non-root execution. An isolated system group and user slyber_sfu with UID 10001 and interactive login disabled (/sbin/nologin) are created inside the container. The media server process never runs as root.
  • Binding privileged ports. During the image build, the binary /usr/local/bin/slyber_sfu is granted the targeted kernel capability cap_net_bind_service=+ep via setcap. This allows the unprivileged user to bind system ports below 1024 if needed (such as port 443 to traverse strict corporate proxies).
  • Single port for media traffic. Because the Pion WebRTC stack multiplexes all connections over a single port 4443, you only need to expose three ports in Docker (4443/udp, 4443/tcp, and 8090/tcp) without creating heavy iptables rules for tens of thousands of ports. On high-load Linux servers, you can also pass --network host instead of -p flags for direct host NIC access.

Launch Examples for Different Authentication Modes

Depending on your project's architecture, you can launch the container in one of three client token verification modes (for a detailed cryptographic breakdown, see Authentication and SFrame E2EE End-to-End Encryption).

1. Running in Secret or JWT Mode and Issuing Your First Token

This scenario is ideal for quick verification on a local machine or test server. We start the container and immediately request a ready-to-use token from the built-in /auth/token generator for user erkin in room test-room.

Bash
docker run -d \
  --name slyber_sfu_secret \
  -p 4443:4443/udp -p 4443:4443/tcp -p 8090:8090/tcp \
  -e PUBLIC_IP="127.0.0.1" \
  -e REALM="sfu.local" \
  -e SFU_UDP_PORT="4443" \
  -e SFU_TCP_PORT="4443" \
  -e SFU_HTTP_PORT="8090" \
  -e AUTH_MODE="secret" \
  -e TURN_SECRET="my-custom-sfu-turn-secret-2026" \
  -e JWT_SECRET="my-custom-sfu-jwt-secret-2026" \
  -e NODE_SECRET="my-custom-sfu-node-secret-2026" \
  ghcr.io/slyber-app/slyber-sfu-server:latest

# Issue ready-to-use tokens via the administrative endpoint
curl -s -H "X-Slyber-Node-Secret: my-custom-sfu-node-secret-2026" \
  "http://127.0.0.1:8090/auth/token?room=test-room&user=erkin"

2. Running with Redis on a Shared Docker Network

If you want to manage active sessions via a Redis database and immediately revoke participant access mid-call, create a shared Docker network and launch both containers using the commands below.

Bash
# 1. Create an isolated Docker network and start Redis
docker network create slyber_sfu_net
docker run -d --name slyber_sfu_redis --network slyber_sfu_net redis:alpine

# 2. Store a test session with a 3600-second TTL
docker exec slyber_sfu_redis redis-cli SET "slyber:session:tok_777" "erkin" EX 3600

# 3. Start Slyber SFU Server in redis mode
docker run -d \
  --name slyber-sfu-server \
  --network slyber_sfu_net \
  -p 4443:4443/udp -p 4443:4443/tcp -p 8090:8090/tcp \
  -e PUBLIC_IP="127.0.0.1" \
  -e REALM="sfu.local" \
  -e SFU_UDP_PORT="4443" \
  -e SFU_TCP_PORT="4443" \
  -e SFU_HTTP_PORT="8090" \
  -e AUTH_MODE="redis" \
  -e REDIS_ADDR="slyber_sfu_redis:6379" \
  -e NODE_SECRET="my-custom-sfu-node-secret-2026" \
  ghcr.io/slyber-app/slyber-sfu-server:latest

# 4. Verify that the SFU server can reach Redis and passes diagnostics
docker exec slyber-sfu-server slyber_sfu doctor

Container Management, Diagnostics, and Updates

Use standard Docker CLI commands for day-to-day maintenance of the running container.

Bash
# Check the binary version inside the image
docker run --rm ghcr.io/slyber-app/slyber-sfu-server:latest --version

# Run full self-diagnostics inside the running container
docker exec slyber-sfu-server slyber_sfu doctor

# View startup logs and cumulative packet statistics
docker logs -f slyber-sfu-server

# Check the server HTTP health endpoint
curl -i http://127.0.0.1:8090/healthz

Alternative Launch via Docker Compose

If your infrastructure manages services declaratively, you can use the ready-made docker-compose.yml template with host networking and automatic log rotation.

Code
services:
  slyber-sfu:
    image: ghcr.io/slyber-app/slyber-sfu-server:latest
    container_name: slyber-sfu-server
    restart: unless-stopped
    network_mode: host
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    ulimits:
      nofile:
        soft: 65535
        hard: 65535
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "3"
    environment:
      SFU_ENV: "${SFU_ENV:-production}"
      SFU_NODE_ID: "${SFU_NODE_ID:-slyber-sfu-01}"
      PUBLIC_IP: "${PUBLIC_IP:?Set PUBLIC_IP in .env}"
      REALM: "${REALM:-slyber.com}"
      DEFAULT_ROOM_PROFILE: "${DEFAULT_ROOM_PROFILE:-conference}"
      SFU_UDP_PORT: "${SFU_UDP_PORT:-4443}"
      SFU_TCP_PORT: "${SFU_TCP_PORT:-4443}"
      SFU_HTTP_PORT: "${SFU_HTTP_PORT:-8090}"
      ENABLE_ICE_TCP: "${ENABLE_ICE_TCP:-true}"
      SOCKET_BUFFER_BYTES: "${SOCKET_BUFFER_BYTES:-8388608}"
      EXTERNAL_TURN_URLS: "${EXTERNAL_TURN_URLS:-}"
      AUTH_MODE: "${AUTH_MODE:-jwt}"
      JWT_SECRET: "${JWT_SECRET:?Set JWT_SECRET (min 24 chars) in .env}"
      NODE_SECRET: "${NODE_SECRET:?Set NODE_SECRET (min 24 chars) in .env}"
      TURN_SECRET: "${TURN_SECRET:-}"
      ALLOWED_ORIGINS: "${ALLOWED_ORIGINS:-https://slyber.com}"
      CREDENTIAL_TTL_SEC: "${CREDENTIAL_TTL_SEC:-3600}"
      REQUIRE_E2EE: "${REQUIRE_E2EE:-false}"
      REDIS_ADDR: "${REDIS_ADDR:-127.0.0.1:6379}"
      MAX_KBPS_PER_TRACK: "${MAX_KBPS_PER_TRACK:-3500}"
      MAX_KBPS_PER_SESSION: "${MAX_KBPS_PER_SESSION:-10000}"
      ENABLE_SIMULCAST: "${ENABLE_SIMULCAST:-true}"
      ENABLE_SVC: "${ENABLE_SVC:-true}"
      VIDEO_CODECS: "${VIDEO_CODECS:-VP9,AV1,H264,VP8}"
      NACK_BUFFER_SIZE: "${NACK_BUFFER_SIZE:-512}"
      LAST_N_VIDEO_LIMIT: "${LAST_N_VIDEO_LIMIT:-16}"
      DYNACAST_ENABLED: "${DYNACAST_ENABLED:-true}"
      ENABLE_WHIP_WHEP: "${ENABLE_WHIP_WHEP:-true}"
      ENABLE_MOQ_RELAY: "${ENABLE_MOQ_RELAY:-false}"
      ENABLE_AI_GATEWAY: "${ENABLE_AI_GATEWAY:-true}"
      ENABLE_CASCADE_PIPE: "${ENABLE_CASCADE_PIPE:-true}"
      ENABLE_INSPECTOR: "${ENABLE_INSPECTOR:-true}"

Complete Environment Variables Reference

Network Stack and Node Identification

  • SFU_ENV sets the server operating mode (production enforces key length validation and a routable IP address, while development allows local startup without keys).
  • SFU_NODE_ID sets the unique server name in Prometheus metrics and cascading headers (default: slyber-sfu-01).
  • PUBLIC_IP sets the host's public IPv4 address that Pion WebRTC advertises in ICE candidates for browser connections (supports auto for automatic detection).
  • REALM sets the server's authentication domain zone (default: slyber.com).
  • DEFAULT_ROOM_PROFILE sets the default profile for newly created rooms (conference, roulette_1v1, broadcast, gaming, or ai_voice).
  • SFU_UDP_PORT and SFU_TCP_PORT set the unified port for receiving WebRTC media traffic over UDP and RFC 4571 TCP (default: 4443).
  • SFU_HTTP_PORT sets the TCP port for the WebSocket signaling gateway, WHIP/WHEP, and telemetry (default: 8090).
  • ENABLE_ICE_TCP enables or disables media transport over TCP (default: true).
  • ALLOW_PORT_FALLBACK allows the server to automatically bind the next available port on a port conflict (default: false).
  • SOCKET_BUFFER_BYTES sets the OS UDP socket read and write buffer size in bytes (default: 8388608 bytes, i.e., 8 MB).
  • EXTERNAL_TURN_URLS accepts a comma-separated list of external TURN servers to automatically issue temporary credentials to clients upon joining a room.

Security, Keys, and Redis Connection

  • AUTH_MODE selects the client token verification mode between jwt, redis, and secret.
  • JWT_SECRET sets the HMAC-SHA256 signing key for client tokens in jwt mode (minimum 24 characters in production).
  • TURN_SECRET sets the shared HMAC-SHA1 secret key for secret mode and generating passwords for external servers listed in EXTERNAL_TURN_URLS.
  • NODE_SECRET sets an isolated administrative key for accessing the /ai/ws, /cascade/, /auth/token, and /inspector/stats gateways via the X-Slyber-Node-Secret header.
  • ALLOWED_ORIGINS sets a comma-separated list of allowed domains for validating the Origin header in WebSocket and CORS requests.
  • ALLOW_INTERNAL_CASCADE allows internal IP addresses (RFC 1918 and loopback) in inter-server cascading (default: false to protect against SSRF attacks).
  • CREDENTIAL_TTL_SEC sets the lifetime of issued temporary tokens in seconds (default: 3600).
  • REQUIRE_E2EE enforces SFrame end-to-end encryption across all rooms on the node (default: false).
  • REDIS_ADDR, REDIS_USERNAME, REDIS_PASSWORD, and REDIS_DB configure connection parameters for the Redis server when using AUTH_MODE=redis.

Media Quality Control (QoS) and Gateways

  • MAX_KBPS_PER_TRACK and MAX_KBPS_PER_SESSION limit the maximum incoming bitrate of a single media track and an entire participant session in kilobits per second (defaults: 3500 and 10000).
  • ENABLE_SIMULCAST and ENABLE_SVC control support for multi-layer Simulcast video and scalable codec SVC filtering (default: true).
  • VIDEO_CODECS defines a comma-separated list of enabled video codecs (default: VP9,AV1,H264,VP8).
  • NACK_BUFFER_SIZE sets the packet ring buffer size per spatial layer for handling NACK retransmission requests (default: 512).
  • LAST_N_VIDEO_LIMIT sets the maximum number of simultaneously active video cameras in a conference room (default: 16).
  • DYNACAST_ENABLED enables automatic quality layer switching based on bandwidth estimation (BWE) feedback (default: true).
  • ENABLE_WHIP_WHEP, ENABLE_MOQ_RELAY, ENABLE_AI_GATEWAY, ENABLE_CASCADE_PIPE, and ENABLE_INSPECTOR enable or disable the respective server gateways (how each gateway works is covered in detail in WHIP and WHEP Gateways, AI Voice Pipeline, and Telemetry).