App 90 is the Half-Life Dedicated Server package on Steam, and it is what you download to run a CS 1.6 server. It is a shared package that contains base Half-Life plus the mods (Counter-Strike, Day of Defeat, and others), which is exactly why people get it slightly wrong — the download can stall or need a specific ordering. This gives the exact commands and explains the quirks.
1. Install SteamCMD first
SteamCMD is the command-line downloader; it is not the game. Install it as in installing SteamCMD on Linux, then launch it:
./steamcmd.sh
You should land at the Steam> prompt. Everything below is typed at that prompt.
2. Log in anonymously
The dedicated server for app 90 is available to anonymous accounts — you do not need your personal Steam credentials, and you should not use them for a server:
login anonymous
It should print Waiting for user info...OK. If it asks for a password, you typed a username; use the literal word anonymous.
3. Set the install directory before downloading
Choose where the files go before the update command, or they land in SteamCMD's default folder:
force_install_dir /home/hlds/cstrike-server
Use an absolute path you own. Order matters: force_install_dir must come before app_update in the same session, or the download ignores it.
4. Download with app_update 90 validate
This is the command that actually pulls the server:
app_update 90 validate
The validate keyword makes SteamCMD checksum every file after download and re-fetch anything corrupt or missing. Always include it on a first install and after any interrupted download. Expect a large download; app 90 brings the full Half-Life base plus the CS content.
5. Handle the multi-mod prompt
Because app 90 is the shared HLDS package, older SteamCMD builds sometimes stop partway and ask you to pick a game variant, or appear to hang at a percentage. If the download stalls, quit and re-run the exact same sequence — validate resumes from where it left off rather than restarting. Running the update two or three times to completion is normal for this package and is not a sign of a broken install.
6. A full non-interactive one-liner
Once you know it works, script the whole thing so it runs unattended. Everything after + is executed in order and +quit exits cleanly:
./steamcmd.sh +force_install_dir /home/hlds/cstrike-server \ +login anonymous \ +app_update 90 validate \ +quit
This is the form to put in an update script or a CI job. Re-running it later pulls any server update Valve has published and re-validates the tree.
7. Confirm you got the CS content
After it finishes, the install directory should contain a cstrike/ folder alongside valve/ and the hlds_run launcher. If cstrike/ is missing, the download did not complete — re-run app_update 90 validate. You can now start the server as covered in the full install guide and pass flags per the command-line parameters reference.
Common errors
- "Invalid Password" on login anonymous — you entered a real username. The account name is literally
anonymouswith no password. - Download stalls at a fixed percentage — a known quirk of the app 90 shared package. Quit and re-run the same command;
validateresumes. - Files land in the wrong folder —
force_install_dircame afterapp_update, or was omitted. Set it first, in the same session. - "ERROR! Failed to install app '90' (No subscription)" — usually a transient Steam issue or a login that did not complete; re-run
login anonymousthen the update. It does not require a purchase. - No cstrike/ directory after it "finished" — the download was incomplete. Run
app_update 90 validateagain to completion. - Permission denied writing files — the install path is not owned by the user running SteamCMD. Point
force_install_dirat a directory you own.
Verification
Re-run app_update 90 validate one more time; on a complete install it verifies quickly and reports the app as fully installed with nothing to download. Confirm cstrike/ exists in your install directory and contains maps and configs, that hlds_run sits at the install root, and that a valve/ folder is present alongside cstrike/ — the shared package always brings the base game too. Then launch the server once to prove the binaries actually run and reach the map. A verification that stops at "the download finished" misses the common case where the tree is present but incomplete, which only surfaces when the engine tries to load a missing library at startup. When you later need to update to the latest build, you run this same command again against the same install directory.









