From d37d68e8dfc95d582ac1bab92bf3752a43750a1f Mon Sep 17 00:00:00 2001 From: ZGaetano Date: Wed, 6 May 2026 19:22:27 -0400 Subject: [PATCH] =?UTF-8?q?docs:=20Artemis=20README=20=E2=80=94=20setup,?= =?UTF-8?q?=20architecture,=20and=20integration=20guide?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 182 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 180 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d20ad45..0b88cb5 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,181 @@ -# artemis +# Artemis -Artemis — a Sunshine fork with embedded WireGuard client for seamless DragonRelay connectivity \ No newline at end of file +**Artemis** is a fork of [Sunshine](https://github.com/LizardByte/Sunshine) — the open-source GameStream host — with an embedded WireGuard client that automatically connects to a [DragonRelay](https://forge.wilddragon.net/zgaetano/dragonrelay) server. + +This lets remote **[DragonMoonlight](https://forge.wilddragon.net/zgaetano/dragonmoonlight)** clients discover and stream from Artemis hosts over a private WireGuard network, without requiring port-forwarding, mDNS, or direct LAN access. + +--- + +## Architecture + +``` +DragonMoonlight (client) Artemis (host) + WG tunnel: 10.99.0.2/24 WG tunnel: 10.99.0.3/24 + │ │ + └────────── 10.99.0.0/24 ──────────────┘ + │ + DragonRelay server + ├── WireGuard server (wg0: 10.99.0.1) + ├── REST API (JWT auth) + └── Host registry (5-min TTL) + +Flow: + 1. Artemis boots → logs into DragonRelay → provisions WG peer + 2. Artemis starts WireGuard tunnel → gets IP 10.99.0.3 + 3. Artemis registers: POST /api/host/register {wg_ip: "10.99.0.3", port: 47984} + 4. Artemis heartbeats: PUT /api/host/heartbeat every 60 s + 5. DragonMoonlight: GET /api/hosts sees 10.99.0.3 in the list + 6. DragonMoonlight connects to 10.99.0.3:47984 over the shared WG tunnel +``` + +--- + +## New files (WireGuard integration layer) + +| File | Purpose | +|------|---------| +| `src/wg/wgconfig.h/.cpp` | Parses standard wg-quick `.conf` files (C++17, no Qt) | +| `src/wg/wgclient.h` | Platform-agnostic WireGuard tunnel interface | +| `src/wg/wgclient_win.cpp` | Windows: Wintun kernel TUN + boringtun FFI | +| `src/wg/wgclient_linux.cpp` | Linux: `/dev/net/tun` + boringtun FFI | +| `src/wg/relayreg.h/.cpp` | DragonRelay HTTP client (libcurl) | +| `src/wg/boringtun_ffi.h` | C ABI bindings for boringtun | +| `cmake/wg.cmake` | CMake integration snippet | +| `scripts/build-boringtun.sh` | Build boringtun for Linux/macOS | + +--- + +## Quick start + +### 1. Clone Sunshine and apply the Artemis patch + +```bash +git clone https://github.com/LizardByte/Sunshine artemis +cd artemis +git remote add artemis-upstream https://forge.wilddragon.net/zgaetano/artemis.git +git fetch artemis-upstream +git merge artemis-upstream/main --allow-unrelated-histories +``` + +### 2. Build boringtun + +**Linux / macOS:** +```bash +bash scripts/build-boringtun.sh +``` + +**Windows (PowerShell):** +```powershell +pwsh scripts/build-boringtun-win.ps1 +``` + +This produces `deps/boringtun/libboringtun.a` (or `.lib` on Windows). + +### 3. Configure CMake + +Add to your `CMakeLists.txt` (after the main target is defined): + +```cmake +include(cmake/wg.cmake) +artemis_wg_configure(sunshine) # replace 'sunshine' with your target name +``` + +### 4. Configure Artemis + +Create `/etc/artemis/relay.conf` (Linux) or `%APPDATA%\Artemis\relay.conf` (Windows): + +```ini +[relay] +url = https://relay.example.com # DragonRelay base URL +username = host-user # DragonRelay account credentials +password = secret +device = my-gaming-pc # Appended to username: host-user@my-gaming-pc +name = Gaming PC # Friendly display name in DragonMoonlight +port = 47984 # Sunshine streaming port (default) +``` + +Artemis reads this on startup, authenticates, provisions a WireGuard peer, and +starts the tunnel automatically. The WireGuard `.conf` returned by DragonRelay +is parsed in-memory — no file is written to disk. + +### 5. Linux: capabilities / root + +The Linux WireGuard client opens `/dev/net/tun` and runs `ip addr/route` +commands. Either run Artemis as root, or grant `CAP_NET_ADMIN`: + +```bash +sudo setcap cap_net_admin+ep /usr/bin/artemis +``` + +### 6. Windows: Administrator + +Wintun requires Administrator to create the kernel TUN adapter. Artemis ships +with a UAC manifest (`requireAdministrator`). Users will see a one-time +elevation prompt on first launch. + +--- + +## Integration points in Sunshine source + +After merging, wire up the relay client in Sunshine's startup/shutdown paths. +The key hooks are: + +```cpp +// In main.cpp or wherever Sunshine initialises subsystems: +#ifdef ARTEMIS_RELAY_ENABLED +#include "wg/wgclient.h" +#include "wg/wgconfig.h" +#include "wg/relayreg.h" + +// Boot sequence (run before Sunshine starts accepting streams): +wg::RelayReg relay; +relay.setBaseURL(config::relay_url); +relay.login(config::relay_user, config::relay_pass, err); + +wg::VPNConf vpnConf; +relay.provisionVPN(config::relay_device, vpnConf, err); + +wg::Config wgCfg; +wg::Config::fromString(vpnConf.conf, wgCfg, err); + +wg::Client wgClient; +wgClient.start(wgCfg); // tunnel up + +relay.registerHost(config::relay_name, wgClient.localIP(), config::relay_port, err); + +// Heartbeat thread (every 60 s): +std::thread([&]() { + while (running) { + std::this_thread::sleep_for(std::chrono::seconds(60)); + relay.heartbeat(err); + } +}).detach(); + +// Shutdown: +relay.unregisterHost(err); +wgClient.stop(); +relay.deleteVPNPeer(vpnConf.id, err); +#endif +``` + +--- + +## Privilege model + +| Platform | Requirement | Why | +|----------|-------------|-----| +| Linux | `CAP_NET_ADMIN` or root | `/dev/net/tun` open + `ip` commands | +| Windows | Administrator | Wintun kernel driver | + +--- + +## Upstream merge hygiene + +Artemis adds only new files under `src/wg/` and `cmake/`. No Sunshine source +files are modified — this minimises merge conflicts when pulling upstream +Sunshine updates: + +```bash +git fetch upstream +git merge upstream/master # only conflict-free for untouched files +```