Files
infrastructure/docs/04-PHASE4-REMOTE-GAMING.md
jazzymc 62a6267026
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Add infrastructure documentation
2026-01-18 16:57:25 +02:00

466 lines
12 KiB
Markdown

# Phase 4: Remote Gaming (Sunshine + Moonlight)
## Goal
Enable low-latency 60FPS game streaming from Nobara Linux (AMD GPU) to MacBook and Android devices, using Tailscale for optimal network pathing.
---
## Prerequisites
- **Gaming PC:** Nobara Linux with AMD GPU (VA-API support)
- **Tailscale:** Installed on gaming PC (from Phase 1)
- **Clients:** MacBook and Android devices with Tailscale
---
## Architecture Overview
```
┌─────────────────────────────────┐
│ Tailscale Mesh Network │
│ (Encrypted, P2P when possible) │
└─────────────────┬───────────────┘
┌────────────────────────────┼────────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Nobara Gaming PC│ │ MacBook │ │ Android Device │
│ Sunshine Host │ │ Moonlight Client│ │ Moonlight Client│
│ 100.x.x.x (TS) │ │ 100.x.x.x (TS) │ │ 100.x.x.x (TS) │
│ AMD VA-API │ │ │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
```
**Why Tailscale for Gaming?**
- Automatic P2P connection when on same LAN
- Encrypted tunnel when remote
- No manual port forwarding required
- MagicDNS for easy hostname resolution
- NAT traversal handled automatically
---
## Implementation Steps
### Step 4.1: Install Sunshine on Nobara
**Method A: Flatpak (Recommended for Nobara)**
```bash
# Install via Flatpak
flatpak install flathub dev.lizardbyte.app.Sunshine
# Enable autostart
flatpak run --command=sunshine dev.lizardbyte.app.Sunshine &
```
**Method B: Native Package**
```bash
# Add Sunshine repository
sudo dnf copr enable lizardbyte/stable
sudo dnf install sunshine
# Enable service
sudo systemctl enable --now sunshine
```
**Post-Install:**
1. Access Sunshine web UI: `https://localhost:47990`
2. Set initial admin password
3. Complete setup wizard
---
### Step 4.2: Configure AMD VA-API Hardware Encoding
**Verify AMD GPU:**
```bash
# Check for AMD GPU
lspci | grep -i vga
# Verify VA-API support
vainfo
```
**Expected output:**
```
vainfo: VA-API version: 1.x
vainfo: Driver version: Mesa Gallium driver ...
vainfo: Supported profile and entrypoints:
VAProfileH264Main : VAEntrypointEncSlice
VAProfileHEVCMain : VAEntrypointEncSlice
```
**Configure Sunshine for VA-API:**
1. Open Sunshine Web UI → Configuration → Video
2. Set:
- **Encoder:** `vaapi`
- **Adapter:** `/dev/dri/renderD128` (default AMD)
- **Codec:** `H.265/HEVC` (better compression, lower latency)
**Sunshine config file** (`~/.config/sunshine/sunshine.conf`):
```ini
[video]
encoder = vaapi
adapter_name = /dev/dri/renderD128
hevc_mode = 2 # Always use HEVC when client supports
[stream]
fps = [30, 60, 120]
resolutions = [
1920x1080,
2560x1440,
3840x2160
]
```
---
### Step 4.3: Add Applications to Sunshine
**Access:** Sunshine Web UI → Applications
**Recommended Applications:**
| Name | Command | Working Directory |
|------|---------|-------------------|
| Desktop | - | - |
| Steam Big Picture | `steam -bigpicture` | - |
| Lutris | `lutris` | - |
| Heroic Games | `heroic` | - |
**For specific games:**
```
Name: Cyberpunk 2077
Command: steam steam://rungameid/1091500
Detached: ["steam"]
```
---
### Step 4.4: Install Tailscale on Nobara
```bash
# Install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh
# Authenticate
sudo tailscale up
# Get Tailscale IP
tailscale ip -4
```
**Note the Tailscale IP** (e.g., `100.64.x.x`) - clients will connect to this.
---
### Step 4.5: Configure Sunshine for Tailscale
**Sunshine listens on all interfaces by default.** For security, restrict to Tailscale:
**Option A: Bind to Tailscale interface only**
```ini
# ~/.config/sunshine/sunshine.conf
[network]
address_family = both
origin_address = 100.64.x.x # Your Tailscale IP
```
**Option B: Firewall rules (recommended)**
```bash
# Allow Sunshine ports only from Tailscale
sudo firewall-cmd --permanent --zone=trusted --add-source=100.64.0.0/10
sudo firewall-cmd --permanent --zone=trusted --add-port=47984-48010/tcp
sudo firewall-cmd --permanent --zone=trusted --add-port=47998-48010/udp
sudo firewall-cmd --permanent --zone=trusted --add-port=47989/tcp # Web UI
sudo firewall-cmd --permanent --zone=trusted --add-port=47990/tcp # Web UI HTTPS
sudo firewall-cmd --reload
```
---
### Step 4.6: Install Moonlight Clients
#### MacBook
```bash
# Homebrew
brew install --cask moonlight
# Or download from: https://moonlight-stream.org/
```
#### Android
- Install "Moonlight Game Streaming" from Google Play Store
---
### Step 4.7: Pair Moonlight with Sunshine
1. **On Moonlight client:**
- Add PC manually: Enter Tailscale IP (e.g., `100.64.x.x`)
- Or use MagicDNS hostname: `nobara-pc` (if enabled in Tailscale)
2. **Enter PIN:**
- Moonlight displays a 4-digit PIN
- Enter in Sunshine Web UI → PIN Pairing
3. **Verify connection:**
- Moonlight should show your configured applications
---
### Step 4.8: MikroTik QoS for Gaming (Optional but Recommended)
**Goal:** Prioritize Nobara PC traffic to prevent bufferbloat during gaming sessions.
**SSH to MikroTik:**
```bash
ssh -i /root/.ssh/mikrotik_key -p 2222 unraid@192.168.31.1
```
**Create Simple Queue for Gaming PC:**
```routeros
# First, find Nobara's IP (replace with actual)
# Assuming Nobara is at 192.168.31.50
# Create queue for gaming priority
/queue simple add \
name="Gaming-Priority" \
target=192.168.31.50 \
max-limit=0/0 \
priority=1/1 \
queue=default-small/default-small \
comment="Nobara Gaming PC Priority"
# Alternative: Use queue tree for more control
/queue tree add \
name="Gaming-Upload" \
parent=global \
packet-mark=gaming-upload \
priority=1 \
max-limit=50M
/queue tree add \
name="Gaming-Download" \
parent=global \
packet-mark=gaming-download \
priority=1 \
max-limit=100M
# Mark gaming traffic
/ip firewall mangle add \
chain=prerouting \
src-address=192.168.31.50 \
action=mark-packet \
new-packet-mark=gaming-upload \
passthrough=yes
/ip firewall mangle add \
chain=postrouting \
dst-address=192.168.31.50 \
action=mark-packet \
new-packet-mark=gaming-download \
passthrough=yes
```
---
### Step 4.9: Optimize Streaming Settings
**Sunshine Settings (Server):**
| Setting | LAN Value | Remote Value |
|---------|-----------|--------------|
| Bitrate | 50-80 Mbps | 20-40 Mbps |
| FPS | 60-120 | 60 |
| Resolution | Native | 1080p |
| Codec | HEVC | HEVC |
**Moonlight Settings (Client):**
| Setting | LAN Value | Remote Value |
|---------|-----------|--------------|
| Video Codec | HEVC (if supported) | HEVC |
| Frame Pacing | V-Sync | On |
| Bitrate | Auto or 50+ Mbps | 20 Mbps |
| Resolution | Match display | 1080p |
---
## Network Path Analysis
**Tailscale P2P (Same Network):**
```
MacBook → Router → Nobara PC
Latency: <1ms additional overhead
```
**Tailscale Relayed (Different Network):**
```
MacBook → Tailscale DERP → Nobara PC
Latency: ~20-50ms additional overhead
```
**With Tailscale Direct (NAT Traversal Success):**
```
MacBook (Office) → Internet → Home Router → Nobara PC
Latency: RTT/2 + encoding latency (~30-80ms typical)
```
---
## Service Interruption Assessment
| Action | Risk | Impact | Mitigation |
|--------|------|--------|------------|
| Install Sunshine | NONE | Nobara only | - |
| Install Tailscale | NONE | Nobara only | - |
| MikroTik QoS | LOW | May affect other traffic briefly | Test during low usage |
| Firewall rules | LOW | Nobara only | Can revert |
---
## Verification Checklist
- [ ] Sunshine installed and running on Nobara
- [ ] VA-API encoding verified: `vainfo` shows HEVC support
- [ ] Tailscale running on Nobara: `tailscale status`
- [ ] Sunshine Web UI accessible: `https://<tailscale-ip>:47990`
- [ ] Moonlight paired successfully
- [ ] Desktop streaming works (low latency)
- [ ] Game streaming works at 60 FPS
- [ ] Remote streaming works (via Tailscale from external network)
- [ ] MikroTik QoS queue active (optional)
---
## Troubleshooting
### High Latency / Stuttering
1. **Check Tailscale connection type:**
```bash
tailscale status
# Look for "direct" vs "relay"
```
2. **Force direct connection:**
```bash
tailscale ping <client-hostname>
```
3. **Lower bitrate in Moonlight**
### Encoding Errors
1. **Verify VA-API:**
```bash
sudo vainfo
# Should show HEVC/H264 encode support
```
2. **Check Sunshine logs:**
```bash
journalctl -u sunshine -f
# Or: ~/.config/sunshine/sunshine.log
```
3. **Fall back to software encoding:**
```ini
# sunshine.conf
encoder = software
```
### No Audio
1. **Check PulseAudio/PipeWire:**
```bash
pactl list sinks
```
2. **Set Sunshine audio sink:**
- Web UI → Audio → Select correct output
---
## Security Considerations
1. **Tailscale-only access:** Sunshine is only reachable via Tailscale network
2. **PIN pairing:** Each client must be manually paired
3. **Web UI protection:** Consider adding Authentik forward auth (optional)
4. **Firewall:** Block Sunshine ports from non-Tailscale interfaces
---
## Optional: Expose Sunshine Web UI via Traefik
If you want to manage Sunshine remotely via browser:
**Add to Traefik dynamic.yml:**
```yaml
http:
routers:
sunshine-secure:
rule: "Host(`sunshine.xtrm-lab.org`)"
entryPoints:
- https
middlewares:
- default-headers
- authentik-forward-auth # Protect with Authentik
tls:
certResolver: cloudflare
service: sunshine
services:
sunshine:
loadBalancer:
servers:
- url: "https://192.168.31.50:47990" # Nobara IP
```
**MikroTik hairpin NAT (if needed):**
```routeros
# Only if accessing from LAN via external hostname
/ip/firewall/nat add chain=srcnat \
action=masquerade \
src-address=192.168.31.0/24 \
dst-address=192.168.31.50 \
dst-port=47990 \
protocol=tcp
```
---
## Files Modified
| File/System | Change | Backup Required |
|-------------|--------|-----------------|
| Nobara: ~/.config/sunshine/ | Sunshine config | No (new install) |
| Nobara: firewalld | Allow Tailscale ports | Can revert |
| MikroTik: Queue | Gaming priority | N/A |
| Traefik dynamic.yml (optional) | Sunshine route | YES |
---
## Performance Expectations
| Scenario | Expected Latency | FPS |
|----------|------------------|-----|
| LAN (same network) | 5-15ms | 60-120 |
| Remote (Tailscale direct) | 30-60ms | 60 |
| Remote (Tailscale relay) | 50-100ms | 60 |
---
## Dependencies for Next Phase
Phase 5 (RustDesk) provides:
- Alternative remote access when gaming not required
- Lower resource usage for general desktop access
- Additional fallback for remote management