initial commit

This commit is contained in:
2026-04-05 17:16:51 -04:00
commit 6bc7cf6318
14 changed files with 1829 additions and 0 deletions
+87
View File
@@ -0,0 +1,87 @@
# Authentik setup
Creates a Forward Auth Proxy Provider that NPM will consult before allowing
any request to `https://stream.hetherman.cloud`.
Prerequisites: you already run Authentik at `https://auth.hetherman.cloud` and
have admin access.
## 1. Create a group
1. Authentik admin -> **Directory -> Groups -> Create**
2. Name: `stream-viewers`
3. Save.
4. Add each friend's user account to this group. **Do not** add yourself /
your admin account - your access comes from your existing admin group.
## 2. Create a Proxy Provider
1. **Applications -> Providers -> Create**
2. Select **Proxy Provider** and click Next.
3. Fill in:
- **Name**: `game-stream-forward-auth`
- **Authorization flow**: `default-provider-authorization-implicit-consent`
(skips the "Authorize application" prompt so friends get a one-click login)
- **Type**: **Forward auth (single application)**
- **External host**: `https://stream.hetherman.cloud`
- **Token validity**: default (24 hours) is fine
4. Save.
## 3. Create an Application
1. **Applications -> Applications -> Create**
2. Fill in:
- **Name**: `Game Stream`
- **Slug**: `game-stream`
- **Provider**: `game-stream-forward-auth` (the provider from step 2)
- **Launch URL**: `https://stream.hetherman.cloud`
3. Save.
## 4. Bind the group policy
Restrict who can authenticate to this application:
1. Open the `Game Stream` application you just created.
2. Go to the **Policy / Group / User Bindings** tab -> **Create binding**
3. **Group**: `stream-viewers`
4. Leave the rest as default; Save.
After this step, only members of `stream-viewers` (and Authentik superusers)
can authenticate to the game stream.
## 5. Ensure the outpost serves this application
Authentik runs an "outpost" that exposes `/outpost.goauthentik.io/auth/nginx`
for the nginx `auth_request` forward-auth pattern.
1. **Applications -> Outposts**
2. Edit the default `authentik Embedded Outpost` (or create one if there is
not one already).
3. Under **Applications**, make sure `Game Stream` is checked.
4. Save. The outpost reloads automatically.
Verify the outpost endpoint is reachable:
```
curl -I https://auth.hetherman.cloud/outpost.goauthentik.io/ping
```
A 200 or 204 means the outpost is up.
## 6. Verify end-to-end
After finishing `docs/npm-setup.md`:
1. Open `https://stream.hetherman.cloud` in a private/incognito browser.
2. You should be redirected to Authentik to log in.
3. Log in as a member of `stream-viewers`. You should be redirected back to
the stream page.
4. Log out, clear cookies, try logging in as a non-member. You should be
denied with a "You do not have access" message.
## Revoking access
Remove the friend's user from the `stream-viewers` group. Their Authentik
session remains valid until it expires, but the next `auth_request` forward
auth check (evaluated on every HTTP request NPM sees) will fail the group
policy and they will be locked out within seconds.
+101
View File
@@ -0,0 +1,101 @@
# Nginx Proxy Manager setup
Configures NPM to:
1. Serve `https://stream.hetherman.cloud` with TLS + Authentik forward auth,
reverse-proxying HTTP traffic to the Windows gaming PC.
2. Forward public UDP 8189 (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.10`).
## 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 | 8189 | NPM host, 8189 |
(TCP 443 is probably already forwarded for your other services; UDP 8189 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 | `8080` |
| Cache Assets | off |
| Block Common Exploits | on |
| Websockets Support | **on** (WebRTC signaling works without this, but it costs nothing) |
**Custom locations tab:** add three entries so WHEP, HLS, and the MediaMTX
API are reverse-proxied to the right MediaMTX ports (and inherit the same
forward-auth gating).
| Location | Scheme | Forward Hostname | Forward Port |
|----------|--------|------------------|--------------|
| `/whep` | `http` | `<PC-LAN-IP>` | `8889` |
| `/hls` | `http` | `<PC-LAN-IP>` | `8888` |
| `/v3` | `http` | `<PC-LAN-IP>` | `9997` |
**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`](../config/npm-advanced.conf). This installs the
Authentik forward-auth subrequest and the sign-in redirect.
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 | `8189` |
| Forward Host | `<PC-LAN-IP>` |
| Forward Port | `8189` |
| TCP | **off** |
| UDP | **on** |
Save. NPM (nginx `stream` module) now forwards public UDP 8189 to MediaMTX
on the gaming PC. This is the path WebRTC media takes after ICE negotiation.
## 5. Verify
1. **HTTP + auth:** from an incognito browser on a different network, visit
`https://stream.hetherman.cloud`. You should be redirected to
`auth.hetherman.cloud` to log in. Log in as a `stream-viewers` member -
you should land back at the stream page (video container + "Stream
offline" overlay, assuming you haven't started OBS yet).
2. **Certificate:** the padlock icon should show the Let's Encrypt cert you
requested.
3. **/whep, /hls, /v3:** once you start streaming in OBS, open DevTools on
the stream page and confirm requests to `/whep/game/whep`,
`/hls/game/index.m3u8`, and `/v3/paths/get/game` all return 200 (and not
401/302).
4. **UDP stream:** with OBS streaming, tail the NPM container logs - you
should see entries from the stream module for UDP connections on 8189.
Alternatively, from the NPM host run
`tcpdump -n -i any udp port 8189` and confirm packets flow while a
viewer is connected.
+132
View File
@@ -0,0 +1,132 @@
# OBS setup
Configures OBS Studio on the Windows gaming PC to capture the game, encode
with NVENC, and publish via WHIP to the local MediaMTX instance that the OBS
script spawns.
Prerequisites:
- OBS Studio 30.0 or newer (WHIP output is built in from 30.x onward).
- You already ran `.\scripts\install.ps1` in an elevated PowerShell, so
`bin\mediamtx.exe` exists and the `GameStream-UDP-8189` firewall rule is
registered (in the disabled state).
## 1. Load the OBS script
1. OBS -> **Tools -> Scripts -> +**
2. Select `obs-script/game_stream.py` from this repo.
3. In the properties panel on the right, set:
| Setting | Value |
|-----------------------|---------------------------------------------------------------|
| MediaMTX binary | `<repo>\bin\mediamtx.exe` |
| MediaMTX config | `<repo>\config\mediamtx.yml` |
| Frontend directory | `<repo>\frontend` |
| Frontend HTTP port | `8080` (default) |
| Firewall rule name | `GameStream-UDP-8189` (must match the rule created by install.ps1) |
| Public URL | `https://stream.hetherman.cloud` |
| MediaMTX API URL | `http://127.0.0.1:9997` |
4. Check the **Script Log** at the bottom - you should see
`[game_stream] game_stream.py loaded`.
## 2. OBS output settings
**Settings -> Output**, set **Output Mode** to **Advanced**.
### Streaming tab
| Setting | Value |
|------------------|---------------------------------------------------------|
| Audio Encoder | Opus (or FFmpeg AAC if Opus is unavailable - Opus is preferred for WebRTC) |
| Video Encoder | **NVIDIA NVENC HEVC** or **NVIDIA NVENC H.264** |
Use H.264 for maximum browser compatibility (all browsers). HEVC works in
Safari and recent Chrome but not Firefox - stick with H.264 unless you have a
specific reason.
**Encoder settings (H.264):**
| Setting | Value |
|---------------------|-------------------|
| Rate Control | CBR |
| Bitrate | 8000 Kbps |
| Keyframe Interval | 2 s |
| Preset | P5 (Quality) |
| Tuning | Ultra Low Latency |
| Multipass | Two Passes (Quarter Resolution) |
| Profile | high |
| Look-ahead | off |
| Psycho Visual Tuning | on |
| GPU | 0 |
| Max B-frames | **0** (required for low-latency WebRTC) |
With a 600 Mbps upload and up to 6 viewers at 8 Mbps each, 8000 Kbps leaves
generous headroom. Push to 12000-15000 Kbps if you want higher quality.
### Audio tab
| Setting | Value |
|-----------------|------------|
| Audio Bitrate | 128 Kbps |
| Sample Rate | 48 kHz |
## 3. OBS stream settings
**Settings -> Stream**
| Setting | Value |
|----------|-----------------------------------------------|
| Service | Custom |
| Protocol | **WHIP** |
| Server | `http://localhost:8889/game/whip` |
| Bearer Token | (leave blank) |
Save.
## 4. First stream
1. Click **Start Streaming**.
2. Check the OBS Script Log - you should see:
- `Firewall rule 'GameStream-UDP-8189' ENABLED`
- `MediaMTX started (pid=...)`
- `Frontend HTTP server listening on 0.0.0.0:8080`
- `Viewers can watch at: https://stream.hetherman.cloud`
3. Open `https://stream.hetherman.cloud` from another device, log in with
Authentik, and verify video plays.
## 5. Stopping
Click **Stop Streaming** in OBS. The script will:
- Stop the MediaMTX subprocess
- Stop the frontend HTTP server
- Disable the firewall rule (`GameStream-UDP-8189` -> disabled)
Verify the firewall state from PowerShell:
```powershell
Get-NetFirewallRule -DisplayName "GameStream-UDP-8189" | Select-Object Enabled
```
Should report `False` while not streaming, `True` while streaming.
## Troubleshooting
- **"MediaMTX binary not found"** in the script log: the path in the script
properties panel is wrong. Re-select it with the file picker.
- **OBS cannot connect to WHIP**: MediaMTX did not start. Check the script
log for the actual reason; most commonly a port conflict on 8889 or 8189
(another process is already using them).
- **Viewers see "Stream offline"** even after you click Start Streaming:
- Check that the MediaMTX API returns `ready: true`:
`curl http://localhost:9997/v3/paths/get/game`
- Check OBS's own streaming indicator - if it's red, OBS is not actually
sending to WHIP. Verify the URL and that the custom service / WHIP
protocol is selected.
- **Viewers connect but playback freezes after a few seconds:** the UDP port
path is broken. Verify the firewall rule is enabled (`Get-NetFirewallRule`),
the router port-forward to NPM for UDP 8189 is correct, and the NPM Stream
entry points at `<PC-LAN-IP>:8189`.
- **Autoplay is blocked / no audio:** browsers start the video muted so
autoplay works. There is a "Click to unmute" button in the status bar.