Instalacja serwera gry przez SteamCMD: biblioteki 32-bitowe, validate i usługa systemd
SteamCMD to wspólna podstawa niemal wszystkich serwerów gier na Steam. Ten poradnik pokazuje instalację, logowanie anonimowe, app_update z validate, pracę jako usługa systemd oraz typowe komunikaty o błędach.
Jeśli prowadzisz serwer gry na własnym serwerze root, prędzej czy później trafiasz na to samo narzędzie: SteamCMD. Nieważne, czy chodzi o Valheim, Rust, Counter-Strike 2, Palworld, Enshrouded czy ARK: pliki serwera leżą u Valve i pobiera się je tym samym klientem konsolowym. Gdy raz porządnie skonfigurujesz SteamCMD, każdą kolejną grę zainstalujesz, zmieniając tylko jedną liczbę.
Ten poradnik obejmuje dokładnie te miejsca, w których krótsze tutoriale się kończą: biblioteki 32-bitowe na systemach 64-bitowych, różnice między Debianem, Ubuntu i rodziną Red Hata, dosłowne brzmienie komunikatów o błędach, procedurę aktualizacji, która nie restartuje serwera przy każdym przebiegu crona, oraz pracę w formie usługi systemd.
Czym SteamCMD jest, a czym nie jest
SteamCMD to Steam Console Client, czyli odchudzona wersja konsolowa klienta Steam, bez interfejsu graficznego. Dobrze robi dokładnie jedną rzecz: pobiera aplikacje z sieci Steam, aktualizuje je i sprawdza ich pliki. Nie uruchamia żadnego serwera, niczego nie konfiguruje i nie zna logiki gry. Po pobraniu pliki serwera lądują w katalogu, a dalej zaczyna się już sama gra.
Żeby zrozumieć cały temat bibliotek, trzeba wiedzieć jedno: bootstrapper SteamCMD do dziś jest programem 32-bitowym. Na czystym systemie 64-bitowym brakuje mu odpowiednich bibliotek uruchomieniowych i właśnie na tym u większości osób wykłada się pierwsze uruchomienie. Same pobrane pliki serwera są w nowoczesnych grach niemal zawsze 64-bitowe.
Przygotowanie: własny użytkownik zamiast roota
Procesy serwera gry nigdy nie działają jako root. Przyjmują połączenia z internetu, w wielu tytułach dociągają mody ze Steam Workshop i wykonują obcy kod. Osobny, nieuprzywilejowany użytkownik kosztuje trzy polecenia i ogranicza szkody.
useradd -m -d /home/steam -s /bin/bash steam
mkdir -p /home/steam/steamcmd
chown -R steam:steam /home/steam/steamcmd
SteamCMD wyraźnie ostrzega przed startem na koncie roota. Jeśli zignorujesz to ostrzeżenie, problem wróci później: gdy katalog raz będzie należał do roota, kolejny przebieg jako steam zakończy się błędem zapisu, a sam komunikat w żaden sposób nie wskaże przyczyny.
Wszystkie kolejne polecenia w tym artykule wpisujesz jako root, a na użytkownika usługi przełączasz się przez runuser -u steam --. Na systemach z sudo tak samo zadziała sudo -u steam. Jeśli chcesz najpierw zająć się podstawowym zabezpieczeniem, znajdziesz je w poradnikach Konfiguracja nowego serwera root oraz Zabezpieczenie SSH.
Biblioteki 32-bitowe, różne w zależności od systemu
W tym miejscu drogi dystrybucji się rozchodzą, a zbiorcze listy poleceń krążące po sieci są tu regularnie błędne.
Debian 12, Debian 13, Ubuntu 22.04 i Ubuntu 24.04
Na wszystkich czterech systemach wystarczy pakiet lib32gcc-s1 z głównego archiwum. To pakiet amd64, który przynosi ze sobą środowisko uruchomieniowe 32-bitowe, i nie wymaga dodatkowej architektury i386:
apt update
apt install -y ca-certificates curl tar file lib32gcc-s1 lib32stdc++6
lib32stdc++6 nie zawsze jest potrzebny samemu SteamCMD, ale wymaga go sporo starszych plików binarnych serwerów (wszystko oparte na Source Engine, tytuły HLDS, część serwerów Unity). Zainstalowanie go od razu oszczędza późniejszego szukania błędów. file nie siedzi w żadnym z obrazów minimalnych, a niżej przyda się do diagnostyki, dlatego od razu trafia na listę.
AlmaLinux 9, Rocky Linux 9, RHEL 9 i Oracle Linux 9
Tam pakiety nazywają się inaczej i noszą przyrostek .i686:
dnf -y update
dnf install -y --allowerasing glibc.i686 libstdc++.i686 tar file curl
Oba dodatki są potrzebne na świeżej instalacji minimalnej, inaczej polecenie przerwie pracę. Powód dla --allowerasing: EL9 przynosi ze sobą curl-minimal, a pełny curl z nim koliduje. Bez tego przełącznika wywołanie na AlmaLinux 9 i Rocky Linux 9 kończy się komunikatem package curl-minimal ... conflicts with curl provided by curl ... conflicting requests. Kto skreśli curl całkiem z listy, też dojdzie do celu, bo curl-minimal dostarcza już /usr/bin/curl. Powód dla poprzedzającego dnf -y update: jeśli stan systemu jest starszy niż repozytoria, świeży pakiet i686 koliduje z zainstalowanym pakietem 64-bitowym, na Rocky Linux 9 zmierzone jako 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. Na Oracle Linux 9 nie występuje żaden z tych dwóch konfliktów, bo pełny curl jest tam już zainstalowany.
EPEL nie jest potrzebny, pakiety leżą w standardowych repozytoriach. Jeśli chcesz dodatkowo narzędzia w rodzaju htop, drogę do nich opisuje Instalacja htopa na AlmaLinux, Rocky i RHEL.
AlmaLinux 10, Rocky Linux 10 i RHEL 10 nie nadają się do SteamCMD
To nie jest problem konfiguracji, tylko ślepy zaułek: RHEL 10 i wywodzące się z niego dystrybucje całkowicie skreśliły 32-bitową architekturę x86. Nie ma tam pakietów i686 w żadnym repozytorium, także przy --enablerepo=*, a polecenie instalacji kończy się komunikatem No match for argument: glibc.i686. Ponieważ steamcmd.sh zawsze wywołuje 32-bitowy bootstrapper linux32/steamcmd, nie da się tego obejść. Na serwer gry po stronie Red Hata wybierz więc rodzinę EL9, czyli AlmaLinux 9, Rocky Linux 9 albo Oracle Linux 9.
Druga pułapka bardzo odchudzonych instalacji EL: jeśli zainstalowany jest tylko util-linux-core, brakuje polecenia runuser, którego używamy w tym poradniku na każdym kroku. Wykonaj wtedy najpierw dnf install -y util-linux. Na AlmaLinux 9, Rocky Linux 9, Oracle Linux 9 oraz na wszystkich systemach Debian i Ubuntu runuser jest już dostępny.
Dlaczego nie po prostu pakiet steamcmd?
Ubuntu trzyma steamcmd w komponencie multiverse, Debian w non-free. W obu przypadkach pakiet zbudowano wyłącznie dla architektury i386. Na świeżo zainstalowanym serwerze 64-bitowym niezawodnie wpadasz więc na:
E: Unable to locate package steamcmd
Żeby pakiet w ogóle stał się kandydatem, trzeba najpierw odblokować komponent i włączyć obcą architekturę. Na Ubuntu multiverse jest w instalacji standardowej już aktywny, więc wystarczą trzy wiersze:
dpkg --add-architecture i386
apt update
apt-cache policy steamcmd
Na Debianie brakuje dodatkowo samego komponentu. Bez niego apt-cache policy steamcmd nie zwraca w ogóle żadnego wyniku, nawet komunikatu o błędzie. Najpierw do źródeł pakietów muszą trafić contrib oraz non-free, od Debiana 12 zwykle w pliku /etc/apt/sources.list.d/debian.sources w wierszu Components:. Dopiero potem zapytanie zadziała i na Debianie 12 zgłosi kandydata 0~20180105-5 z bookworm/non-free i386. Polecenie apt update między przełącznikiem architektury a zapytaniem jest obowiązkowe: bez tego przebiegu listy pakietów i386 nie istnieją, a kandydat pozostaje (none).
Ten wysiłek rzadko się opłaca. Pakiet Debiana to bardzo stary wrapper (wersja 0~20180105-5 w Debianie 13), który i tak pobiera tylko ten sam bootstrapper, jaki ściągniesz sam dwoma wierszami. Instalacja ręczna jest identyczna na wszystkich systemach, więc łatwiej ją udokumentować.
Instalacja SteamCMD i odczytanie pierwszego uruchomienia
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
Trzecie polecenie to właściwy test. Przy pierwszym wywołaniu SteamCMD dociąga sam siebie, pokazuje pasek postępu i kończy pracę. Wygląda to tak:
[ 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
Kryterium sukcesu: ostatni wiersz brzmi Loading Steam API...OK. Jeśli zamiast tego pojawi się Loading Steam API...FAILED albo proces od razu przerwie pracę, brakuje bibliotek 32-bitowych z poprzedniej sekcji. Typowe brzmienie komunikatu to:
steamcmd.sh: line 41: /home/steam/steamcmd/linux32/steamcmd: No such file or directory
Ten komunikat wprowadza w błąd, bo plik jak najbardziej istnieje. Nie znajduje się natomiast 32-bitowy interpreter, którego potrzebuje plik binarny. Sprawdzisz to poleceniem file /home/steam/steamcmd/linux32/steamcmd: wynik brzmi ELF 32-bit LSB shared object, Intel 80386, ... interpreter /lib/ld-linux.so.2 i wskazuje tym samym dokładnie brakujący interpreter. Jeśli samo file zgłasza command not found, zostało pominięte w kroku instalacji powyżej. Wariant error while loading shared libraries: libstdc++.so.6 pokazuje ten sam problem, tylko o poziom później.
Logowanie anonimowe kontra logowanie na konto
Zdecydowana większość serwerów dedykowanych jest opublikowana jako osobna, bezpłatna aplikacja Steam i da się je pobrać bez danych dostępowych:
+login anonymous
To przypadek standardowy i droga, którą zawsze warto sprawdzić najpierw. Żadnego hasła na serwerze, żadnego Steam Guard, żadnych zablokowanych kont po przeprowadzce serwera.
Logowanie na konto jest konieczne tylko wtedy, gdy build serwera jest powiązany z posiadaniem gry. Poznasz to po takim komunikacie:
ERROR! Failed to install app 'ID' (No subscription)
No subscription zawsze znaczy jedno: to konto nie ma prawa pobrać tej aplikacji. Przy logowaniu anonimowym oznacza to, że potrzebne jest prawdziwe konto z kupioną grą. Przy prawdziwym koncie oznacza, że brakuje licencji albo użyto błędnego App ID.
Logowanie na konto przebiega interaktywnie, bo Steam Guard żąda kodu:
/home/steam/steamcmd/steamcmd.sh +login mojanazwauzytkownika
Po jednorazowym potwierdzeniu w katalogu ~/.steam leży plik sentry i od tej chwili działają także wywołania nieinteraktywne. Trzy punkty, które w praktyce potrafią zaboleć: załóż do tego celu osobne konto Steam, które trzyma wyłącznie licencję serwera. Nigdy nie wpisuj hasła do skryptu crona. I licz się z tym, że po dłuższej bezczynności albo zmianie adresu IP Steam znów poprosi o potwierdzenie, przez co automatyczna aktualizacja po cichu zawiśnie.
Zupełnie osobną sprawą jest Game Server Login Token (GSLT). Nie ma on nic wspólnego z pobieraniem, tylko z tym, czy działający serwer pojawi się publicznie na liście serwerów. W Counter-Strike 2 i innych tytułach Valve generujesz go na koncie Steam i wpisujesz w konfiguracji serwera, a nie w SteamCMD.
Instalacja gry: kolejność, validate i gałęzie
SteamCMD przetwarza argumenty z + ściśle od lewej do prawej. Wynika z tego najważniejsza reguła w całym poradniku:
+force_install_dirmusi stać przed+app_update. Jeśli stoi za nim, pliki wylądują w ścieżce domyślnej, a wskazany katalog pozostanie pusty.
Pełne wywołanie, tutaj na przykładzie serwera Valheim z 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
Zwróć uwagę, że validate zapisuje się bez plusa: to argument polecenia app_update, a nie osobne polecenie. validate porównuje każdy plik z sumą kontrolną z depotu i pobiera od nowa wszystko, co się różni. Ma to sens przy pierwszej instalacji, po przerwanym pobieraniu oraz przy dziwnych awariach. Przy każdej rutynowej aktualizacji jest zbędne i kosztowne, bo odczytywany jest cały zasób. Warto znać dwa skutki uboczne: samodzielnie zmienione pliki należące do depotu wracają do stanu pierwotnego, natomiast w grach z modami w katalogu instalacyjnym validate potrafi usunąć obce pliki.
Kontrolą powodzenia jest wiersz końcowy:
Success! App '896660' fully installed.
Inną gałąź, na przykład publiczną gałąź testową, dopinasz bezpośrednio do app_update:
+app_update 896660 -beta public-test validate
Dla gałęzi chronionej hasłem dochodzi jeszcze -betapassword. Droga powrotna do wersji standardowej to -beta none; samo pominięcie parametru nie wystarczy, bo wybór gałęzi zostaje zapisany w manifeście.
Gdy coś pójdzie nie tak: komunikaty o błędach dosłownie
SteamCMD zgłasza problemy jako status szesnastkowy, który bez rozszyfrowania nic nie mówi. Najczęstsze z nich:
Error! App '...' state is 0x202 after update job: za mało miejsca na dysku. Sprawdź poleceniemdf -h /home/steam. Pamiętaj, że poza katalogiem docelowym SteamCMD potrzebuje miejsca na bufor pobierania, z reguły w tym samym systemie plików podsteamapps/downloading. Przy dużych tytułach szczytowe zapotrzebowanie w trakcie aktualizacji sięga niemal dwukrotności rozmiaru końcowego. Gdy dysk jest pełny, pomoże Pełny dysk w Linuksie: jak zwolnić miejsce.Error! App '...' state is 0x606 after update job: błąd zapisu. W dziewięciu przypadkach na dziesięć chodzi o uprawnienia, a nie o sprzęt. Klasyk: pierwszy przebieg odbył się jako root, drugi jakosteam. Naprawa poleceniemchown -R steam:steam /home/steam. Przy dowiązaniach symbolicznych na drugi dysk także cel musi należeć do użytkownika usługi.Error! App '...' state is 0x402 after update job: brak sprawnego połączenia z serwerami treści Steam. Najczęściej winna jest wychodząca reguła firewalla albo problem z serwerem nazw. SteamCMD potrzebuje wychodząco TCP 443 oraz portów od 27015 do 27050.No subscription: temat licencji, patrz poprzednia sekcja.Failed to load steamclient.soalbo[S_API FAIL] SteamAPI_Init(): plik binarny serwera szuka biblioteki Steam w stałym miejscu, którego SteamCMD nie wypełnia. Dotyczy to praktycznie wszystkich serwerów na Unreal Engine oraz gier Rust, Palworld i V Rising. Rozwiązaniem są dwa dowiązania w katalogu domowym użytkownika usługi.
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
Ponieważ są to dowiązania do katalogu SteamCMD, pozostają ważne także po samoaktualizacji SteamCMD. Częstym błędem następczym jest utworzenie tych katalogów jako root, przez co usługa nie może ich później odczytać.
Gdy pobieranie trwale się zacina, ostatnią dźwignią jest usunięcie pliku steamapps/appmanifest_<ID>.acf z katalogu instalacyjnego. SteamCMD uzna wtedy aplikację za niezainstalowaną i pobierze ją w całości od nowa.
Automatyzacja aktualizacji bez bezsensownych restartów serwera
Rozpowszechniona rada brzmi: raz dziennie uruchamiaj przez crona app_update i restartuj usługę. To kosztuje jedną przerwę każdego dnia, nawet jeśli żadnej aktualizacji nie ma. Lepszym rozwiązaniem jest porównanie Build ID. Zainstalowane stoi w pliku manifestu, aktualne dostarcza app_info_print:
runuser -u steam -- /home/steam/steamcmd/steamcmd.sh +login anonymous +app_info_update 1 +app_info_print 896660 +quit
Powstaje z tego skrypt w /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 "Nie udało się ustalić aktualnego Build ID, przerywam."
exit 1
fi
if [ "$installed" = "$latest" ]; then
echo "Aktualne (build $installed), bez restartu."
exit 0
fi
echo "Aktualizacja z $installed na $latest"
systemctl stop "$UNIT"
runuser -u steam -- "$CMD" +force_install_dir "$DIR" +login anonymous +app_update "$APPID" +quit
systemctl start "$UNIT"
Skrypt restartuje serwer tylko wtedy, gdy naprawdę coś się zmieniło, i czysto przerywa pracę, jeśli Steam akurat nie odpowiada. Bez tej kontroli pusty wynik zapytania zostałby odczytany jako aktualizacja, a serwer zatrzymany bez powodu. Uruchamiasz go przez crona albo lepiej przez timer systemd; podstawy opisuje Konfiguracja cronjoba w Linuksie.
Pamiętaj, że wiele gier po aktualizacji serwera wymaga także zaktualizowanych klientów. Automatyczna aktualizacja w środku godzin szczytu wyrzuca z gry wszystkich graczy. Zaplanuj przebieg na wczesne godziny poranne.
Praca w formie usługi systemd
Serwer gry w sesji screen nie przeżyje restartu. Rozwiązuje to jednostka w pliku /etc/systemd/system/valheim.service:
[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 "zmienToHaslo"
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
Dwa wiersze są tu ważniejsze, niż wyglądają. KillSignal=SIGINT sprawia, że serwer zapisuje stan przy zatrzymaniu, bo sporo serwerów gier ignoruje SIGTERM i przy twardym ubiciu traci postęp z ostatnich minut. TimeoutStopSec daje mu na to czas. Szczegółowe wyjaśnienie wszystkich pól znajdziesz w poradniku Tworzenie usługi systemd, a postępowanie w przypadku serwera na Javie w artykule Automatyczny start serwera Minecraft.
Jeśli serwer ginie zaraz po starcie z powodu braku pamięci RAM, pomoże rzut oka na Konfiguracja swapa. Porty trafiają potem do firewalla, patrz Konfiguracja UFW, przy czym serwery gier prawie zawsze potrzebują UDP, a sam wpis TCP jest typowym powodem, dla którego serwer działa, ale nikt nie potrafi się połączyć.
App ID popularnych gier
ID to jedyne miejsce, które zmienia się między grami. Anonimowo pobierzesz między innymi:
- 232250 Team Fortress 2
- 4020 Garry's Mod
- 222860 Left 4 Dead 2
- 730 Counter-Strike 2 (od przejścia z CS:GO klient i serwer to ta sama aplikacja, więc pobieranie jest odpowiednio duże)
- 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, malutkie i dlatego idealne jako test działania instalacji
Nie myl aplikacji serwera z aplikacją gry. W przypadku ARK 346110 to gra, a 376030 to serwer. Jeśli szukasz jakiegoś ID, znajdziesz je na liście Dedicated Servers List w Valve Developer Wiki albo przez SteamDB. Szybki test jest zawsze taki sam: anonimowe app_update, a jeśli pojawi się No subscription, było to ID klienta.
Po czym poznasz, że naprawdę działa
Cztery sprawdzenia, w tej kolejności:
- Pliki są na miejscu.
du -sh /home/steam/valheimmusi pokazać wiarygodny rozmiar, natomiast w plikusteamapps/appmanifest_896660.acfznajduje siębuildid. Katalog o rozmiarze kilku megabajtów oznacza przerwane pobieranie. - Proces żyje dłużej niż minutę.
systemctl status valheimpokazujeactive (running). Usługa, która restartuje się co sekundę, stoi naactivating (auto-restart), a wtedy powód wskażejournalctl -u valheim -n 50. - Port jest otwarty, i to jako UDP.
ss -ulpn | grep 2456musi wskazać proces. Jeśli nic nie widać, serwer wciąż się inicjalizuje albo jest przypięty do błędnego adresu. - Osiągalny z zewnątrz. Dopiero teraz sprawdź firewalla i połącz się z poziomu gry. Wiele tytułów potrzebuje dodatkowo portu zapytań, przy Valheimie jest to port serwera plus jeden.
Jeśli te cztery punkty się zgadzają, podbudowa jest w porządku, a wszystko dalej to już konfiguracja samej gry. Na serwerze root KernelHost w centrum danych maincubes we Frankfurcie nad Menem dochodzi do tego ochrona DDoS z własnej sieci, co jest istotne zwłaszcza przy publicznie listowanych serwerach gier, bo publiczna lista serwerów pokazuje adres IP każdemu. Tło tematu znajdziesz w artykule Ochrona serwera przed atakami DDoS.
Najczęstsze pytania
Dlaczego SteamCMD nie startuje na moim serwerze 64-bitowym?
Czy do serwera gry potrzebuję konta Steam?
Co oznacza „App state is 0x606 after update job”?
Czy podawać validate przy każdej aktualizacji?
Jak aktualizować automatycznie bez codziennego restartu serwera?
Dlaczego apt nie znajduje pakietu steamcmd?
2026 KernelHost GmbH. Wszelkie prawa zastrzeżone. Ten poradnik jest chroniony prawem autorskim. Publikowanie go w innych serwisach, w całości, we fragmentach lub w zmienionej formie, wymaga naszej pisemnej zgody. Cytaty z podaniem źródła i z linkiem są jak najbardziej mile widziane.

