The HLDS command line looks like line noise the first time you see it, but there is a clean rule underneath: flags that start with a dash (-game, -port) are engine parameters read once at startup, and flags that start with a plus (+map, +maxplayers) are console commands and cvars executed after the engine boots. Get that distinction and the whole line stops being mysterious.
The two kinds of argument
A typical launch:
./hlds_run -game cstrike -strictportbind -ip 0.0.0.0 -port 27015 \ +map de_dust2 +maxplayers 20 +sv_lan 0
Everything before is engine setup; everything with a + is exactly what you could type in the server console. That is why +maxplayers has a plus (it is a command) but -port has a dash (the engine needs it before the console exists).
Engine parameters (dash)
| Parameter | What it does |
|---|---|
-game cstrike | Loads the Counter-Strike mod. Without it you get vanilla Half-Life. Mandatory. |
-port 27015 | UDP port the server binds. Default 27015. Use this to run several servers on one box. |
-ip 0.0.0.0 | Which local IP to bind. 0.0.0.0 = all interfaces. Set a specific IP when the box has several and you want one server per IP. |
-strictportbind | Fail loudly if the port is taken instead of silently grabbing the next free one. Use it always. |
-console | Plain-text console (Windows). On Linux the console is already text. |
-insecure | Disable VAC. VAC does almost nothing for CS 1.6 today; this removes the "not secured" line. |
-nomaster | Do not heartbeat the master list. For a private/LAN server you deliberately want hidden. |
-pingboost 1|2|3 | Alternative timing/sleep strategy for higher server FPS. 3 is the most aggressive; test, do not cargo-cult. |
-sys_ticrate 1000 | Caps the server's FPS (frame loop rate). Higher can smooth movement at a CPU cost. |
-num_edicts 2048 | Raise the entity limit for plugin-heavy servers that hit ED_Alloc: no free edicts. |
-pidfile hlds.pid | Write the process id to a file — handy for scripts and supervisors. |
-norestart | Tell hlds_run not to auto-restart the engine after a crash. Use it when systemd is doing the restarting. |
Console commands and cvars (plus)
| Command | What it does |
|---|---|
+map de_dust2 | The map to start on. Required — without a start map the server has nothing to load. |
+maxplayers 20 | Slot count. This is the real player cap; set it here, not only in cfg. |
+sv_lan 0 | 0 to appear on the internet master list. With 1 the server never heartbeats and Steam clients are refused. |
+exec server.cfg | Execute a config after boot. server.cfg is auto-executed anyway; use this for extra files. |
+servercfgfile game.cfg | Change which cfg the engine auto-execs as the server config. |
+ip 1.2.3.4 | Cvar form of the bind IP; the dash -ip is preferred and set earlier. |
+rcon_password ... | Set RCON here to keep it out of a world-readable cfg if you like. It still ends up in memory. |
hlds_run vs hlds_linux
On Linux you almost always launch hlds_run, a shell wrapper that starts hlds_linux, captures its output to debug.log, and restarts it after a crash. Under a systemd service you generally want one restarter, not two — either let systemd restart and pass -norestart to hlds_run, or run hlds_linux directly.
Quoting and ordering
Two practical rules save a lot of debugging. First, keep all dash parameters before all plus commands on the line — some shells and the engine's own parser get confused when they are interleaved, and a misparsed +sv_lan 0 can leave you on the LAN list wondering why. Second, quote any value with a space, especially through a shell: a hostname belongs in server.cfg rather than on the command line for exactly this reason. When you need several config files, chain them with repeated +exec — they run in order after the map loads:
+exec server.cfg +exec bans.cfg +exec plugins.cfg
Windows differences
On Windows you launch hlds.exe rather than hlds_run, and -console is worth adding to get the readable text console instead of the old dialog window. There is no hlds_run wrapper, so crash-restart is your batch file's or supervisor's job, and -norestart is meaningless there. Otherwise the parameter set — -game, -port, +map, +maxplayers, +sv_lan — is identical across platforms.
Common mistakes
- Server takes the wrong port — you launched two instances without
-strictportbind; the second silently used 27016. Always pass it. - Server invisible in the internet list —
+sv_lan 1(or a leftoversv_lan 1in cfg), or you passed-nomaster. Set+sv_lan 0and drop-nomaster. +maxplayersignored — you putmaxplayersinserver.cfg; it is a launch-time value, so pass+maxplayerson the command line.ED_Alloc: no free edicts— plugin-heavy server hitting the entity ceiling. Add-num_edicts 2048.- Config seems half-applied — engine parameters after a
+commandcan be misparsed by shells; keep all-flags first, then all+commands.
Verification
After launch, check the bind and the runtime values agree with your flags:
ss -lunp | grep 27015
confirms the port. In the console, status shows the map and slot count you asked for, and sv_lan echoes 0. If all three match your command line, the parameters took. From here, fold the working command line into a systemd unit and move gameplay settings into an annotated server.cfg.









