initial commit
This commit is contained in:
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
Reference in New Issue
Block a user