docs: DragonMoonlight setup and integration guide
This commit is contained in:
parent
33edc6affe
commit
6db9781a96
1 changed files with 188 additions and 2 deletions
190
README.md
190
README.md
|
|
@ -1,3 +1,189 @@
|
|||
# dragonmoonlight
|
||||
# 🐉 DragonMoonlight
|
||||
|
||||
DragonMoonlight — a fork of moonlight-qt with embedded WireGuard and native DragonRelay integration
|
||||
A fork of [moonlight-qt](https://github.com/moonlight-stream/moonlight-qt) with native [DragonRelay](https://forge.wilddragon.net/zgaetano/dragonrelay) integration and an embedded WireGuard client.
|
||||
|
||||
Instead of managing a separate VPN app, DragonMoonlight authenticates against your DragonRelay server, auto-provisions a WireGuard peer, brings up the tunnel, and presents your streaming hosts — all in one UI.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────┐ ┌──────────────────────────────┐
|
||||
│ DragonMoonlight (this fork) │ │ DragonRelay (homelab) │
|
||||
│ │ │ │
|
||||
│ RelayClient ─── HTTPS ────────►│──────►│ POST /api/vpn/peer │
|
||||
│ │ │ │ (returns WireGuard .conf) │
|
||||
│ ▼ │ │ │
|
||||
│ TunnelManager │ │ wg0 interface │
|
||||
│ ├─ boringtun (WireGuard/Rust) │◄═════►│ 10.99.0.1 │
|
||||
│ └─ utun (macOS, no root*) │ WG │ │
|
||||
│ │ │ mDNS → Apollo/Artemis hosts │
|
||||
│ DragonRelayView.qml │ └──────────────────────────────┘
|
||||
│ (host list, stream button) │
|
||||
└─────────────────────────────────┘
|
||||
|
||||
* Route setup requires one macOS admin auth dialog per session.
|
||||
```
|
||||
|
||||
## New files (vs upstream moonlight-qt)
|
||||
|
||||
```
|
||||
app/vpn/
|
||||
├── boringtun_ffi.h C ABI for the boringtun Rust library
|
||||
├── wireguardconfig.h/.cpp WireGuard .conf parser
|
||||
├── tunnelmanager.h Cross-platform tunnel interface
|
||||
├── tunnelmanager_mac.mm macOS implementation (utun + boringtun)
|
||||
├── relayclient.h/.cpp HTTP client for the DragonRelay API
|
||||
└── CMakeLists_vpn.cmake Build system additions
|
||||
|
||||
app/gui/
|
||||
└── DragonRelayView.qml Connect / host-list UI page
|
||||
|
||||
scripts/
|
||||
└── build-boringtun.sh Compiles boringtun as a static library
|
||||
|
||||
deps/boringtun/ Created by build-boringtun.sh (git-ignored)
|
||||
```
|
||||
|
||||
## Building (macOS)
|
||||
|
||||
### 1. Prerequisites
|
||||
|
||||
```bash
|
||||
# Xcode Command Line Tools
|
||||
xcode-select --install
|
||||
|
||||
# Homebrew
|
||||
brew install qt@6 cmake rustup
|
||||
|
||||
# Rust toolchain
|
||||
rustup-init
|
||||
rustup target add aarch64-apple-darwin x86_64-apple-darwin
|
||||
```
|
||||
|
||||
### 2. Clone upstream moonlight-qt into this repo
|
||||
|
||||
This repo holds only the DragonMoonlight additions. You need to merge with upstream:
|
||||
|
||||
```bash
|
||||
git clone https://forge.wilddragon.net/zgaetano/dragonmoonlight
|
||||
cd dragonmoonlight
|
||||
|
||||
# Add upstream as a remote and merge
|
||||
git remote add upstream https://github.com/moonlight-stream/moonlight-qt.git
|
||||
git fetch upstream
|
||||
git merge upstream/master --allow-unrelated-histories
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
### 3. Build boringtun
|
||||
|
||||
```bash
|
||||
bash scripts/build-boringtun.sh --universal
|
||||
# Produces: deps/boringtun/libboringtun.a (universal arm64+x86_64)
|
||||
```
|
||||
|
||||
### 4. Integrate the VPN CMake snippet
|
||||
|
||||
In moonlight-qt's root `CMakeLists.txt`, add **after** the main target is defined:
|
||||
|
||||
```cmake
|
||||
include(app/vpn/CMakeLists_vpn.cmake)
|
||||
```
|
||||
|
||||
### 5. Register DragonRelayBackend with QML
|
||||
|
||||
In `app/main.cpp` (or wherever the QML engine is set up), add:
|
||||
|
||||
```cpp
|
||||
#include "dragonrelaybackend.h" // thin QObject wrapping RelayClient + TunnelManager
|
||||
|
||||
// Before engine.load():
|
||||
DragonRelayBackend relayBackend;
|
||||
engine.rootContext()->setContextProperty("dragonRelay", &relayBackend);
|
||||
```
|
||||
|
||||
`DragonRelayBackend` is the next class to write — it wires `RelayClient` ↔ `TunnelManager` ↔ QML.
|
||||
|
||||
### 6. Add the view to the navigation stack
|
||||
|
||||
In `app/gui/main.qml` or the computer browser stack, push `DragonRelayView` alongside the normal `PcView`.
|
||||
|
||||
### 7. Build
|
||||
|
||||
```bash
|
||||
mkdir build && cd build
|
||||
cmake .. -DCMAKE_PREFIX_PATH="$(brew --prefix qt@6)"
|
||||
make -j$(sysctl -n hw.logicalcpu)
|
||||
```
|
||||
|
||||
## How it works (connection flow)
|
||||
|
||||
```
|
||||
User clicks "Connect" in DragonRelayView
|
||||
│
|
||||
▼
|
||||
RelayClient.login(url, user, pass)
|
||||
│ POST /api/auth/login → JWT
|
||||
▼
|
||||
RelayClient.provisionVPN(deviceName)
|
||||
│ POST /api/vpn/peer → {id, conf}
|
||||
▼
|
||||
WireGuardConfig.fromConf(conf)
|
||||
│
|
||||
▼
|
||||
TunnelManager.start(cfg)
|
||||
├─ new_tunnel() via boringtun FFI
|
||||
├─ openUtun() → utunN fd (no root)
|
||||
├─ UDP socket → server endpoint
|
||||
├─ configureInterface() → osascript admin dialog (once per session)
|
||||
│ ifconfig + route add for 10.99.0.0/24
|
||||
└─ I/O threads (tunToUdp, udpToTun, ticker)
|
||||
│
|
||||
▼
|
||||
WireGuard handshake completes
|
||||
│
|
||||
▼
|
||||
RelayClient.fetchHosts() → GET /api/hosts
|
||||
│
|
||||
▼
|
||||
DragonRelayView shows host list
|
||||
│
|
||||
User clicks "Stream"
|
||||
│
|
||||
▼
|
||||
dragonRelay.streamHost(ip, "Desktop")
|
||||
(launches Moonlight streaming session)
|
||||
```
|
||||
|
||||
## Privilege model
|
||||
|
||||
| Operation | Root / Admin? |
|
||||
|---|---|
|
||||
| Open utun device | No |
|
||||
| `ifconfig utunN <ip> up` | Yes — one-time macOS auth dialog |
|
||||
| `route add -net 10.99.0.0/24 -interface utunN` | Yes — same dialog, batched |
|
||||
| Streaming (RTSP/UDP to Apollo host) | No |
|
||||
|
||||
The admin dialog appears once when the VPN first connects. Subsequent reconnects in the same session reuse the saved original-gateway and only need the dialog again if the interface was torn down.
|
||||
|
||||
**Production path:** Replace the `osascript` approach with a signed, sandboxed SMJobBless privileged helper or a NetworkExtension PacketTunnelProvider entitlement (requires Apple developer approval).
|
||||
|
||||
## DragonRelayBackend (next step)
|
||||
|
||||
The QML view is wired to a `dragonRelay` context property. The next file to write is `app/vpn/dragonrelaybackend.h/.cpp` — a `QObject` that:
|
||||
|
||||
- Owns `RelayClient` and `TunnelManager`
|
||||
- Exposes `Q_PROPERTY` values (`status`, `statusText`, `hosts`) to QML
|
||||
- Has `Q_INVOKABLE` methods: `connectRelay()`, `disconnectRelay()`, `streamHost()`
|
||||
- Translates `RelayClient` and `TunnelManager` signals into QML-visible state changes
|
||||
|
||||
## Roadmap
|
||||
|
||||
- [ ] `DragonRelayBackend` C++ ↔ QML bridge
|
||||
- [ ] Integrate `DragonRelayView` into upstream `PcView.qml` navigation
|
||||
- [ ] Windows support (`tunnelmanager_win.cpp` using Wintun)
|
||||
- [ ] Linux support (`tunnelmanager_linux.cpp` using kernel WireGuard)
|
||||
- [ ] Replace `osascript` with SMJobBless privileged helper on macOS
|
||||
- [ ] Replace plain-text password storage with system keychain (QKeychain)
|
||||
- [ ] `connected()` signal from first received packet rather than a fixed timer
|
||||
- [ ] Multi-monitor / display selection (Sunshine API integration)
|
||||
|
|
|
|||
Loading…
Reference in a new issue