RE:NODE

Guides12 min read

Team Fortress 2 server setup, config and SourceMod

Installing a TF2 dedicated server: SteamCMD and the GSLT, server.cfg, map cycles and custom maps, SourceTV, SourceMod admins, and keeping it populated.

Updated

1 reader

TF2 is old, well optimised and cheap to host, which means the thing that decides whether your server is good is not the hardware. It is the map rotation, the plugin list and whether somebody is watching it. A 24-slot server fits comfortably in 2 GB and one core; the install is the only thing about it that is large, at roughly 25 GB on disk. This guide covers the install, the configuration that actually changes how the game plays, SourceTV, SourceMod and admins, and the part most guides skip - how a community server stops being empty.

What you get from a TF2 server#

The dedicated server is a Source server running the tf game directory, app id 232250, installed anonymously with SteamCMD. It needs no game licence, runs on Linux or Windows, and is undemanding by any modern standard.

Some things about it are fixed and worth knowing before you start tuning:

  • The tick rate is 66 and you cannot change it. -tickrate is ignored by TF2. Third-party extensions exist that force other values; they are unsupported, they drift out of date with every game update, and every plugin and config you will download assumes 66. Leave it.
  • A Game Server Login Token is effectively mandatory. Valve has required one for public server listings since 2016. Without a token the server still runs and can be joined by IP, but it does not appear in the browser, which for a community server is the same as not existing.
  • Community servers are found, not matched. Casual matchmaking does not route players to you. Your traffic comes from the Community Servers browser, from friends, and from whatever Discord or listing site you put yourself on.
  • Everything social is a SourceMod plugin. Votes, reserved slots, custom commands, bans that persist, MOTD ads - none of it is in the base game.

Requirements and resource usage#

ServerRAMCPUNotes
12-16 slots, vanilla1-2 GB1 coreFriends and a map cycle
24 slots, SourceMod, a few plugins2-3 GB1-1.5 coresThe normal community server
32 slots, busy plugin list3-4 GB2 coresChaotic by design; plan for it
24 slots plus SourceTV and demos3 GB1.5 coresAdd disk for the recordings

The surprise in TF2 hosting is disk, not memory. The dedicated server install is around 25 GB, and custom maps are 50-150 MB each, so a rotation of twenty community maps is another couple of gigabytes. That is why TF2 plans here start with 30 GB rather than the 10 GB a game this light on memory would otherwise need.

CPU is a single-thread story, as with every Source game. A full 32-slot server with a dozen plugins will use appreciably more of one core than a 12-slot vanilla one, but neither is heavy. If your server is stuttering, suspect a plugin in a per-frame hook before you suspect the plan; CPU vs RAM for game servers covers how to tell which resource is actually at its limit.

Installing the server: SteamCMD and the GSLT#

bash
$ steamcmd +force_install_dir /home/tf2/server +login anonymous \    +app_update 232250 validate +quit$ cd /home/tf2/server$ ./srcds_run -game tf -console -usercon -port 27015 \    +maxplayers 24 +map cp_process_f12 +sv_setsteamaccount <token>

Create the token at Steam's game server account page using app id 440 - the base game's id, not the server's. One token per server; reusing one across two live servers causes both to be logged out. The token is a credential: it can be banned if your server misbehaves, and anyone who has it can impersonate your server. Keep it out of server.cfg if other people can read your files, and prefer a startup variable or a separate config file that only you can see. Steam game server tokens explained covers bans, per-game app ids and what happens when a token is revoked.

The rest of the launch line is short:

ParameterWhat it does
-game tfThe game directory
-consoleRun headless
-userconEnable RCON; without it rcon_password does nothing
-port 27015Game and query port
+maxplayers 24Slots. The engine allows up to 32
+map <name>First map; the cycle takes over afterwards
+servercfgfile server.cfgOnly needed if you renamed it

SteamCMD explained covers validate, update scripts and what to do when an update half-finishes.

server.cfg, the settings that matter#

tf/cfg/server.cfg runs on every map change. Most of what people put in it has no measurable effect; this is the part that does.

tf/cfg/server.cfg
hostname "Badlands and friends | EU | no random crits"rcon_password "long-random-string"sv_password ""sv_lan 0sv_region 3sv_contact "you@example.com"sv_tags "nocrits,vanilla,eu"mp_timelimit 30mp_winlimit 0mp_maxrounds 0mp_autoteambalance 1mp_teams_unbalance_limit 1mp_idlemaxtime 5mp_idledealmethod 1mp_friendlyfire 0mp_respawnwavetime 10tf_weapon_criticals 0tf_damage_disablespread 1tf_use_fixed_weaponspreads 1sv_pure 1sv_cheats 0sv_allowupload 0sv_allowdownload 1sv_downloadurl "https://files.example.com/tf/"net_maxfilesize 64mapcyclefile "mapcycle.txt"

