artemis/README.md

6.1 KiB

Artemis

Artemis is a fork of Sunshine — the open-source GameStream host — with an embedded WireGuard client that automatically connects to a DragonRelay server.

This lets remote 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  {name, wg_ip, port, displays}
  4. Artemis heartbeats: PUT  /api/host/heartbeat {wg_ip}  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/displayinfo.h + _linux.cpp / _win.cpp Display enumeration for relay registration
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
scripts/build-boringtun-win.ps1 Build boringtun for Windows

Quick start

1. Clone Sunshine and apply the Artemis patch

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 scripts/build-boringtun.sh

Windows (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):

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):

[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:

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:

// In main.cpp or wherever Sunshine initialises subsystems:
#ifdef ARTEMIS_RELAY_ENABLED
#include "wg/wgclient.h"
#include "wg/wgconfig.h"
#include "wg/relayreg.h"
#include "wg/displayinfo.h"

// Boot sequence (run before Sunshine starts accepting streams):
wg::RelayReg relay;
relay.setBaseURL(config::relay_url);

std::string err;
if (!relay.login(config::relay_user, config::relay_pass, err))
    BOOST_LOG(error) << "Relay login failed: " << 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

const std::string localIP = wgClient.localIP();   // e.g. "10.99.0.3"
const auto displays = wg::enumerateDisplays();
relay.registerHost(config::relay_name, localIP, config::relay_port, displays, err);

// Heartbeat thread (every 60 s):
std::thread([&]() {
    while (running) {
        std::this_thread::sleep_for(std::chrono::seconds(60));
        std::string err;
        relay.heartbeat(localIP, err);            // wg_ip required
    }
}).detach();

// Shutdown:
{ std::string err; relay.unregisterHost(localIP, err); } // wg_ip required
wgClient.stop();
{ std::string err; 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:

git fetch upstream
git merge upstream/master   # only conflict-free for untouched files