Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.
Revision as of 03:28, 7 December 2025 by Webb (talk | contribs)
This is a WIP updated version of the Linux dedicated server article. I want to ask for feedback before moving out of my user namespace. The original article was adapted and revised from a guide written by Raizo, the original of which can be found here: https://blog.raizo.dev/posts/tf2-classic-linux-server-tutorial/

Prerequisites

  • A Linux server running Ubuntu Server* on an x86_64 CPU** with root/administrator access
  • A SFTP/SSH client (PuTTY, Termius, FileZilla, MobaXterm)
  • At least 20GB of free storage
  • A minimum of a 10Mbps upload speed if you intend on hosting a server over the Internet. More bandwidth may be needed if custom maps are used.

* This guide was written for and tested on Ubuntu Server 24.04 LTS Minimal. Other distros may use different package names and conventions.

** Using an x86 compatibility layer like Box86 for another architecture is unsupported and may not work.

Reading this article

A command prefixed by # is meant to be run as root.

A command prefixed by $ is meant to be run as a regular user without root permissions. In this case the srcds user.

A command prefixed by Steam> is meant to be run inside of a SteamCMD shell.

Some commands are listed in-line with the rest of a paragraph and lack this symbol, in which case you should run the command as whichever account you're currently logged in with.

Creating a user for the server

Pick a directory to install your server into. Many put it under a directory in /opt, but for this guide we'll be using /home/srcds.

Create a disabled user with a home directory:

# useradd -s /bin/false -mr srcds

-m creates a home directory for the new user, -r specifies that it's a system account that will not have a password, and -s /bin/false prevents the account from having a default shell.

Installing Source SDK Base 2013 Dedicated Server (srcds), SteamCMD, and dependencies

The SteamCMD package is in the multiverse repos. TF2Classic and SteamCMD require i386 (32-bit) libraries to function. You also need 7-Zip to extract TF2Classic.

# add-apt-repository multiverse
# dpkg --add-architecture i386
# apt update

Install SteamCMD, and miscellaneous packages that we'll be using.

webbnote: libcurl4-gnutls-dev broken

# apt install dialog
# apt install steamcmd p7zip aria2 tilde lib32z1 libbz2-1.0:i386 lib32gcc-s1 lib32stdc++6 libcurl3-gnutls:i386 libsdl2-2.0-0:i386 wget

*Note:See Developer Wiki SteamCMD Repository Packages if your distro is having issues getting steamcmd.

If your version of Ubuntu doesn't come with a text editor, you may install one now. For this guide we'll use nano.

# apt install nano

Switch to the srcds user you created:

# sudo -Hu srcds bash
$ cd ~
$ . /etc/environment
$ steamcmd

You should be dropped into a SteamCMD shell. We can install the SDK now. Note that force_install_dir must be ran before login anonymous.

Steam>force_install_dir /home/srcds/sdk
Steam>login anonymous
Steam>app_update 244310 -beta previous2021
Steam>quit

If everything went well, srcds should be installed and you should be back at your user shell.

Installing TF2C

We'll be downloading the archived verison of TF2C. You also have the option of using TF2CDownloader.

$ wget https://wiki.tf2classic.com/archive/tf2classic-2.2.3.zip -O /tmp/tf2classic.zip
$ mkdir ~/sdk/tf2classic
$ cd ~/sdk/tf2classic
$ 7z x /tmp/tf2classic.zip && rm /tmp/tf2classic.zip

This will downloaded the latest archive of TF2C, create its directory, and extract it. If everything succeeds it will delete tf2classic.zip.

Valve changed some shared object file names in the SDK and the objects we’re given have not adapted to the new names. Since these are simply renames, we can symlink them. Your server will not start without doing this.

Enter the bin directory by typing, exactly:

$ cd bin

Run the following commands to create the symlinks in the bin folder:

$ cd ~/sdk/bin
$ ln -s datacache_srv.so datacache.so
$ ln -s dedicated_srv.so dedicated.so
$ ln -s engine_srv.so engine.so
$ ln -s materialsystem_srv.so materialsystem.so
$ ln -s replay_srv.so replay.so
$ ln -s scenefilecache_srv.so scenefilecache.so
$ ln -s shaderapiempty_srv.so shaderapiempty.so
$ ln -s studiorender_srv.so studiorender.so
$ ln -s vphysics_srv.so vphysics.so
$ ln -s soundemittersystem_srv.so soundemittersystem.so
$ cd ~/sdk/tf2classic/bin
$ ln -s server.so server_srv.so

We can also fix steamclient.so errors by symlinking a file to .steam.

$ mkdir -p ~/.steam/sdk32
$ ln -s ~/sdk/bin/steamclient.so ~/.steam/sdk32/

Testing the server

Before proceeding, we can manually run the server to make sure the install was successful.

$ cd ~/sdk
$ ./srcds_run -game tf2classic +map ctf_2fort +sv_password changethis

If all goes well, it should start.

Server Configuration

Generate your server config(s) on cfg.tf.

Make sure the server type is set to “Internet and LAN” if you want players outside your LAN to be able to join (you may need to port forward if you’re on consumer broadband or open ports on your firewall).

Upload the generated ZIP file to your server using SFTP, unzip the folder using:

$ cd /tmp
$ unzip $PATH_TO_ARCHIVE

And merge the cfg folder with /home/srcds/sdk/tf2classic/cfg/.

$ rsync /tmp/cfg ~/srcds/sdk/tf2classic/cfg
$ rm -rf /tmp/cfg

Running the server via Systemd

Systemd is a program that will automatically handle things like logging, restarts, and starting your server when your machine boots. We'll use this to run our server, instead of manually running commands.

Creating an SDK 2013 update script

We're going to create a script that will update our SDK 2013 for us instead of typing it out manually each time. Later, we'll optionally use this script to check and update SDK 2013 on our server automatically when the server starts.

First, let's create a directory for the script.

$ mkdir ~/bin
$ nano ~/bin/update-sdk.steamcmd

Fill the file the following contents:

@ShutdownOnFailedCommand 1 //set to 0 if updating multiple servers at once
@NoPromptForPassword 1
force_install_dir /home/srcds/sdk
login anonymous
app_update 244310 -beta previous2021
quit

You can execute this script manually by using the +runscript argument on SteamCMD.

$ . /etc/environment
$ steamcmd +runscript /home/srcds/bin/update-sdk.steamcmd

Creating a service file

Create a service file in /etc/systemd/system/ as root.

Example tf2c.service:

[Unit]
Description=TF2C
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=srcds
StandardError=journal
StandardOutput=journal
WorkingDirectory=/home/srcds/sdk
RemainAfterExit=no
ExecStartPre=/usr/games/steamcmd +runscript /home/srcds/bin/update-sdk.steamcmd # Exclude or comment this if you don't want to check for an update on each restart
Environment="LD_LIBRARY_PATH=".:bin:$LD_LIBRARY_PATH""
ExecStart=/usr/bin/script -e -c "/home/srcds/sdk/srcds_linux +map ctf_2fort -game tf2classic +maxplayers 24" /dev/null
TimeoutStartSec=infinity
Restart=always

[Install]
WantedBy=multi-user.target

[Install]
WantedBy=multi-user.target

Then, enable the service to start with Systemd.

# systemctl enable tf2c.service

Automatic restarts using crontab

As root, execute crontab -e. This will open a special file where you can set cronjobs. For example, adding the following line will restart your game server every day at 04:00:

0 4 * * * systemctl restart tf2c.service

You may create as many services as you have TF2C servers but remember to name the service files uniquely, enable them in systemctl, and add them to the crontab.

Systemd manual start, stop, restart/update

If you don't wish to use the service files above to automatically boot servers, or you need to perform these actions for maintenance: you may issue commands to manually start, stop, restart, or update the server(s) through systemd.

# systemctl restart tf2c # in case you need to restart manually or to grab updates!! 
# systemctl stop tf2c # in case you need to stop the server manually
# systemctl start tf2c # in case you need to start the server manually
# systemctl disable tf2c # in case you need to stop the server from booting as your system initializes 
# systemctl enable tf2c # in case you need to start the server to boot as your system initializes 


See also Dedicated Linux Server Extras.