Four of those change the game rather than the server:

  • tf_weapon_criticals 0 removes random critical hits. This is the single most requested community server setting, and half your visitors will decide within a minute whether they like your server based on it. Either choice is defensible; pick one and say so in the hostname.
  • tf_damage_disablespread 1 removes random damage variation, and tf_use_fixed_weaponspreads 1 makes shotgun pellets deterministic. Together with the above these are the standard "competitive-feeling" trio.
  • mp_idlemaxtime with mp_idledealmethod 1 moves idle players to spectator after that many minutes; 2 kicks them. On a server that fills, this is what stops half your slots being occupied by people who went to make tea in 2019.
  • sv_pure 1 enforces the shipped whitelist in tf/cfg/pure_server_whitelist.txt, which stops clients using modified models and bright-pink-everything skins. sv_pure 2 is stricter and will reject legitimate HUDs and custom content, so most community servers stay at 1.

The rate cvars deserve a mention because people change them for no reason. sv_minrate and sv_maxrate bound bandwidth per client; sv_mincmdrate/sv_maxcmdrate bound how often clients send input; sv_minupdaterate/sv_maxupdaterate bound how often the server sends snapshots. Competitive configs clamp the command and update rates to 66 at both ends so every player is treated identically. If you are not running matches, leave the whole family alone - badly chosen values cause choke and packet loss that look exactly like a network fault.

Per-map overrides go in tf/cfg/<mapname>.cfg, which runs after server.cfg when that map loads. That is how you give an arena map a different time limit without a plugin.

Ports, SourceTV and connecting#

PortProtocolPurpose
27015UDPGame traffic and Steam queries
27015TCPRCON, with -usercon
27020UDPSourceTV
27005UDPOutbound on the client, nothing to open

TF2 plans here come with three allocations, which is exactly the shape of that table: the game port, SourceTV, and one spare for a second server or a stats daemon. Game server ports explained covers why the query lives on the game port in Source games and on a separate one elsewhere.

SourceTV is worth enabling even if nobody spectates, because it records demos you can review after an argument:

tf/cfg/server.cfg
tv_enable 1tv_port 27020tv_name "Badlands TV"tv_title "Badlands and friends"tv_delay 90tv_maxclients 8tv_autorecord 1tv_delaymapchange 1

tv_delay 90 is the broadcast delay in seconds that stops spectators relaying enemy positions to players. tv_autorecord 1 writes a .dem for every map, in the tf folder, which grows quietly until you clean it up - put that on a schedule rather than discovering it as a full disk.

Players join through the Community Servers browser, through a Steam favourite, or directly with connect 203.0.113.10:27015 in the developer console. Direct connect is the diagnostic: if it works and the browser does not list you, the problem is the token or the region, not the server. Treat rcon_password as the credential it is - the protocol sends it in plain text - and read RCON safely before exposing it anywhere.

reads the listingconnectmap name, download URLmap and contentverifies client filesFastDLbz2 over HTTPServer browserquery on 27015TF2 server66 tickPlayerTF2 clientsv_purewhitelist check
What happens between clicking connect and spawning

Maps, the map cycle and custom content#

The cycle lives in tf/cfg/mapcycle.txt, one map per line, and the server reads it from the file named by mapcyclefile. TF2 ships mapcycle_default.txt; copy it rather than editing it, because updates overwrite the original.

A map cycle with fewer, better maps beats a long list nobody votes for. Eight to twelve maps is plenty. Every map you add is one more thing a first-time visitor might have to download, and a 120 MB download is where most of them leave.

Custom maps need two things. The .bsp goes in tf/maps/ on the server, and a bzip2-compressed copy goes on the web host behind sv_downloadurl so clients can fetch it at web speed rather than trickling it over the game port. Without FastDL, sv_allowdownload 1 still works - it is just slow enough that people assume the server is broken.

Voting for the next map is a SourceMod job. The bundled mapchooser, rockthevote and nominations plugins between them give you an end-of-map vote, an RTV command and a nomination list, configured through addons/sourcemod/configs/maplists.cfg. Keep the votable list shorter than the full cycle; a vote with thirty options is a vote for whatever was at the top.

SourceMod, Metamod and admin#

SourceMod and Metamod:Source first; everything social builds on them. Metamod loads into the engine, SourceMod loads into Metamod, and plugins are .smx files in addons/sourcemod/plugins/.

Admins go in addons/sourcemod/configs/admins_simple.ini, one line each:

addons/sourcemod/configs/admins_simple.ini
"STEAM_0:1:12345678"   "99:z""STEAM_0:0:87654321"   "20:bcdef"

