- README: update architecture diagram for RTMP+FFmpeg pipeline, add FFmpeg install step, fix path descriptions - obs-setup: switch from WHIP to RTMP output, add FFmpeg prerequisite, fix script log messages (MediaMTX starts on load not streaming start), add Python setup note, update troubleshooting for game-opus path and audio - npm-setup: remove Custom Locations GUI instructions (must be empty - all locations defined in Advanced tab only), update verify steps to game-opus paths, add troubleshooting for WHEP 400/401 causes - authentik-setup: add section 6 covering both manual account creation and self-service enrollment via invite link; clarify User Write stage group field is what triggers auto-add (not the invitation form) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4.4 KiB
Nginx Proxy Manager setup
Configures NPM to:
- Serve
https://stream.hetherman.cloudwith TLS + Authentik forward auth, reverse-proxying HTTP traffic to the Windows gaming PC. - Forward public UDP 48189 (WebRTC media) to the gaming PC via an NPM Stream (L4 UDP proxy).
Replace <PC-LAN-IP> with the LAN IP of the Windows gaming PC
(e.g., 192.168.50.254).
1. DNS
Create an A / CNAME record for stream.hetherman.cloud pointing to the same
DDNS hostname / public IP your other NPM-hosted services use.
2. Router port forwarding
Make sure your router forwards these to NPM (not to the PC directly):
| Proto | External port | Internal target |
|---|---|---|
| TCP | 443 | NPM host, 443 |
| UDP | 48189 | NPM host, 48189 |
(TCP 443 is probably already forwarded for your other services; UDP 48189 is the new one for this app.)
3. NPM Proxy Host (HTTP)
In NPM, Hosts -> Proxy Hosts -> Add Proxy Host.
Details tab:
| Field | Value |
|---|---|
| Domain Names | stream.hetherman.cloud |
| Scheme | http |
| Forward Hostname | <PC-LAN-IP> |
| Forward Port | 48080 |
| Cache Assets | off |
| Block Common Exploits | on |
| Websockets Support | on |
Custom Locations tab: leave this empty. Do not add any custom location
entries here. The /whep/, /hls/, and /v3/ locations are defined in the
Advanced tab config below with trailing-slash path stripping. Adding them in
the GUI creates duplicate nginx location blocks that cause routing failures.
SSL tab:
- SSL Certificate: Request a new SSL Certificate with Let's Encrypt
- Force SSL: on
- HTTP/2 Support: on
- HSTS Enabled: optional
Advanced tab: paste the entire contents of
config/npm-advanced.conf. This installs:
- Authentik forward-auth subrequest on all requests
/whep/-> MediaMTX WHEP port 48889 (prefix stripped)/hls/-> MediaMTX HLS port 48888 (prefix stripped)/v3/-> MediaMTX API port 19997 (prefix stripped, auth bypassed)/outpost.goauthentik.io-> Authentik internal outpost
Save the proxy host. Wait for the Let's Encrypt certificate to be issued.
4. NPM Stream (UDP L4 proxy)
In NPM, Hosts -> Streams -> Add Stream.
| Field | Value |
|---|---|
| Incoming Port | 48189 |
| Forward Host | <PC-LAN-IP> |
| Forward Port | 48189 |
| TCP | off |
| UDP | on |
Save. NPM (nginx stream module) now forwards public UDP 48189 to MediaMTX
on the gaming PC. This is the path WebRTC media takes after ICE negotiation.
5. Verify
- HTTP + auth: from an incognito browser on a different network, visit
https://stream.hetherman.cloud. You should be redirected toauth.hetherman.cloudto log in. Log in as astream-viewersmember - you should land back at the stream page (video container + "Stream offline" overlay, assuming you haven't started OBS yet). - Certificate: the padlock icon should show the Let's Encrypt cert.
- With OBS streaming, open DevTools on the stream page and confirm:
POST /whep/game-opus/whepreturns 201GET /hls/game-opus/index.m3u8returns 200GET /statusreturns 200 with"ready": true
- UDP stream: with OBS streaming and a viewer connected, run
tcpdump -n -i any udp port 48189on the NPM host and confirm packets flow.
Troubleshooting
- 500 or auth loop on stream.hetherman.cloud: check the outpost
proxy_passin the Advanced config uses the internal Authentik address (http://192.168.50.224:30140) not the public HTTPS URL. Using the public URL causes SSL SNI issues when NPM tries to proxy to itself. - WHEP returns 400: the Custom Locations tab in the NPM GUI has
/whep,/hls, or/v3entries. Remove them - these must only be in the Advanced tab config so the trailing-slash path stripping works correctly. - WHEP returns 401 / browser shows a Basic Auth dialog: MediaMTX is
challenging the viewer directly. Check
authInternalUsersinmediamtx.ymlhas a rule allowingreadfrom any IP (emptyips: []).