466 lines
12 KiB
Markdown
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
|