Installare un server di gioco con SteamCMD

Pubblicato il 16 min di lettura

SteamCMD è la base comune di quasi tutti i server di gioco su Steam. Questa guida mostra l'installazione, l'accesso anonimo, app_update con validate, la gestione come servizio systemd e i messaggi di errore tipici.

Chi gestisce un server di gioco su un proprio server root finisce quasi sempre sullo stesso strumento: SteamCMD. Che si tratti di Valheim, Rust, Counter-Strike 2, Palworld, Enshrouded o ARK, i file del server sono ospitati da Valve e si scaricano tutti attraverso lo stesso client a riga di comando. Una volta configurato SteamCMD in modo pulito, ogni gioco successivo si installa cambiando un solo numero.

Questa guida copre esattamente i punti in cui i tutorial più brevi si fermano: le librerie a 32 bit sui sistemi a 64 bit, le differenze tra Debian, Ubuntu e la famiglia Red Hat, i messaggi di errore riportati alla lettera, una procedura di aggiornamento che non riavvia il server a ogni passaggio del cron e la gestione come servizio systemd.

Che cos'è SteamCMD e che cosa non è

SteamCMD è lo Steam Console Client, una versione a riga di comando ridotta all'osso del client Steam, senza interfaccia grafica. Sa fare bene una cosa sola: scaricare applicazioni dalla rete Steam, aggiornarle e verificarne i file. Non avvia nessun server, non configura nulla e non conosce la logica di gioco. Al termine del download i file del server si trovano in una directory, poi la parola passa al gioco vero e proprio.

Un punto essenziale per capire tutta la questione delle librerie: il bootstrapper di SteamCMD è ancora oggi un programma a 32 bit. Su un sistema puramente a 64 bit gli mancano le librerie di runtime corrispondenti, ed è proprio qui che il primo avvio fallisce nella maggior parte dei casi. I file del server scaricati, invece, nei giochi moderni sono quasi sempre a 64 bit.

Preparazione: un utente dedicato al posto di root

I processi di un server di gioco non girano mai come root. Accettano connessioni da Internet, in molti titoli scaricano mod dallo Steam Workshop ed eseguono quindi codice di terze parti. Un utente dedicato e senza privilegi costa tre comandi e limita i danni.

useradd -m -d /home/steam -s /bin/bash steam
mkdir -p /home/steam/steamcmd
chown -R steam:steam /home/steam/steamcmd

SteamCMD avvisa esplicitamente quando viene lanciato come root. Chi ignora l'avviso se lo ritrova più tardi: non appena una directory appartiene a root, l'esecuzione successiva come steam fallisce con un errore di scrittura, e il messaggio non lascia intuire la vera causa.

Tutti i comandi di questo articolo si inseriscono come root e passano all'utente di servizio tramite runuser -u steam --. Sui sistemi con sudo funziona allo stesso modo sudo -u steam. Se prima vuoi occuparti della messa in sicurezza di base, trovi le fondamenta in Configurare un nuovo server root e Mettere in sicurezza SSH.

Le librerie a 32 bit, diverse a seconda del sistema

Qui le distribuzioni si dividono, e le liste di comandi generiche che circolano in rete sbagliano regolarmente proprio su questo punto.

Debian 12, Debian 13, Ubuntu 22.04 e Ubuntu 24.04

Su tutti e quattro i sistemi basta il pacchetto lib32gcc-s1 dell'archivio principale. È un pacchetto amd64 che porta con sé il runtime a 32 bit e non richiede nessuna architettura i386 aggiuntiva:

apt update
apt install -y ca-certificates curl tar file lib32gcc-s1 lib32stdc++6

lib32stdc++6 non serve sempre a SteamCMD in sé, ma parecchi binari server più vecchi (tutto quello basato sul motore Source, i titoli HLDS, alcuni server Unity) lo richiedono. Installarlo subito risparmia una ricerca di errori più avanti. file non è presente in nessuna delle immagini minimali e serve più in basso per la diagnosi, per questo compare già nella lista.

AlmaLinux 9, Rocky Linux 9, RHEL 9 e Oracle Linux 9

Lì i pacchetti hanno nomi diversi e portano il suffisso .i686:

dnf -y update
dnf install -y --allowerasing glibc.i686 libstdc++.i686 tar file curl

