# Artemis **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 ```