Spun up my own video node over the weekend
Over the weekend I brought up vdn.csylabs.com — my own video node. SRT in, HLS/WebRTC/RTMP out. My own domain, my own keys, my own logs.
The reason was straightforward: for both my own work and partner work, I needed a place where I could experiment freely — without someone else's control panel, without a monthly license, without waiting for someone to push a release.
Stack:
→ MistServer 3.10 Free_64 — SRT ingest on ports 9999 and 10000, output to HLS, WebRTC and RTMP
→ Caddy at the edge — TLS, redirects, basic access control for the admin panel
→ Ansible role for the rollout: variables in vault, one ansible-playbook run and the node is live
→ Own event log and fail2ban on top of systemd
Glass-to-glass latency lands around 1.5 seconds on the ffmpeg push → receiver → ffmpeg pull caller-mode chain. For live broadcast that's well within range.
The identifier is the key. I made Phase 0 auth as simple as possible. Each partner gets a stream identifier shaped like str_<12 hex> — 48 bits of entropy, not guessable, not snoopable. Whoever knows the identifier owns the channel.
Why this way. In Free_64, per-stream passwords aren't configurable — the password is shared at the connector level. So I moved all of the secrecy into the identifier itself. It isn't elegant, but it's predictable: if I need to revoke a key, I change the identifier, issue a new one, and the old one becomes irrelevant immediately.
For issuing keys I wrote a small CLI, vdn-stream.sh:
vdn-stream.sh gen # generate str_<12hex>
vdn-stream.sh add <id> <partner> # register a stream
vdn-stream.sh urls <id> # show push/pull/HLS URLs
vdn-stream.sh list # list active streams
The script pulls the admin password from ansible-vault (macOS Keychain), SSHes to the node, and hits the MistServer admin endpoint on 127.0.0.1:4242. That panel isn't exposed publicly — and shouldn't be: everything touching it rides through SSH.
What I found along the way:
MistServer won't accept an arbitrary identifier. My first push went to an unregistered id — the server politely rejected it: Push rejected - stream not configured. Free_64 requires explicit registration through addstream, no improvisation. For Phase 0 that's actually a feature: onboarding any partner becomes a single vdn-stream.sh add call, and nothing leaks into the system by accident.
Per-stream passwords aren't supported in Free_64. Commercial builds give every stream its own key; Free_64 gives one shared connector-level password. I thought about working around it with Caddy or iptables, but went the opposite way — pushed all the secrecy into the identifier. 48 bits of randomness isn't "password123"; brute force isn't on the table.
The admin panel is locked behind bcrypt through Caddy. But I have SSH. A hash doesn't reverse in one direction, so there's no need to reverse it. I SSH in and knock on 127.0.0.1:4242 directly. The CLI does exactly that, and I can poke it by hand any time — no need to expose the admin panel publicly.
Plan:
→ Week of April 25-26 — a streams page on ops.csylabs.com: table of active streams, one-click key generation, migration from a markdown file into a streaming.stream table
→ Next — automatic overlays on top of the signal: schedule on the input side, finished graphics on the output side. A live human operator is expensive; a good chunk of their work can run off triggers
→ The node is built from both sides: signal coming in from below, finished picture going out above. For partners, it's a replacement not just for delivery, but for a slice of manual post-production as well
More as it comes.