Sommige Steam-games leveren alleen een Windows dedicated server. Er zit geen Linux-binary in de depot, dus het gebruikelijke advies is "draai het op een Windows-machine." Dat hoeft niet. Met Wine kun je de Windows-server op een gewone Linux-machine draaien, en die verbindt gewoon met Steam en accepteert echte spelers. Dit is precies het recept dat bij ons werkte, met Alien Swarm: Reactive Drop (een gratis Source co-op game) als voorbeeld. Dezelfde aanpak zou moeten werken voor andere Windows-only Source dedicated servers.
Controleer eerst of er echt geen Linux-server bestaat
Ga nergens vanuit. Vraag het rechtstreeks aan Steam voordat je naar Wine grijpt. Wijs steamcmd naar de app en lees de platformlijst uit:
steamcmd +login anonymous +app_info_print <appid> +quit \
| grep -iE "oslist|name"Als de dedicated-server app alleen "oslist windows" heeft, bestaat er geen native Linux-build om op terug te vallen. Je kunt ook proberen een Linux-installatie te forceren; als er echt geen Linux-depot is, mislukt dat meteen:
steamcmd +@sSteamCmdForcePlatformType linux \
+login anonymous +app_update <appid> validate +quit
# ERROR! Failed to install app '<appid>' (Missing configuration)Die foutmelding, en het feit dat er geen ELF-bestanden terechtkomen, bevestigt het. Wine is dan de weg. Installeer de server ÉN app 1007 (de Steamworks Common Redistributables) in dezelfde map, met platformtype windows. App 1007 levert de Steam-DLL's die de server nodig heeft, en je ziet zo in stap 2 waarom:
steamcmd +@sSteamCmdForcePlatformType windows +login anonymous \
+force_install_dir /path/to/server \
+app_update <appid> validate \
+app_update 1007 validate \
+quitWaarom de simpele Wine-aanpak mislukt
De server direct vanuit Wine draaien loopt meteen tegen twee muren aan:
- Geen console: de server verwacht een echte terminal. Pipen vanuit /dev/null geeft CTextConsoleWin32::GetLine: !GetNumberOfConsoleInputEvents en hij start nooit op.
- Kan Steam-bibliotheek niet laden: zelfs als hij opstart, print hij "Unable to load Steam support library" en registreert hij zich nooit bij Steam, waardoor niemand hem kan vinden of joinen.
Beide zijn op te lossen. Hier is het volledige recept.
Stap 1: geef het een echte terminal (PTY)
Een headless machine heeft geen terminal, en de Windows console-server weigert zonder terminal te draaien. Wikkel de launch in script, dat een pseudo-terminal toewijst, en gebruik Xvfb voor een nepdisplay:
Xvfb :99 -screen 0 1024x768x24 &
export DISPLAY=:99 WINEPREFIX=/wine
script -qfc "wine srcds_console.exe -console -condebug \
-game <gamedir> +map <map> -port 27015" /tmp/server.logDaarmee laadt de server al een map en bindt hij zijn gamepoort. Maar hij kan nog steeds niet met Steam praten.
Stap 2: twee Steam-DLL's, twee verschillende bronnen
De Source-engine heeft ZOWEL steamclient.dll ALS steam.dll nodig naast de server-exe, en dit is de valkuil die ons een volledige extra debugronde kostte: ze komen uit VERSCHILLENDE bronnen, en app 1007 geeft je er maar ÉÉN van.
- steamclient.dll: komt van app 1007 (Steamworks Common Redistributables), die je in Stap 1 hebt geïnstalleerd. Canoniek, versie-gematcht, onderhouden door Valve.
- steam.dll: zit NIET in app 1007. Het is onderdeel van de Steam CLIENT, en de enige nette manier om het te krijgen is om de Windows steamcmd.exe eenmalig onder Wine te draaien. Die update zichzelf en zet steam.dll (plus steamclient.dll) neer in zijn eigen map.
Bootstrap dus steam.dll met steamcmd.exe onder Wine, en kopieer daarna beide DLL's naast de server-exe:
# steam.dll: run Windows steamcmd once under Wine (needs Xvfb for a display)
cd "$WINEPREFIX/drive_c/steamcmd"
curl -fsSLO https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip
unzip -o steamcmd.zip
DISPLAY=:99 wine steamcmd.exe +quit # lays down steam.dll + steamclient.dll
# place both next to the server exe
cd /path/to/server
cp "$WINEPREFIX/drive_c/steamcmd/steam.dll" .
[ -f steamclient.dll ] || cp "$WINEPREFIX/drive_c/steamcmd/steamclient.dll" .Stap 3: waarom steam.dll het cruciale onderdeel is
Dit is het deel dat bijna niemand opschrijft. De foutmelding zegt "Unable to load Steam support library", en daarmee wordt niet steamclient.dll bedoeld, maar steam.dll. De Source-engine zoekt naar steam.dll naast zijn eigen executable om de hele Steam-keten op te starten. Met alleen steamclient.dll aanwezig (wat alles is wat app 1007 je geeft) blijft het mislukken; zodra steam.dll naast de .exe staat, slaat de log om van mislukking naar succes:
Connection to Steam servers successful.
VAC secure mode is activated.VAC activeert alleen als de server correct is ingelogd als gameserver, dus die regel is je bewijs dat de registratie is gelukt. De meeste Source-servers loggen hier anoniem in en hebben geen Game Server Login Token (GSLT) nodig. Alleen een paar games (zoals CS2) vereisen er een.
De valkuil: A2S blijft stil terwijl de server prima werkt
Dit is het addertje onder het gras dat ons de meeste tijd kostte, en de reden dat we het bijna opgaven. Onder Wine beantwoordt de server GEEN A2S_INFO, de UDP-query die tools gebruiken om de naam, map en spelersaantal van een server uit te lezen. Vraag het op en elke poort geeft een timeout, zelfs vanaf dezelfde machine. Als je A2S gebruikt als health check, lijkt de server helemaal dood.
Hij is niet dood. Dat A2S stil blijft onder Wine, weerhoudt echte spelers er niet van om te joinen. De in-game serverbrowser haalt servers op uit Steams masterlijst (waar de server zelf naartoe pusht), en een directe verbinding gebruikt het spelprotocol, niet A2S. De echte test is dus of een client kan verbinden, niet of een query wordt beantwoord. Toen we het uiteindelijk probeerden, verbond een echte speler meteen bij de eerste poging en kon gewoon spelen:
Client "player" connected (10.0.0.5:27005).
1/ 8 on map <mapname>De praktische les: gebruik bij een Wine-gehoste server geen A2S voor je health check. Controleer iets dat écht de status weergeeft, zoals de regel "VAC secure mode is activated" in de log, de regel met het spelersaantal, of gewoon of de UDP-poort van de game open staat.
Werkt dit voor elke Windows-game?
Wees eerlijk over de reikwijdte. Wij hebben dit bewezen op een Source-engine server, en hetzelfde recept (PTY, een met steamcmd gebouwde runtime, steam.dll naast de exe) zou moeten werken voor andere Windows-only Source dedicated servers. Games op andere engines integreren Steam anders, dus behandel die als aparte experimenten. Twee dingen kun je hoe dan ook verwachten: booten duurt langer dan native Linux (Wine plus de steamcmd-stap plus de Steam-login), en het stille A2S-gedrag hierboven zal waarschijnlijk voor ze allemaal gelden.
Of sla dit allemaal over
Dit is het soort yak shave dat een hele middag opslokt. Als je gewoon de server wilt, draaien wij de Linux-fleet en de Wine-plumbing voor je, per uur, met een publiek IP-adres vanaf de eerste minuut. Bekijk wat we hosten op 2hours.gg.