Entrambe le aggiunte sono necessarie su un'installazione minimale appena fatta, altrimenti il comando si interrompe. Il motivo di --allowerasing: EL9 include curl-minimal, e il pacchetto curl completo entra in conflitto con esso. Senza quell'opzione la chiamata termina su AlmaLinux 9 e Rocky Linux 9 con package curl-minimal ... conflicts with curl provided by curl ... conflicting requests. Anche togliendo del tutto curl dalla lista si arriva allo scopo, perché curl-minimal fornisce già /usr/bin/curl. Il motivo del dnf -y update anteposto: se lo stato del sistema è più vecchio dei repository, il nuovo pacchetto i686 entra in conflitto con il pacchetto a 64 bit installato, rilevato su Rocky Linux 9 come 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. Su Oracle Linux 9 non si verifica nessuno dei due conflitti, lì è già installato il curl completo.

EPEL non serve, i pacchetti si trovano nei repository standard. Se vuoi anche strumenti come htop, la strada è descritta in Installare htop su AlmaLinux, Rocky e RHEL.

AlmaLinux 10, Rocky Linux 10 e RHEL 10 non sono adatti a SteamCMD

Non è un problema di configurazione, è un vicolo cieco: RHEL 10 e le distribuzioni che ne derivano hanno eliminato completamente l'architettura x86 a 32 bit. Lì nessun repository offre pacchetti i686, nemmeno con --enablerepo=*, e il comando di installazione termina con No match for argument: glibc.i686. Dato che steamcmd.sh richiama sempre il bootstrapper a 32 bit linux32/steamcmd, non c'è modo di aggirare la cosa. Per un server di gioco sul versante Red Hat va quindi scelta la famiglia EL9, cioè AlmaLinux 9, Rocky Linux 9 oppure Oracle Linux 9.

Un secondo ostacolo sulle installazioni EL molto snelle: se è presente solo util-linux-core, manca runuser, che in questa guida viene usato ovunque. In quel caso esegui prima dnf install -y util-linux. Su AlmaLinux 9, Rocky Linux 9, Oracle Linux 9 e su tutti i sistemi Debian e Ubuntu runuser è già presente.

Perché non usare semplicemente il pacchetto steamcmd?

Ubuntu tiene steamcmd nel componente multiverse, Debian in non-free, e in entrambi i casi il pacchetto è compilato esclusivamente per l'architettura i386. Su un server a 64 bit appena installato si finisce quindi immancabilmente in:

E: Unable to locate package steamcmd

Perché diventi anche solo un candidato, vanno prima abilitati il componente e l'architettura estranea. Su Ubuntu multiverse è già attivo nell'installazione standard, lì bastano tre righe:

dpkg --add-architecture i386
apt update
apt-cache policy steamcmd

Su Debian manca in più il componente. Senza di esso apt-cache policy steamcmd non restituisce alcun output, nemmeno un messaggio di errore. Prima vanno aggiunti contrib e non-free alle fonti dei pacchetti, da Debian 12 di solito in /etc/apt/sources.list.d/debian.sources nella riga Components:. Solo dopo la query funziona e su Debian 12 segnala il candidato 0~20180105-5 da bookworm/non-free i386. L'apt update tra il cambio di architettura e la query è obbligatorio: senza quel passaggio le liste dei pacchetti i386 non esistono e il candidato resta (none).

Lo sforzo raramente vale la pena. Il pacchetto Debian è un wrapper molto vecchio (versione 0~20180105-5 in Debian 13) che comunque si limita a scaricare lo stesso bootstrapper che si recupera da soli in due righe. L'installazione manuale è identica su tutti i sistemi e quindi molto più facile da documentare.

Installare SteamCMD e interpretare il primo avvio

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

Il terzo comando è il vero test. Alla primissima chiamata SteamCMD scarica sé stesso, mostra una barra di avanzamento e poi termina. Si presenta così:

[  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

Criterio di successo: l'ultima riga è Loading Steam API...OK. Se compare invece Loading Steam API...FAILED oppure il processo si interrompe subito, mancano le librerie a 32 bit della sezione precedente. Il messaggio tipico è questo:

steamcmd.sh: line 41: /home/steam/steamcmd/linux32/steamcmd: No such file or directory

Questo messaggio è fuorviante, perché il file esiste eccome. Quello che non viene trovato è l'interprete a 32 bit di cui il binario ha bisogno. Puoi verificarlo con file /home/steam/steamcmd/linux32/steamcmd: l'output riporta ELF 32-bit LSB shared object, Intel 80386, ... interpreter /lib/ld-linux.so.2 e nomina quindi esattamente l'interprete mancante. Se file stesso risponde command not found, è stato dimenticato nel passaggio di installazione qui sopra. La variante error while loading shared libraries: libstdc++.so.6 indica lo stesso problema, solo un livello più avanti.

Accesso anonimo contro accesso con account

La stragrande maggioranza dei server dedicati è pubblicata come applicazione Steam separata e gratuita e si scarica senza credenziali:

+login anonymous

È il caso normale ed è la strada da provare sempre per prima. Nessuna password sul server, nessuno Steam Guard, nessun account bloccato dopo un trasloco del server.

Un accesso con account serve solo quando la build del server è legata al possesso del gioco. Lo si riconosce da questo messaggio:

ERROR! Failed to install app 'ID' (No subscription)

No subscription significa sempre la stessa cosa: questo account non può scaricare questa app. Con l'accesso anonimo vuol dire che serve un account vero in possesso del gioco. Con un account vero vuol dire che manca la licenza oppure che è stato usato l'App ID sbagliato.

L'accesso con account avviene in modo interattivo, perché Steam Guard chiede un codice:

/home/steam/steamcmd/steamcmd.sh +login ilmionomeutente

Dopo la conferma una tantum viene creato un file sentry sotto ~/.steam, e da quel momento funzionano anche le chiamate non interattive. Tre punti che nella pratica fanno male: per questo scopo usa un account Steam separato che detenga solo la licenza del server. Non scrivere mai la password in uno script cron. E metti in conto che dopo un periodo di inattività prolungato o un cambio di IP Steam chieda di nuovo una conferma, cosa che blocca silenziosamente un aggiornamento automatico.

Da tenere del tutto separato è il Game Server Login Token (GSLT). Non ha niente a che vedere con il download, ma decide se il server in esecuzione compare pubblicamente nella lista dei server. Su Counter-Strike 2 e sugli altri titoli Valve viene generato nell'account Steam e inserito nella configurazione del server, non in SteamCMD.

Installare un gioco: ordine degli argomenti, validate e branch

SteamCMD elabora gli argomenti + rigorosamente da sinistra a destra. Da qui deriva la regola più importante in assoluto:

+force_install_dir deve stare prima di +app_update. Se sta dopo, i file finiscono nel percorso predefinito e la directory indicata resta vuota.

Ecco una chiamata completa, qui con l'esempio del server Valheim e del suo 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

Nota che validate si scrive senza segno più: è un argomento di app_update e non un comando a sé stante. validate confronta ogni file con il checksum del depot e riscarica le differenze. Ha senso alla prima installazione, dopo un download interrotto e in caso di crash inspiegabili. A ogni aggiornamento di routine è superfluo e costoso, perché viene riletto l'intero contenuto. Due effetti collaterali vanno conosciuti: i file che appartengono al depot e che hai modificato tu vengono ripristinati, e nei giochi con mod nella directory di installazione validate può rimuovere file estranei.

Come controllo di riuscita serve la riga finale:

Success! App '896660' fully installed.

Un branch diverso, per esempio un ramo di test pubblico, si aggancia direttamente a app_update:

+app_update 896660 -beta public-test validate

Per un ramo protetto da password si aggiunge -betapassword. Il ritorno alla versione standard avviene con -beta none: non basta semplicemente omettere il parametro, perché la scelta del branch resta memorizzata nel manifest.

Quando qualcosa va storto: i messaggi di errore alla lettera

SteamCMD segnala i problemi come stato esadecimale, che senza traduzione non dice nulla. I più frequenti:

  • Error! App '...' state is 0x202 after update job: spazio su disco insufficiente. Verifica con df -h /home/steam. Ricorda che, oltre alla directory di destinazione, SteamCMD ha bisogno di spazio per la cache di download, di norma nello stesso filesystem sotto steamapps/downloading. Nei titoli di grandi dimensioni il picco durante l'aggiornamento può arrivare quasi al doppio della dimensione finale. Se il disco è pieno, ti aiuta Liberare spazio su un disco pieno sotto Linux.
  • Error! App '...' state is 0x606 after update job: errore di scrittura. In nove casi su dieci sono i permessi, non l'hardware. Il classico: la prima esecuzione è avvenuta come root, la seconda come steam. Riparazione con chown -R steam:steam /home/steam. Con link simbolici verso un secondo disco anche la destinazione deve appartenere all'utente di servizio.
  • Error! App '...' state is 0x402 after update job: nessuna connessione utilizzabile verso i server di contenuti Steam. Di solito una regola firewall in uscita oppure un problema di risoluzione dei nomi. In uscita SteamCMD ha bisogno di TCP 443 e delle porte da 27015 a 27050.
  • No subscription: questione di licenza, vedi la sezione precedente.
  • Failed to load steamclient.so oppure [S_API FAIL] SteamAPI_Init(): il binario del server cerca la libreria Steam in una posizione fissa che SteamCMD non riempie. Sono interessati praticamente tutti i server Unreal Engine, oltre a Rust, Palworld e V Rising. La soluzione sono due link nella home dell'utente di servizio.
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

Dato che sono link verso la directory di SteamCMD, restano validi anche dopo un autoaggiornamento di SteamCMD. Un errore conseguente frequente è creare queste directory come root, così il servizio poi non riesce a leggerle.

Quando un download resta bloccato in modo persistente, l'ultima leva è cancellare steamapps/appmanifest_<ID>.acf nella directory di installazione. Da quel momento SteamCMD considera l'app non installata e la riscarica per intero.

Automatizzare gli aggiornamenti senza riavviare il server inutilmente

Il consiglio più diffuso è di far girare app_update una volta al giorno via cron e riavviare il servizio. Questo costa un'interruzione ogni giorno, anche quando non c'è alcun aggiornamento. Meglio confrontare il build ID. Quello installato si trova nel file manifest, quello attuale lo fornisce app_info_print:

runuser -u steam -- /home/steam/steamcmd/steamcmd.sh +login anonymous +app_info_update 1 +app_info_print 896660 +quit

Da qui nasce uno script in /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 "Impossibile determinare il build ID attuale, interrompo."
  exit 1
fi

if [ "$installed" = "$latest" ]; then
  echo "Già aggiornato (build $installed), nessun riavvio."
  exit 0
fi

echo "Aggiornamento da $installed a $latest"
systemctl stop "$UNIT"
runuser -u steam -- "$CMD" +force_install_dir "$DIR" +login anonymous +app_update "$APPID" +quit
systemctl start "$UNIT"

Lo script riavvia solo quando qualcosa è davvero cambiato e si interrompe in modo pulito quando Steam non risponde. Senza questo controllo un risultato di query vuoto verrebbe interpretato come aggiornamento e il server verrebbe fermato senza motivo. L'esecuzione avviene via cron oppure, meglio ancora, tramite un timer systemd; le basi le trovi in Configurare un cron job sotto Linux.

Tieni presente che molti giochi, dopo un aggiornamento del server, richiedono anche client aggiornati. Un aggiornamento automatico in piena fascia di gioco butta fuori tutti i giocatori. Pianifica l'esecuzione nelle prime ore del mattino.

Gestire il server come servizio systemd

Un server di gioco dentro una sessione screen non sopravvive a un riavvio. Una unit in /etc/systemd/system/valheim.service risolve il problema:

[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 "daCambiare"
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

Due righe qui dentro sono più importanti di quanto sembrino. KillSignal=SIGINT fa in modo che il server salvi quando viene fermato, perché parecchi server di gioco ignorano SIGTERM e con un arresto brutale perdono i progressi degli ultimi minuti. TimeoutStopSec gli dà il tempo per farlo. Una spiegazione dettagliata di tutti i campi la trovi in Creare un servizio systemd, la procedura nel caso di un server Java in Avviare automaticamente un server Minecraft.

Se il server muore subito all'avvio per mancanza di RAM, dai un'occhiata a Configurare lo swap. Le porte vanno poi aperte nel firewall, vedi Configurare UFW, tenendo presente che i server di gioco hanno quasi sempre bisogno di UDP e che una voce solo TCP è tipicamente il motivo per cui il server gira ma nessuno riesce a connettersi.

App ID dei giochi più diffusi

L'ID è l'unico punto che cambia da un gioco all'altro. Scaricabili in modo anonimo sono, tra gli altri:

  • 232250 Team Fortress 2
  • 4020 Garry's Mod
  • 222860 Left 4 Dead 2
  • 730 Counter-Strike 2 (dal passaggio da CS:GO client e server sono la stessa app, di conseguenza il download è molto voluminoso)
  • 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, minuscolo e quindi ideale come test di funzionamento dell'installazione

Non confondere l'app del server con l'app del gioco. In ARK per esempio 346110 è il gioco e 376030 il server. Se cerchi un ID, lo trovi nella Dedicated Servers List del Valve Developer Wiki oppure tramite SteamDB. Il test rapido è sempre lo stesso: app_update anonimo, e se arriva No subscription, era l'ID del client.

Come capisci che funziona davvero

Quattro verifiche, in quest'ordine:

  1. I file ci sono. du -sh /home/steam/valheim deve mostrare una dimensione plausibile, e in steamapps/appmanifest_896660.acf compare un buildid. Una directory di pochi megabyte significa download interrotto.
  2. Il processo vive più di un minuto. systemctl status valheim mostra active (running). Un servizio che riparte ogni secondo resta su activating (auto-restart), e in quel caso journalctl -u valheim -n 50 fornisce il motivo.
  3. La porta è aperta, e in UDP. ss -ulpn | grep 2456 deve nominare il processo. Se non si vede nulla significa che il server è ancora in fase di inizializzazione oppure è in ascolto sull'indirizzo sbagliato.
  4. Raggiungibile dall'esterno. Solo a questo punto verifica il firewall e prova a connetterti dal gioco. Molti titoli richiedono in più una porta di query, in Valheim è la porta del server più uno.

Se questi quattro punti sono a posto, la base è in ordine e tutto il resto è configurazione di gioco. Su un server root KernelHost nel datacenter maincubes di Francoforte sul Meno si aggiunge la protezione DDoS dalla rete propria, cosa che conta soprattutto per i server di gioco elencati pubblicamente, perché una lista pubblica dei server rende l'indirizzo IP visibile a chiunque. Gli approfondimenti li trovi in Proteggere il server dagli attacchi DDoS.

Domande frequenti

Perché SteamCMD non parte sul mio server a 64 bit?
Il bootstrapper di SteamCMD è un programma a 32 bit. Senza il runtime adatto segnala in sostanza "linux32/steamcmd: No such file or directory", anche se il file esiste. Su Debian e Ubuntu il problema si risolve con "apt install lib32gcc-s1 lib32stdc++6", su AlmaLinux 9, Rocky Linux 9 e Oracle Linux 9 con "dnf -y update" seguito da "dnf install --allowerasing glibc.i686 libstdc++.i686". Su Debian e Ubuntu non serve nessuna architettura i386 aggiuntiva. Sulla famiglia EL10 (AlmaLinux 10 e affini) non esistono più pacchetti i686, quindi lì SteamCMD non è utilizzabile.
Serve un account Steam per un server di gioco?
Nella maggior parte dei casi no. I server dedicati sono applicazioni Steam separate e gratuite e si scaricano con "+login anonymous". Un account vero serve solo se durante il download SteamCMD segnala "No subscription". Da questo va distinto il Game Server Login Token, che non ha nulla a che vedere con il download ma decide se il server in esecuzione compare nella lista pubblica dei server.
Che cosa significa "App state is 0x606 after update job"?
È un errore di scrittura che deriva quasi sempre da permessi sbagliati sui file e non da un disco difettoso. La causa tipica è una prima esecuzione come root e una seconda come utente di servizio. "chown -R steam:steam /home/steam" rimette le cose a posto. Lo stato affine 0x202 indica invece spazio libero insufficiente, e lì aiuta solo fare pulizia oppure aggiungere spazio.
Devo passare validate a ogni aggiornamento?
No. Alla prima installazione, dopo un download interrotto e in caso di crash inspiegabili validate è la scelta giusta. Nell'uso di routine rilegge a ogni passaggio l'intero contenuto e costa tempo e I/O inutilmente. Inoltre ripristina i file che hai modificato tu e in alcuni giochi può rimuovere le mod dalla directory di installazione.
Come aggiorno automaticamente senza riavviare il server ogni giorno?
Confronta il build ID. Quello installato si trova in steamapps/appmanifest_<ID>.acf, quello attuale lo fornisce "+app_info_update 1 +app_info_print <ID>". Solo quando i due valori divergono il servizio viene fermato, aggiornato e riavviato. È importante interrompere lo script quando la query non restituisce alcun risultato, altrimenti in caso di disservizio lato Steam il server viene fermato senza motivo.
Perché apt non trova il pacchetto steamcmd?
Perché su Ubuntu si trova in multiverse e su Debian in non-free, ed è compilato esclusivamente per l'architettura i386. Senza il componente abilitato e senza "dpkg --add-architecture i386" compare "E: Unable to locate package steamcmd". Dato che il pacchetto si limita comunque a scaricare lo stesso bootstrapper, l'installazione manuale tramite l'archivio tar è la via più semplice e identica su tutte le distribuzioni.

SteamCMD Server di gioco Linux Debian Ubuntu systemd Valheim Counter-Strike 2 Server root