The number before the colon is immunity, and the letters after it are permission flags - z is root, and the rest map to kick, ban, slay, changemap and so on. Groups and overrides live in admins.cfg and admin_overrides.cfg alongside it. After editing, sm_reloadadmins in the console applies it without a restart.

CommandEffect
sm plugins listWhat is loaded, and what failed
sm plugins reload <n>Reload one plugin by its list number
sm_adminThe in-game admin menu
sm_kick <player> <reason>Kick
sm_ban <player> <minutes> <reason>Ban, 0 for permanent
sm_map <map>Change map
sm_rcon <command>Run a server command from in-game
sm_reloadadminsRe-read the admin files

Reserved slots for regulars is a small feature that keeps a community together, and it is a bundled plugin: set your slot count one higher than you advertise, enable reservedslots, and give the flag to the people who show up every week.

Bans that survive a restart and are visible to other admins need a database and a web panel - SourceBans++ is the usual answer. Every game plan here includes one database slot created from the panel with generated credentials, so check the plugin's requirements against it before you commit to that route.

One operational warning: a TF2 update usually breaks SourceMod until you update it too. Metamod and SourceMod bind to engine internals, and after a game patch the server will start with no plugins at all, or refuse to load them. Keep the download page bookmarked, use the stable branch unless a snapshot is required, and do not let an automatic game update run an hour before an event. What to do when a mod update breaks is the general version of this problem. The plugin side in detail is in TF2 SourceMod plugins.

Population is a schedule, not a hope#

An empty server stays empty. This is the whole of community server hosting and no configuration file changes it.

  • Pick two evenings and be there. People join servers with people on them. Two reliable hours a week beats a permanently running empty box.
  • Fill it with bots for the first month if you must, honestly: tf_bot_quota 8 with tf_bot_quota_mode fill keeps eight bots on until humans replace them. Bots need a navigation mesh, so they only work on maps that ship with a .nav file or one you generated with nav_generate - which is slow and imperfect on community maps.
  • Put the server in front of people. A Discord with a status bot, a listing site entry, and accurate sv_tags so the browser filters find you. Discord webhooks for server status covers the bot side.
  • Write rules and give two people admin. A server with no moderation is one bad evening from having no regulars. Server rules, moderation and staff covers permissions and appeals; growing a game server community covers the rest.

A weekly restart during the quiet hours keeps memory and demo files in check. The panel's Schedules tab does it from a cron expression along with a backup, which is the entire maintenance burden of a TF2 server once it is set up.

Troubleshooting#

The server is not in the Community Servers browser. In order: no GSLT, a banned GSLT, the query port unreachable, sv_lan 1, or the wrong sv_region. Confirm the server itself works with a direct connect.

Players are kicked for "server is enforcing consistency for this file". sv_pure rejecting a client file. Usually a custom HUD or model that the whitelist does not allow; sv_pure 1 rather than 2 fixes most of it.

A custom map takes minutes to download. No FastDL, or the bz2 file is missing from the web host for that specific map. Check the exact file name and case.

SourceMod stopped loading after an update. Update Metamod and SourceMod. The console prints the failure at start-up; read the first lines, not the last.

Everyone chokes and loses packets at the same time. Rate cvars, or a plugin sending a lot of data. Reset the rate family to defaults before blaming the network.

The server hits its memory limit and restarts. Unusual for TF2 and almost always a plugin leaking. On RE:NODE a container at its limit is stopped and restarted clean rather than left to swap, and repeated restarts raise a warning and an automatic ticket rather than silently looping.

FAQ#

Do I need a Game Server Login Token for a TF2 server?

For anything public, yes. Valve has required one for server browser listings since 2016. A server without one runs fine and accepts direct connections, which is enough for a private group but not for a community server.

Can I change the tick rate of a TF2 server?

No, not in a supported way. TF2 is locked to 66 ticks a second and ignores -tickrate. Extensions exist that force other values and they cause more problems than they solve.

How many slots should I run?

24 is the sweet spot for most community servers, and 32 is the practical maximum. Above 24 the game becomes a different experience - spam-heavy and hard to play seriously - which is a design choice rather than a performance one.

How much disk does a TF2 server need?

About 25 GB for the install, plus 50-150 MB per custom map and whatever SourceTV demos accumulate. Memory is the easy part; disk is what people underestimate.

Will my plugins survive a TF2 update?

The plugins usually will; SourceMod itself often will not until you update it. Plan updates for a time when nobody is playing, and never let one run just before an event you have advertised.

Should I disable random crits?

It is the most common change community servers make, and it is worth making a decision rather than leaving the default by accident. Put whichever you chose in the hostname so people know what they are joining.


Comments

Completely anonymous: no account, no email, no cookie. We store the name you type, the text and the time - nothing else. Links are limited and markup is not rendered.

0/2000