Blog

Overal spelen op je cloudserver met Moonlight en Tailscale

Geen IPv6 thuis, geen poort openzetten: we verbonden Moonlight met een Sunshine-cloudserver via een Tailscale-netwerk (getest met Headscale): directe verbinding, 1080p 60 fps, 0 verloren frames en dezelfde 7,3 tot 7,8 ms verwerking op de server als zonder Tailscale.

Overal spelen op je cloudserver met Moonlight en Tailscale

Onze servers zijn standaard bereikbaar via IPv6. Veel thuisverbindingen hebben IPv6, maar niet allemaal: sommige mobiele netwerken, hotelwifi en oudere modems hebben alleen IPv4. Je kunt een dedicated IPv4 aan je server toevoegen (€ 5 per maand), maar er is nog een andere manier, die de poorten van Sunshine bovendien dicht houdt voor internet: Tailscale. Het bouwt een privé, versleuteld netwerk (een “tailnet”) tussen je apparaten, op basis van WireGuard. Je server en je telefoon krijgen elk een adres in 100.x.y.z, en Moonlight maakt verbinding met dat adres alsof beide thuis staan.

Een game, door Sunshine naar Moonlight gestreamd via het tailnet-adres (5 seconden, prestatie-overlay van Moonlight linksboven).

De resultaten in het kort

  • Het werkt met de officiële Tailscale-client aan beide kanten: directe verbinding tussen de twee machines (tailscale ping: pong via 203.0.113.10:41641 in 1ms), Moonlight op 100.x.y.1.
  • Tailscale kost niets meetbaars in de stream: afwisselende runs met en zonder Tailscale gaven dezelfde 1080p 60 fps, 7,3 tot 7,8 ms verwerking op de server via beide routes, 0 verloren frames.
  • Sunshine is dicht voor internet: de poorten accepteren alleen verbindingen die via het tailnet binnenkomen. Alleen de tunnel wordt gebruikt; je hoeft niets open te zetten op je modem.
  • Weinig CPU-belasting: de Tailscale-dienst gebruikte 3 tot 4% van één core op de server tijdens een 1080p-stream op 15 Mbit/s.

Twee manieren om een tailnet te krijgen

Tailscale-accountHeadscale
Wat het isDe eigen dienst van Tailscale beheert je netwerk (gratis Personal-abonnement)Open-source controleserver die je zelf draait
Clientsoftwareofficiële Tailscale-appsdezelfde officiële Tailscale-apps
Opzettenop elk apparaat inloggenHeadscale installeren, sleutels aanmaken, elk apparaat ernaar laten wijzen
Bereikbaarheidaltijd bereikbaarHeadscale moet bereikbaar zijn voor al je apparaten

De normale route is een Tailscale-account: installeer Tailscale op de server en op je apparaten, log in met hetzelfde account, klaar. In onze test gebruikten we in plaats daarvan Headscale, omdat we voor een test geen account wilden aanmaken: het is een open-source server die dezelfde rol speelt als de coördinatiedienst van Tailscale. Het netwerk zelf is hetzelfde: op beide machines draaide de officiële Tailscale-client (versie 1.104.5), die dezelfde WireGuard-tunnels bouwt, met welke controleserver hij ook praat.

Testopstelling

OnderdeelWaarde
ServerDebian 13, Intel UHD 770 (gedeelde GPU), 4 vCPU, Sunshine 2026.914, RetroArch, headless sway
ClientDebian 13, Moonlight 6.2, H.264 1080p 60 fps, hardwaredecodering
TailnetTailscale 1.104.5 op beide, Headscale 0.29.7 op de server (officiële .deb van GitHub)
Netwerkclient en server in hetzelfde datacenter: via internet komt de latentie van je verbinding erbij

1. Tailscale installeren op de server

Tailscale publiceert pakketten voor Debian 13:

curl -fsSL https://pkgs.tailscale.com/stable/debian/trixie.noarmor.gpg \
  -o /usr/share/keyrings/tailscale-archive-keyring.gpg
curl -fsSL https://pkgs.tailscale.com/stable/debian/trixie.tailscale-keyring.list \
  -o /etc/apt/sources.list.d/tailscale.list
apt update && apt install tailscale

Met een Tailscale-account voer je tailscale up uit en open je de link die het toont om in te loggen. Installeer daarna de Tailscale-app op je computer, telefoon of tv-box en log in met hetzelfde account.

Met Headscale (wat wij testten) installeer je de server vanaf de officiële GitHub-release, stel je server_url in in /etc/headscale/config.yaml en maak je daarna een gebruiker en een sleutel aan:

headscale users create gamer
headscale preauthkeys create --user 1 --reusable --expiration 2h
tailscale up --login-server https://headscale.example.com --authkey <key> --hostname retro-server

De client sluit aan met hetzelfde commando tailscale up --login-server … --authkey …. In onze test luisterde Headscale op het privéadres van de server, omdat beide machines in hetzelfde datacenter stonden. Voor echt gebruik moet Headscale bereikbaar zijn voor al je apparaten, via HTTPS: draai het op een machine met een publiek IPv4-adres (bijvoorbeeld met de optie dedicated IPv4), anders kan een apparaat zonder IPv6 het niet bereiken. Dat is de belangrijkste reden waarom een Tailscale-account eenvoudiger is.

2. De verbinding controleren

$ tailscale status
100.x.y.2  retro-client  gamer  linux  -
100.x.y.1  retro-server  gamer  linux  active; direct 203.0.113.10:41641, tx 750808 rx 128908072

$ tailscale ping 100.x.y.1
pong from retro-server (100.x.y.1) via 203.0.113.10:41641 in 1ms

