Gameserver met SteamCMD installeren
SteamCMD is de basis onder vrijwel elke gameserver op Steam. Deze handleiding toont de installatie, het anonieme inloggen, app_update met validate, het draaien als systemd-dienst en de typische foutbeelden.
Wie een gameserver op een eigen rootserver draait, komt bijna altijd bij hetzelfde gereedschap uit: SteamCMD. Of het nu Valheim, Rust, Counter-Strike 2, Palworld, Enshrouded of ARK is, de serverbestanden staan bij Valve en worden via dezelfde commandoregelclient opgehaald. Wie SteamCMD één keer netjes heeft opgezet, installeert elk volgend spel met een gewijzigd getal.
Deze handleiding behandelt precies de punten waar kortere tutorials ophouden: de 32-bits bibliotheken op 64-bits systemen, de verschillen tussen Debian, Ubuntu en de Red Hat-familie, de foutmeldingen letterlijk, een updateprocedure die de server niet bij elke cronloop opnieuw start, en het draaien als systemd-dienst.
Wat SteamCMD is en wat het niet is
SteamCMD is de Steam Console Client, een uitgeklede commandoregelversie van de Steam-client zonder grafische schil. Hij kan precies één ding goed: toepassingen uit het Steam-netwerk downloaden, bijwerken en de bestanden ervan controleren. Hij start geen server, hij configureert niets en hij kent de spellogica niet. Na de download staan de serverbestanden in een map, daarna is het betreffende spel aan de beurt.
Belangrijk om het hele bibliothekenverhaal te begrijpen: de bootstrapper van SteamCMD is tot op vandaag een 32-bits programma. Op een puur 64-bits systeem ontbreken de bijbehorende runtimebibliotheken, en precies daarop loopt de eerste start bij de meeste mensen stuk. De gedownloade serverbestanden zelf zijn bij moderne spellen bijna altijd 64-bits.
Voorbereiding: een eigen gebruiker in plaats van root
Gameserverprocessen draaien nooit als root. Ze nemen verbindingen vanaf het internet aan, halen bij veel titels mods uit de Steam Workshop op en voeren vreemde code uit. Een eigen gebruiker zonder rootrechten kost drie commando's en beperkt de schade.
useradd -m -d /home/steam -s /bin/bash steam
mkdir -p /home/steam/steamcmd
chown -R steam:steam /home/steam/steamcmd
SteamCMD waarschuwt daar bij een start als root uitdrukkelijk voor. Wie die waarschuwing negeert, krijgt het probleem later terug: zodra een map eenmaal van root is, mislukt de latere run als steam met een schrijffout, en de foutmelding wijst niet op de oorzaak.
Alle volgende commando's in dit artikel voert u als root in; ze schakelen via runuser -u steam -- over naar de dienstgebruiker. Op systemen met sudo werkt sudo -u steam net zo goed. Wilt u eerst de basisbeveiliging op orde brengen, dan vindt u de basis onder Nieuwe rootserver inrichten en SSH beveiligen.
De 32-bits bibliotheken, per systeem verschillend
Hier gaan de distributies uiteen, en algemene lijstjes met commando's van internet kloppen op dit punt geregeld niet.
Debian 12, Debian 13, Ubuntu 22.04 en Ubuntu 24.04
Op alle vier de systemen volstaat het pakket lib32gcc-s1 uit het hoofdarchief. Het is een amd64-pakket dat de 32-bits runtime meebrengt, en het heeft geen extra i386-architectuur nodig:
apt update
apt install -y ca-certificates curl tar file lib32gcc-s1 lib32stdc++6
lib32stdc++6 is voor SteamCMD zelf niet altijd nodig, maar heel wat oudere serverbinaries (alles op basis van de Source Engine, HLDS-titels, enkele Unity-servers) vragen erom. Het meteen mee installeren scheelt later een zoektocht naar de fout. file zit in geen enkel minimaal image en is verderop nodig voor de foutanalyse, daarom staat het meteen in de lijst.
AlmaLinux 9, Rocky Linux 9, RHEL 9 en Oracle Linux 9
Daar heten de pakketten anders en dragen ze het achtervoegsel .i686:
dnf -y update
dnf install -y --allowerasing glibc.i686 libstdc++.i686 tar file curl
Beide toevoegingen zijn op een verse minimale installatie nodig, anders breekt het commando af. De reden voor --allowerasing: EL9 brengt curl-minimal mee, en de volledige curl botst daarmee. Zonder die schakelaar eindigt de aanroep op AlmaLinux 9 en Rocky Linux 9 met package curl-minimal ... conflicts with curl provided by curl ... conflicting requests. Wie curl helemaal uit de lijst schrapt, bereikt het doel eveneens, want curl-minimal levert /usr/bin/curl al mee. De reden voor het voorgeschakelde dnf -y update: is de systeemstand ouder dan de pakketbronnen, dan botst het verse i686-pakket met het geïnstalleerde 64-bits pakket, op Rocky Linux 9 gemeten als file /usr/share/gcc-11/python/libstdcxx/v6/printers.py from install of libstdc++-11.5.0-14.el9.i686 conflicts with file from package libstdc++-11.4.1-2.1.el9.x86_64. Op Oracle Linux 9 doet geen van beide conflicten zich voor, daar is de volledige curl al geïnstalleerd.
EPEL is niet nodig, de pakketten zitten in de standaard pakketbronnen. Wilt u daarnaast gereedschap zoals htop, dan vindt u de weg daarheen onder htop installeren op AlmaLinux, Rocky en RHEL.
AlmaLinux 10, Rocky Linux 10 en RHEL 10 zijn ongeschikt voor SteamCMD
Dat is geen configuratieprobleem maar een doodlopende weg: RHEL 10 en de daarvan afgeleide distributies hebben de 32-bits x86-architectuur volledig geschrapt. Er zijn daar in geen enkele repository i686-pakketten, ook niet met --enablerepo=*, en het installatiecommando eindigt met No match for argument: glibc.i686. Omdat steamcmd.sh altijd de 32-bits bootstrapper linux32/steamcmd aanroept, valt daar niet omheen te werken. Kies voor een gameserver aan de Red Hat-kant daarom de EL9-familie, dus AlmaLinux 9, Rocky Linux 9 of Oracle Linux 9.
Een tweede struikelblok bij zeer uitgeklede EL-installaties: is alleen util-linux-core geïnstalleerd, dan ontbreekt runuser, dat in deze handleiding overal wordt gebruikt. Voer dan eerst dnf install -y util-linux uit. Op AlmaLinux 9, Rocky Linux 9, Oracle Linux 9 en op alle Debian- en Ubuntu-systemen is runuser al aanwezig.
Waarom niet gewoon het pakket steamcmd?
Ubuntu heeft steamcmd in de component multiverse staan, Debian in non-free, en in beide gevallen is het pakket uitsluitend voor de architectuur i386 gebouwd. Op een vers geïnstalleerde 64-bits server loopt u daarom gegarandeerd hiertegen aan:
E: Unable to locate package steamcmd
Om er überhaupt een kandidaat van te maken, moet u eerst de component vrijgeven en de vreemde architectuur activeren. Op Ubuntu is multiverse in de standaardinstallatie al actief, daar volstaan deze drie regels:
dpkg --add-architecture i386
apt update
apt-cache policy steamcmd
Op Debian ontbreekt bovendien de component. Zonder die component levert apt-cache policy steamcmd helemaal geen uitvoer op, dus zelfs geen foutmelding. Eerst moeten contrib en non-free in de pakketbronnen terecht, sinds Debian 12 gewoonlijk in /etc/apt/sources.list.d/debian.sources op de regel Components:. Pas daarna werkt de opvraging en meldt ze op Debian 12 de kandidaat 0~20180105-5 uit bookworm/non-free i386. De apt update tussen de architectuurschakelaar en de opvraging is verplicht: zonder die run bestaan de i386-pakketlijsten niet en blijft de kandidaat op (none) staan.
De moeite loont zelden. Het Debian-pakket is een zeer oude wrapper (versie 0~20180105-5 in Debian 13) die toch alleen dezelfde bootstrapper downloadt die u in twee regels zelf ophaalt. De handmatige installatie is op alle systemen identiek en daarmee beter te documenteren.
SteamCMD installeren en de eerste start duiden
runuser -u steam -- curl -sSLo /home/steam/steamcmd/steamcmd_linux.tar.gz https://media.steampowered.com/client/installer/steamcmd_linux.tar.gz
runuser -u steam -- tar -xzf /home/steam/steamcmd/steamcmd_linux.tar.gz -C /home/steam/steamcmd
runuser -u steam -- /home/steam/steamcmd/steamcmd.sh +quit
Het derde commando is de eigenlijke test. Bij de allereerste aanroep werkt SteamCMD zichzelf bij, toont een voortgangsindicator en sluit zichzelf af. Dat ziet er zo uit:
[ 0%] Checking for available update...
[----] Downloading update (0 of 58,393 KB)...
[100%] Download complete.
[----] Extracting package...
[----] Installing update...
[----] Verifying installation...
Steam Console Client (c) Valve Corporation - version 1751...
Loading Steam API...OK
Succescriterium: de laatste regel luidt Loading Steam API...OK. Verschijnt in plaats daarvan Loading Steam API...FAILED of breekt het proces meteen af, dan ontbreken de 32-bits bibliotheken uit de vorige paragraaf. De typische formulering daarbij is:
steamcmd.sh: line 41: /home/steam/steamcmd/linux32/steamcmd: No such file or directory
Die melding is misleidend, want het bestand bestaat wel degelijk. Wat niet wordt gevonden, is de 32-bits interpreter die het binary nodig heeft. Controleren kan met file /home/steam/steamcmd/linux32/steamcmd: de uitvoer luidt ELF 32-bit LSB shared object, Intel 80386, ... interpreter /lib/ld-linux.so.2 en noemt daarmee precies de ontbrekende interpreter. Ontbreekt file zelf met command not found, dan is het in de installatiestap hierboven vergeten. De variant error while loading shared libraries: libstdc++.so.6 wijst op hetzelfde probleem, alleen een laag later.
Anoniem inloggen tegenover inloggen met een account
De allermeeste dedicated servers zijn als eigen, gratis Steam-toepassing gepubliceerd en zijn zonder inloggegevens te downloaden:
+login anonymous
Dat is het normale geval en de weg die u altijd als eerste moet proberen. Geen wachtwoord op de server, geen Steam Guard, geen geblokkeerde accounts na een serververhuizing.
Inloggen met een account is alleen nodig wanneer de serverbuild aan het bezit van het spel is gekoppeld. Dat herkent u aan deze melding:
ERROR! Failed to install app 'ID' (No subscription)
No subscription betekent altijd: dit account mag deze app niet downloaden. Bij anoniem inloggen betekent het dat er een echt account met een gekocht spel nodig is. Bij een echt account betekent het dat de licentie ontbreekt of dat de verkeerde app-ID is gebruikt.
Het inloggen met een account verloopt interactief, omdat Steam Guard om een code vraagt:
/home/steam/steamcmd/steamcmd.sh +login mijngebruikersnaam
Na de eenmalige bevestiging staat er een sentry-bestand onder ~/.steam, daarna werken ook niet-interactieve aanroepen. Drie punten die in de praktijk pijn doen: gebruik hiervoor een apart Steam-account dat alleen de serverlicentie bezit. Zet het wachtwoord nooit in een cron-script. En houd er rekening mee dat Steam na langere inactiviteit of een IP-wissel opnieuw om een bevestiging vraagt, waardoor een automatische update stilzwijgend blijft hangen.
Los daarvan staat het Game Server Login Token (GSLT). Dat heeft niets met de download te maken, maar bepaalt of de draaiende server openbaar in de serverlijst verschijnt. Bij Counter-Strike 2 en andere Valve-titels maakt u het aan in het Steam-account en zet u het in de serverconfiguratie, niet in SteamCMD.
Een spel installeren: volgorde, validate en branches
SteamCMD werkt de +-argumenten strikt van links naar rechts af. Daaruit volgt de allerbelangrijkste regel:
+force_install_dirmoet vóór+app_updatestaan. Staat het erachter, dan belanden de bestanden in het standaardpad en blijft de opgegeven map leeg.
Een volledige aanroep, hier aan de hand van de Valheim-server met app-ID 896660:
runuser -u steam -- mkdir -p /home/steam/valheim
runuser -u steam -- /home/steam/steamcmd/steamcmd.sh +force_install_dir /home/steam/valheim +login anonymous +app_update 896660 validate +quit
Let erop dat validate zonder plusteken wordt geschreven; het is een argument van app_update en geen eigen commando. validate vergelijkt elk bestand met de controlesom uit het depot en haalt afwijkingen opnieuw op. Dat is zinvol bij de eerste installatie, na een afgebroken download en bij vreemde crashes. Bij elke routineupdate is het overbodig en duur, omdat de volledige inhoud wordt uitgelezen. Twee bijwerkingen moet u kennen: zelf gewijzigde bestanden die bij het depot horen, worden teruggezet, en bij spellen met mods in de installatiemap kan validate vreemde bestanden verwijderen.
Ter controle dient de slotregel:
Success! App '896660' fully installed.
Een andere branch, bijvoorbeeld een openbare testtak, hangt u direct achter app_update:
+app_update 896660 -beta public-test validate
Voor een met een wachtwoord beveiligde tak komt -betapassword erbij. De weg terug naar de standaardversie is -beta none; de parameter simpelweg weglaten volstaat niet, omdat de branchkeuze in het manifest opgeslagen blijft.
Als het misgaat: de foutmeldingen letterlijk
SteamCMD meldt problemen als hexadecimale status, en die zegt zonder vertaalslag niets. De meest voorkomende:
Error! App '...' state is 0x202 after update job: te weinig opslagruimte. Controleer dat metdf -h /home/steam. Denk eraan dat SteamCMD naast de doelmap ook ruimte nodig heeft voor de tijdelijke downloadopslag, in de regel in hetzelfde bestandssysteem ondersteamapps/downloading. Bij grote titels kan de piekbehoefte tijdens de update bijna het dubbele van de eindomvang bedragen. Is de schijf vol, dan helpt Volle schijf onder Linux opruimen.Error! App '...' state is 0x606 after update job: schrijffout. In negen van de tien gevallen zijn het de rechten en niet de hardware. Klassieker: de eerste run gebeurde als root, de tweede alssteam. Herstellen doet u metchown -R steam:steam /home/steam. Bij symbolische links naar een tweede schijf moet ook het doel van de dienstgebruiker zijn.Error! App '...' state is 0x402 after update job: geen bruikbare verbinding met de contentservers van Steam. Meestal een uitgaande firewallregel of een probleem met de naamserver. SteamCMD heeft uitgaand TCP 443 nodig en daarnaast 27015 tot en met 27050.No subscription: een licentiekwestie, zie de vorige paragraaf.Failed to load steamclient.soof[S_API FAIL] SteamAPI_Init(): het serverbinary zoekt de Steam-bibliotheek op een vaste plek die SteamCMD niet vult. Dit raakt vrijwel alle Unreal Engine-servers en daarnaast Rust, Palworld en V Rising. De oplossing bestaat uit twee verwijzingen in de thuismap van de dienstgebruiker.
runuser -u steam -- mkdir -p /home/steam/.steam/sdk64
runuser -u steam -- ln -sf /home/steam/steamcmd/linux64/steamclient.so /home/steam/.steam/sdk64/steamclient.so
runuser -u steam -- mkdir -p /home/steam/.steam/sdk32
runuser -u steam -- ln -sf /home/steam/steamcmd/linux32/steamclient.so /home/steam/.steam/sdk32/steamclient.so
Omdat het verwijzingen naar de SteamCMD-map zijn, blijven ze na een zelfupdate van SteamCMD geldig. Een veelgemaakte vervolgfout is het aanmaken van deze mappen als root, waardoor de dienst ze later niet kan lezen.
Blijft een download hardnekkig hangen, dan is de laatste hefboom het verwijderen van steamapps/appmanifest_<ID>.acf in de installatiemap. Daarna houdt SteamCMD de app voor niet geïnstalleerd en haalt hij die volledig opnieuw op.
Updates automatiseren zonder de server zinloos te herstarten
Het gangbare advies luidt: laat één keer per dag via cron app_update lopen en herstart de dienst. Dat kost elke dag een onderbreking, ook wanneer er helemaal geen update is. Beter is een vergelijking van de build-ID. De geïnstalleerde staat in het manifestbestand, de actuele levert app_info_print:
runuser -u steam -- /home/steam/steamcmd/steamcmd.sh +login anonymous +app_info_update 1 +app_info_print 896660 +quit
Daar maakt u een script van onder /usr/local/sbin/steam-update.sh:
#!/bin/bash
set -euo pipefail
APPID=896660
DIR=/home/steam/valheim
CMD=/home/steam/steamcmd/steamcmd.sh
UNIT=valheim
MANIFEST="$DIR/steamapps/appmanifest_${APPID}.acf"
installed=$(awk '/"buildid"/ {gsub(/"/,"",$2); print $2; exit}' "$MANIFEST" 2>/dev/null || echo 0)
latest=$(runuser -u steam -- "$CMD" +login anonymous +app_info_update 1 +app_info_print "$APPID" +quit \
| awk '/"public"/{f=1} f && /"buildid"/ {gsub(/"/,"",$2); print $2; exit}')
if [ -z "$latest" ]; then
echo "Kon de actuele build-ID niet bepalen, wordt afgebroken."
exit 1
fi
if [ "$installed" = "$latest" ]; then
echo "Actueel (build $installed), geen herstart."
exit 0
fi
echo "Update van $installed naar $latest"
systemctl stop "$UNIT"
runuser -u steam -- "$CMD" +force_install_dir "$DIR" +login anonymous +app_update "$APPID" +quit
systemctl start "$UNIT"
Het script herstart alleen wanneer er echt iets is veranderd, en breekt netjes af wanneer Steam op dat moment niet antwoordt. Zonder die controle zou een leeg resultaat van de opvraging als update worden gelezen en zou de server zonder reden worden gestopt. Uitvoeren doet u het via cron of beter via een systemd-timer; de basis daarvoor staat onder Cronjob onder Linux instellen.
Houd er rekening mee dat veel spellen na een serverupdate ook bijgewerkte clients vereisen. Een automatische update midden in de drukste speeluren gooit alle spelers eruit. Plan de run daarom in de vroege ochtenduren.
Als systemd-dienst draaien
Een gameserver in een screen-sessie overleeft geen herstart. Een unit onder /etc/systemd/system/valheim.service lost dat op:
[Unit]
Description=Valheim Dedicated Server
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=steam
Group=steam
WorkingDirectory=/home/steam/valheim
Environment=LD_LIBRARY_PATH=/home/steam/valheim/linux64
Environment=SteamAppId=892970
ExecStart=/home/steam/valheim/valheim_server.x86_64 -nographics -batchmode -name "KernelHost" -port 2456 -world "Dedicated" -password "wijzigMij"
Restart=on-failure
RestartSec=10
KillSignal=SIGINT
TimeoutStopSec=90
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now valheim
systemctl status valheim
Twee regels daarin zijn belangrijker dan ze eruitzien. KillSignal=SIGINT zorgt ervoor dat de server bij het stoppen opslaat, want heel wat spelservers negeren SIGTERM en verliezen bij een hardhandige afsluiting de voortgang van de laatste minuten. TimeoutStopSec geeft de server daar de tijd voor. Een uitvoerige uitleg van alle velden vindt u onder systemd-service aanmaken, de aanpak bij een Java-server onder Minecraft-server automatisch starten.
Sterft de server bij het starten meteen door een tekort aan werkgeheugen, dan helpt een blik op Swap instellen. De poorten horen daarna in de firewall, zie UFW instellen, waarbij spelservers bijna altijd UDP nodig hebben en een regel met alleen TCP doorgaans de reden is dat de server wel draait maar niemand verbinding kan maken.
App-ID's van de gangbare spellen
De ID is het enige onderdeel dat per spel verandert. Anoniem te downloaden zijn onder meer:
- 232250 Team Fortress 2
- 4020 Garry's Mod
- 222860 Left 4 Dead 2
- 730 Counter-Strike 2 (client en server zijn sinds de overstap van CS:GO dezelfde app, navenant groot is de download)
- 258550 Rust
- 376030 ARK: Survival Evolved
- 896660 Valheim
- 2394010 Palworld
- 2278520 Enshrouded
- 1829350 V Rising
- 294420 7 Days to Die
- 380870 Project Zomboid
- 1690800 Satisfactory
- 581330 Insurgency: Sandstorm
- 233780 Arma 3
- 1007 Steamworks SDK Redistributables, piepklein en daarom ideaal als functietest van de installatie
Verwar de server-app niet met de spel-app. Bij ARK is 346110 bijvoorbeeld het spel en 376030 de server. Wie een ID zoekt, vindt die in de Dedicated Servers List in de Valve Developer Wiki of via SteamDB. De snelle test is altijd dezelfde: een anonieme app_update, en komt daar No subscription uit, dan was het de client-ID.
Waaraan u ziet dat het echt draait
Vier controles, in deze volgorde:
- Bestanden aanwezig.
du -sh /home/steam/valheimmoet een plausibele omvang tonen, en insteamapps/appmanifest_896660.acfstaat eenbuildid. Een map van een paar megabyte betekent een afgebroken download. - Het proces leeft langer dan een minuut.
systemctl status valheimtoontactive (running). Een dienst die elke seconde opnieuw start, staat opactivating (auto-restart); dan levertjournalctl -u valheim -n 50de reden. - De poort staat open, en wel als UDP.
ss -ulpn | grep 2456moet het proces noemen. Niets te zien betekent: de server is nog bezig met initialiseren of is aan het verkeerde adres gebonden. - Van buitenaf bereikbaar. Pas daarna controleert u de firewall en maakt u vanuit het spel verbinding. Veel titels hebben daarnaast een query-poort nodig; bij Valheim is dat de serverpoort plus één.
Kloppen deze vier punten, dan is de basis in orde en is al het overige spelconfiguratie. Op een KernelHost-rootserver in het datacenter maincubes in Frankfurt am Main komt daar de DDoS-bescherming uit ons eigen netwerk bij, en dat is juist relevant bij gameservers die openbaar in de serverlijst staan, omdat zo'n lijst het IP-adres voor iedereen zichtbaar maakt. Achtergronden daarover vindt u onder Server beschermen tegen DDoS-aanvallen.
Veelgestelde vragen
Waarom start SteamCMD op mijn 64-bits server niet?
Heb ik een Steam-account nodig voor een gameserver?
Wat betekent "App state is 0x606 after update job"?
Moet ik validate bij elke update meegeven?
Hoe werk ik automatisch bij zonder de server dagelijks te herstarten?
Waarom vindt apt het pakket steamcmd niet?
2026 KernelHost GmbH. Alle rechten voorbehouden. Deze handleiding is auteursrechtelijk beschermd. Publicatie op andere websites, geheel, gedeeltelijk of in bewerkte vorm, is zonder onze schriftelijke toestemming niet toegestaan. Citeren met bronvermelding en link is uitdrukkelijk welkom.

