# TrueNAS deploy — datarhei Core (M2, WebRTC-in-Core) Host-networked Docker stack that runs the real root Core binary with the M2 WebRTC egress subsystem wired in. This replaces the M1 `webrtc-poc` stack — WebRTC is now a first-class output alongside RTMP/SRT/HLS. ## What changed from M1 | M1 (webrtc-poc) | M2 (this stack) | | -------------------------------------- | -------------------------------------------- | | Standalone `cmd/webrtc-poc` binary | Full Core with restream, HTTP API, storage | | One hard-coded stream id | Every restream process can opt into WebRTC | | Single UDP ingest, PT-split forwarding | Two UDP ports per process, per-track | | Plain `/whep/:id` on a side port | `/api/v3/whep/:id` on the JWT-protected API | | No auth | JWT (same creds as the rest of Core) | ## Prereqs - Docker on the TrueNAS host (TrueNAS SCALE includes it) - LAN or public IP that clients can reach (set in `.env` as `PUBLIC_IP`) - Admin credentials for Core's API - FFmpeg is bundled in the image — no host install required ## One-time setup ``` sudo mkdir -p /mnt/NVME/Docker/dragonfork-core cd /mnt/NVME/Docker/dragonfork-core # Pull the repo (or sync deploy files) onto the host. The compose # build `context:` points at the repo root. git clone https://forgejo.wilddragon.net/zgaetano/datarhei-dragonfork-core.git cd datarhei-dragonfork-core/deploy/truenas/core cat > .env <:8080/` | The full Restreamer UI (rebranded "Wild Dragon"). Manage processes, configure ingests, set up RTMP/SRT/HLS outputs, view logs. The standard Datarhei admin experience. | | `http://:8080/wilddragon-webrtc.html` | Wild Dragon WebRTC admin. Sign in, pick a process, click "Enable WebRTC". The page restarts the process so the new RTP output legs go live, then surfaces the WHEP URL with a one-click jump to the smoke player. **The fastest path from "I want WebRTC on this stream" to "the smoke player is rendering it."** | | `http://:8080/whep-player.html` | Standalone WHEP subscriber (the smoke player). ICE / codec / bitrate diagnostics, JWT input, shareable URLs. Use to verify WebRTC actually works after enabling it. | | `http://:8080/api/swagger/index.html` | Swagger API docs. Same auth. Hit the WHEP endpoints directly when scripting. | The Restreamer UI doesn't (yet) have a WebRTC checkbox in its process editor — that's why the standalone admin page exists. A proper UI fork that adds WebRTC controls inline is tracked in issue #15. ## End-to-end smoke test ``` 1. Open http://:8080/ (Restreamer UI). Sign in with admin / . 2. Create a new "Source" with type RTMP. Note the RTMP push URL it shows. 3. Push your test source to that URL (OBS, ffmpeg, etc.). Confirm it shows "running" in the UI. 4. Open http://:8080/wilddragon-webrtc.html. Sign in with the same creds. 5. Click "Enable WebRTC" on the process you just created. 6. Click the "open ↗" link next to the WHEP URL to load the smoke player. 7. Click "Subscribe" in the smoke player. Within ~1s you should see your RTMP source rendering as WebRTC. ``` If step 7 hangs, the most common cause is `PUBLIC_IP` in `.env` not matching what the browser can actually reach (host firewall, wrong LAN IP, etc.). Check the WHEP smoke player's log panel — it'll surface the ICE state transitions. ## Smoke-test via API directly ``` # Issue a JWT against the admin creds from .env: TOKEN=$(curl -s -X POST -H 'Content-Type: application/json' \ -d '{"username":"admin","password":""}' \ http://10.0.0.25:8080/api/login | jq -r '.access_token') # Probe the WHEP endpoint — should 404 for an unknown id. curl -i -H "Authorization: Bearer $TOKEN" \ -X POST http://10.0.0.25:8080/api/v3/whep/nope # → HTTP/1.1 404 Not Found # Create a process with WebRTC enabled, send RTMP to its input, then # subscribe the Pion whep-client to /api/v3/whep/. ``` ## Cutting over from the M1 PoC The M1 `webrtc-poc` stack is independent; it binds its own ports. You can run both side-by-side during the cutover: ``` # Stop the M1 stack when you're ready to retire it: cd /mnt/NVME/Docker/dragonfork-webrtc-poc docker compose down ``` ## Teardown ``` docker compose down ``` ## Security notes - The WHEP endpoint is mounted under `/api/v3`, which is JWT-protected. That's the M2 posture — WHEP clients (browsers) need a token. M3 adds per-process signed-URL tokens so embeds don't require admin credentials. - The binary runs as root inside the container; if you need an unpriv user, mount volumes owned by a fixed UID and add a `user:` directive. This matches how the upstream datarhei/core image ships. - Put Caddy or nginx in front for TLS. The media itself is DTLS-SRTP-encrypted regardless. - The Wild Dragon WebRTC admin page (`/wilddragon-webrtc.html`) talks to the same JWT-protected API. The token is held in `localStorage` and cleared when you click "Sign out". If you've configured Core's API to require auth — which you should — this page is gated by it.