direct betekent dat de twee machines zonder relay met elkaar praten. Via internet probeert Tailscale je apparaten ook rechtstreeks te verbinden door je router thuis heen (de server heeft daarvoor uitgaand IPv4). Lukt dat niet, dan gaat het verkeer via een Tailscale-relay (“DERP”): het werkt nog steeds, maar voegt latentie toe. tailscale status laat zien welke van de twee je hebt.

Een gewone ping door de tunnel duurde gemiddeld 1,7 ms (op zijn best 0,8 ms) tegenover 0,36 ms zonder Tailscale: de WireGuard-versleuteling voegt ruim minder dan een milliseconde toe, wat onzichtbaar is naast de latentie van een internetverbinding.

Staafdiagram: ping-retourtijd zonder Tailscale (0,36 ms) en via Tailscale (gemiddeld 1,73 ms)
Ping tussen de twee machines: 0,36 ms direct, gemiddeld 1,73 ms door de tunnel (op zijn best 0,79 ms, één piek van 8,8 ms).

3. Sunshine dicht houden voor internet

Het nut van het tailnet is dat Sunshine niet bereikbaar hoeft te zijn vanaf internet. Op de server blokkeert een kleine nftables-tabel de poorten van Sunshine, behalve op de interface tailscale0:

nft -f - <<'EOF'
table inet sunshine_tailnet_only {
  chain input {
    type filter hook input priority 0; policy accept;
    iifname "tailscale0" accept
    iifname "lo" accept
    tcp dport { 47984, 47989, 47990, 48010 } drop
    udp dport 47998-48010 drop
  }
}
EOF

We hebben het vanaf de client gecontroleerd: poort 47989 van Sunshine antwoordde niet meer op het normale adres van de server, en antwoordde wel (HTTP 200) op 100.x.y.1. Om Moonlight te koppelen, open je de webinterface van Sunshine via een SSH-tunnel (ssh -L 47990:localhost:47990 you@100.x.y.1).

4. Spelen: Moonlight op het 100.x-adres

Voeg in Moonlight de server toe via zijn tailnet-adres (hier 100.x.y.1), koppel hem en start een game. Moonlight herkende de server die het al kende en maakte verbinding zonder verdere instellingen. De tailnet-interface heeft een kleinere pakketgrootte (MTU van 1.280 bytes); daarvoor hoefden we niets te veranderen in Moonlight.

Om te zien of Tailscale iets verandert, streamden we dezelfde game vier keer, afwisselend via het normale adres van de server en via zijn tailnet-adres:

Moonlight, 1080p 60 fps H.264Zonder TailscaleVia Tailscale
Ontvangen framerate60,0 tot 60,4 fps60,0 fps
Verwerking op de server (opname + codering), gemiddeld7,5 tot 7,8 ms7,3 tot 7,4 ms
Verwerking op de server, max10,4 tot 10,6 ms10,5 tot 10,8 ms
Frames verloren door het netwerk of door jitter0%0%
Decodeertijd op de client0,23 ms0,24 tot 0,25 ms
Staafdiagram: serververwerking per frame in vier afwisselende runs, direct en via Tailscale
Vier streams van dezelfde game, afwisselend via het directe adres en het Tailscale-adres: gemiddeld 7,3 tot 7,8 ms in beide gevallen.
Moonlight streamt een game van de cloudserver via het Tailscale-adres, met de prestatiestatistieken
Via het tailnet: 60 fps, gemiddeld 7,3 ms verwerking op de server, geen enkel frame verloren.

Op de server gebruikte tijdens het streamen de Tailscale-dienst 2,8 tot 4,2% van één core, Sunshine 13 tot 17% en de emulator 3 tot 4%. In twee eerdere runs, gedaan terwijl andere testservers dezelfde GPU zwaar belastten, liep de verwerking op de server op tot gemiddeld 21 tot 27 ms: dat kwam doordat de GPU op dat moment gedeeld werd, niet door Tailscale, zoals de afwisselende runs hierboven laten zien.

Staafdiagram: server-CPU tijdens het streamen via Tailscale voor Sunshine, tailscaled en RetroArch, in procent van één kern
Server-CPU tijdens een 1080p-stream door de tunnel, in procent van één kern: de Tailscale-service kost minder dan de emulator.

5. Welk abonnement?

Tailscale zelf heeft bijna niets nodig. Waar het om gaat is de game: iGPU Start (2 vCPU, 8 GB RAM, € 14,99 per maand excl. btw) is genoeg voor retroconsoles; voor pc-games raden we iGPU Power aan (4 vCPU, 14 GB RAM, twee keer het GPU-aandeel van Start, € 29,99 per maand excl. btw).

Liever meteen spelen? Vraag het per e-mail bij je bestelling (contact@linuxgpu.eu): we kunnen de server leveren met Sunshine, de launcher van je games en Tailscale al geïnstalleerd (aan de serverkant). Jij installeert Moonlight en de Tailscale-app op je eigen apparaten.

Wat je erop kunt spelen: retrogaming met RetroArch, Sunshine en Moonlight, Windows 11 in de cloud met Sunshine en Moonlight en Windows-games op Linux met Wine.

Systemen die direct klaar zijn om te gamen. De systemen die we standaard installeren zijn hier al op ingericht: Debian 13 met een recente kernel (7.3), de Intel-GPU-drivers en Mesa (OpenGL, Vulkan, VA-API-videocodering), en Windows 11 (optie) met de grafische driver van Intel en Extern bureaublad dat op de GPU rendert. Geen drivers zoeken: installeer je game en Sunshine, en speel.

Probeer het

Bekijk de abonnementen: de optie dedicated IPv4 kost € 5 per maand, maar met Tailscale heb je die niet nodig om te spelen.