HLDS is a 32-bit binary from 2003 and it is still what App 90 gives you. Nothing about that has changed in 2026 — what changed is that a modern 64-bit Ubuntu or Debian install ships none of the 32-bit runtime it needs. Most of the "SteamCMD installed fine but the server won't start" reports come from that single gap. This guide installs the server the way it should be installed: as an unprivileged user, with the right multilib packages, and with a start command you can hand to systemd afterwards.
1. Create a dedicated user
Never run a game server as root. A remote code execution bug in a 20-year-old netcode stack is not hypothetical.
sudo adduser --disabled-password --gecos "" steam sudo su - steam
2. Enable multiarch and install the 32-bit runtime
On Debian/Ubuntu:
sudo dpkg --add-architecture i386 sudo apt update sudo apt install -y lib32gcc-s1 lib32stdc++6 libc6:i386 libncurses6:i386 libcurl4:i386 ca-certificates tar wget
On older releases the package is lib32gcc1 instead of lib32gcc-s1. If you skip this step, the server exits with:
./hlds_linux: No such file or directory
which is the kernel telling you the ELF interpreter /lib/ld-linux.so.2 is missing — not that the file is missing. See this fix and the full 32-bit dependency list.
3. Install SteamCMD
mkdir -p ~/steamcmd && cd ~/steamcmd wget https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz tar -xvzf steamcmd_linux.tar.gz ./steamcmd.sh +quit
The first run self-updates and drops you back to the shell. If it loops on Failed to load cached hosts file, delete ~/Steam and rerun.
4. Download App 90
App 90 is "Half-Life Dedicated Server", and CS 1.6 is shipped as a mod inside it. It is an anonymous-login app, but it has a long-standing quirk: an anonymous app_update 90 often stops after downloading only the base Half-Life files. The reliable form is to set the platform explicitly and to run the update twice.
cd ~/steamcmd ./steamcmd.sh +force_install_dir /home/steam/hlds \ +login anonymous \ +app_set_config 90 mod cstrike \ +app_update 90 validate \ +quit
Run the exact same command a second time. It is normal for the first pass to finish with Success! App '90' fully installed. and still be missing cstrike/; the second pass fills it in. If you instead get:
Error! App '90' state is 0x402 after update job.
re-run it — that state means the download was interrupted, and SteamCMD resumes cleanly. For Failed to install app '90' (No subscription) see the dedicated fix; it is almost always caused by logging in with a personal account instead of anonymous.
5. Verify the install
ls /home/steam/hlds/cstrike/liblist.gam ls /home/steam/hlds/hlds_run /home/steam/hlds/hlds_linux
All three must exist. liblist.gam is what tells the engine which game DLL to load; if it is absent, the mod did not download and you must repeat step 4.
6. Write a minimal server.cfg
Create /home/steam/hlds/cstrike/server.cfg:
hostname "My CS 1.6 Server" rcon_password "change-this-to-something-long" sv_password "" sv_lan 0 sv_contact "[email protected]" mp_timelimit 30 mp_friendlyfire 0 mp_autoteambalance 1 mp_limitteams 2 mp_startmoney 800 mp_freezetime 3 sv_maxrate 25000 sv_minrate 15000 sv_maxupdaterate 101 sv_minupdaterate 30 sv_timeout 60 log on mp_logmessages 1 mp_logdetail 3
sv_lan 0 is mandatory — with sv_lan 1 the server never heartbeats the master list and Steam clients are rejected with a LAN error. A full annotated file is in the server.cfg guide.
7. Start the server
cd /home/steam/hlds ./hlds_run -game cstrike -strictportbind -ip 0.0.0.0 -port 27015 \ +map de_dust2 +maxplayers 20 +sv_lan 0
hlds_run is a shell wrapper that restarts hlds_linux after a crash and writes debug.log. -strictportbind makes the server fail loudly instead of silently taking port 27016 when 27015 is busy. Parameters are explained in the command line reference.
8. Open the firewall
CS 1.6 is UDP-only for gameplay; RCON also uses TCP on the same port number.
sudo ufw allow 27015/udp sudo ufw allow 27015/tcp sudo ufw allow 26900/udp
26900 is the outbound client port range used for master-server communication on some setups; it costs nothing to allow. Details: which ports to open.
Common errors
Couldn't allocate dedicated server IP port— something already holds 27015. Check withss -lunp | grep 27015.error while loading shared libraries: libstdc++.so.6: cannot open shared object file— you installed the 64-bit package. You needlib32stdc++6.Host_Error: Couldn't get DLL API from ./cstrike/dlls/cs.so!— the mod files are incomplete, or you copied a Windowsmp.dllinto a Linux install.- Server starts but nobody can find it —
sv_lanis 1, or the VPS provider blocks UDP. See server not in the master list.
Verification
From another machine:
ss -lunp | grep 27015
should show hlds_linux bound. Then in the console type status — you should see your map, hostname, and players : 0 active (20 max). Finally, from a client, open the console and run connect YOUR_IP:27015. If you connect and spawn, the install is done.
Next steps
Plain HLDS is the floor, not the ceiling. Replace the engine with ReHLDS, add Metamod-r and AMX Mod X, and put the whole thing behind a systemd unit so it survives a reboot.









