arrow_back Back to open·broadcast
terminal Self-hosting guide

Run it yourself

open·broadcast is open-core: the receiver, encoder and bonding router are free software under AGPL-3.0. Everything the hosted service runs, you can run on your own VPS — the encoder ⇄ receiver contract is identical either way. This guide gets a receiver taking a bonded feed and fanning it out to your destinations.

engineering

This is a technical setup for broadcast engineers — you'll need a Linux VPS, Docker, and comfort on the command line. Community support is on GitHub; there's no hand-holding tier (that's what the hosted service will be for).

How it fits together

Your encoder sends one bonded RIST feed — multiple WAN uplinks presented as RIST peers on a single port — to a receiver you run. The receiver does a copy-only fan-out (no re-encode) to your destinations (RTMP/RTMPS/SRT/RIST). A bonding router is optional but is what turns several cheap uplinks into one resilient link.

# encoder ──▶ [bonding router] ──▶ your receiver (VPS) ──▶ RTMP · SRT · RIST
1

Run the receiver

The receiver is a headless C++ service. The quickest path is the published container image; it idles until an encoder (or curl) starts a session.

docker run -d --name obr-receiver --restart unless-stopped \ -p 8080:8080 -p 5000:5000/udp \ -e OBR_TOKEN="$(openssl rand -hex 32)" \ -e OBR_PSK="$(openssl rand -hex 16)" -e OBR_PSK_AES=256 \ ghcr.io/patcarter883/open-broadcast-receiver:latest
lock

The control port speaks plain HTTP inside the container. Put nginx/Caddy with TLS in front of :8080, or firewall it to your management network. Secrets never travel in URLs — tokens and PSKs go in headers and dedicated fields only.

Prefer to build from source (or read every flag)? See the receiver README — CMake ≥ 3.28, GStreamer ≥ 1.28, vendored librist.

2

Point an encoder at it

Run the open·broadcast encoder (branch v2, FLTK desktop app) on the source machine. Give it your receiver's control URL and OBR_TOKEN, take NDI / SDP / MPEG-TS in, and it drives the receiver over the same REST contract the hosted service uses. Any RIST-ADVANCED sender that speaks the contract works too.

3

Bond your uplinks (optional but recommended)

To bond several WANs (Starlink + LTE + fixed), run luci-app-rist2rist on an OpenWrt router: one RIST feed in, one RIST peer out per WAN interface. The receiver sees the paths as bonded peers on the session port and rides out any one of them dropping — no reconnect. Without a bonding router you can still send over a single link; you just lose the resilience.

4

Start a stream

The encoder does this for you, but here it is directly — POST /start (schema 2):

curl -X POST https://your-receiver:8080/start \ -H "Authorization: Bearer $OBR_TOKEN" \ -H 'Content-Type: application/json' \ -d '{ "schema_version": 2, "session_id": "demo-1", "ingest": { "bandwidth": 8000 }, "source": { "codec": "h264" }, "outputs": [ { "id": "yt", "type": "rtmp", "url": "rtmp://a.rtmp.youtube.com/live2", "key_or_streamid": "YOUR-STREAM-KEY" } ] }' # watch it: /status and /stats (per-peer bond telemetry); stop with POST /stop

Outputs reconnect forever with backoff, so a platform ingest hiccup mid-event heals without you touching anything. Destination validation blocks private IP ranges by default (SSRF hygiene); opt out with --egress-allow-private if you restream to your own LAN.

The repositories

dns
open-broadcast-receiver
Headless RIST receiver → copy-only fan-out to RTMP/RTMPS/SRT/RIST.
videocam
open-broadcast-encoder
FLTK encoder (branch v2) — NDI/SDP/MPEG-TS in, bonded RIST out.
router
luci-app-rist2rist
OpenWrt bonding hop — one RIST in, one RIST peer out per WAN.
description
CONTRACT.md
The wire contract the encoder and receiver share — hosted or self-hosted.
balance

All first-party code is AGPL-3.0-or-later. If you run a modified receiver as a network service, the licence's network clause applies — share your changes.