Dedicated legacy Linux server: Difference between revisions

From TF2 Classified Wiki
Jump to navigation Jump to search
Webb (talk | contribs)
Add previous2021 branch to guide
Webb (talk | contribs)
Add notice that this is for legacy version, change notices to ambox
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
:''This 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/''
{{Ambox|contents=This article is based on a guide written by Raizo, the original of which can be found [https://blog.raizo.dev/posts/tf2-classic-linux-server-tutorial/ here].}}
{{Ambox|contents=This guide is written for the old ''Team Fortress 2 Classic'' non-Steam builds. For the latest ''Team Fortress 2 Classified'' on Steam see [[Dedicated Linux server|this guide]].}}


== Prerequisites ==
== Reading this article ==
* A Linux server running Ubuntu Server<sup>*</sup> on an x86_64 CPU. You cannot easily run SRCDS on any other architecture besides an x86_64 CPU. Box64/Box86 may work for ARM processors (e.g. Raspberry Pis) but that's complex, and not covered here.
<!-- Originally from https://wiki.teamfortress.com/wiki/Linux_dedicated_server#Reading_this_article -->
* A SFTP/SSH client (PuTTY, Termius, FileZilla, MobaXterm)
A command prefixed by <code>#</code> is meant to be run as '''root'''.
* At least 16GB of free storage
 
* A minimum of a 10Mbps upload speed if you intend on hosting a server over the Internet. No need to worry for LAN servers.
A command prefixed by <code>$</code> is meant to be run as a '''regular user''' without root permissions. In this case the <code>srcds</code> user.


<sup>*</sup>'''Note''': This guide was written for and tested on Ubuntu Server 24.04 LTS, however any Debian-based distro should work similarly and fine using this guide.
A command prefixed by <code>Steam></code> is meant to be run inside of a SteamCMD shell.


=== Reading this article ===
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.
<!-- Originally from https://wiki.teamfortress.com/wiki/Linux_dedicated_server#Reading_this_article -->
This article has been written according to standard Linux terminal documentation syntax, meaning the following:


A command prefixed by <code>#</code> (a hashtag) is meant to be run as '''root'''. In this article, we're assuming that you're using a VPS and logged in as the root account to start with.
== Prerequisites ==


A command prefixed by <code>$</code> (a dollar sign) is meant to be run as a '''regular user''' without root permissions.
* A Linux server running Ubuntu Server<sup>*</sup> on an x86_64 CPU<sup>**</sup> with root access
* At least 20GB of free storage
* A minimum of a 10Mbps upload speed if you intend on hosting a server over the Internet, more will be needed if you host custom content
* An opened port on your firewall for the server
* ''Optional'': An SSH/SFTP client if doing remote access/file management
* ''Optional'': A port that's been forwarded for the server if you wish to have it accessible over the internet


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.
<sup>*</sup> This guide was written for and tested on Ubuntu Server 24.04 LTS Minimal. Other distros may use different package names and conventions.


=== Creating a steam user for SteamCMD and Source SDK Base 2013 Dedicated Server ===
<sup>**</sup> Using an x86 compatibility layer like Box86 for another architecture is unsupported and may not work.
Pick a directory to install your server into. Industry standard is usually in <code>/opt</code>, but <code>/home</code> may be easier for you. If you want to use a directory in <code>/home</code>, omit the <code>-d</code> option as useradd will create a directory in <code>/home</code> with the user’s username, ours being <code>steam</code>. We’ll pick <code>/opt/tf2classic</code>.


Create a user with that home directory and give it a strong password:
== Preparing for install ==


<pre>
=== Dependencies ===
# useradd -m -d /opt/tf2classic -s /usr/bin/bash steam
# passwd steam
</pre>


<code>-m</code> creates a home directory for it, <code>-d /opt/tf2classic</code> specifies where our home directory will be, and <code>-s /usr/bin/bash</code> sets the shell to bash.
We'll need to install some required packages and tools for our server to work, as well as for installation.


=== Installing Source SDK Base 2013 DS, SteamCMD, and dependencies ===
Since the legacy TF2C branch, Source SDK, and SteamCMD are built for 32-bit, we'll need to enable 32-bit packages. We'll also add the <code>multiverse</code> repository which has SteamCMD.
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.


<pre>
<pre>
Line 40: Line 39:
</pre>
</pre>


Install SteamCMD, and miscellaneous packages that we'll be using.
Next, we'll install the <code>dialog</code> package so the Steam Subscriber Agreement dialog works, and then the rest of the packages we need.


<pre>
<pre>
# apt install steamcmd unzip aria2 tilde lib32z1 libncurses5:i386 libbz2-1.0:i386 lib32gcc-s1 lib32stdc++6 libtinfo5:i386 libcurl3-gnutls:i386 libsdl2-2.0-0:i386 libcurl4-gnutls-dev libcurl4-gnutls-dev:i386
# 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
</pre>
</pre>
''<sup>*</sup>'''Note''':See [https://developer.valvesoftware.com/wiki/SteamCMD#Package_From_Repositories|Valve Developer Wiki SteamCMD Repository Packages] if your distro is having issues getting steamcmd.
''
Login to the steam user you created:
<pre># su - steam</pre>


Run <code>steamcmd</code> and let it update. When it’s finished updating and displays the main SteamCMD shell, run <code>force_install_dir /opt/tf2classic/server</code> to choose the directory for the Source SDK Base 2013 Dedicated server to install into. This path can be anything, just make sure you have access to it.  
If your version of Ubuntu doesn't come with a text editor, you may install one now. For this guide we'll use <code>nano</code>.


Login anonymously by typing and running: <code>login anonymous</code>
<pre># apt install nano</pre>


Then run <code>app_update 244310 -beta previous2021 validate</code> in SteamCMD to install Source SDK Base 2013 DS.
=== Creating a user for the server ===


Give it a few, and when it’s finished we can run <code>exit</code>.
Pick a directory to install your server into. Many put it under a directory in <code>/opt</code>, but for this guide we'll be using <code>/home/srcds</code>.


== Downloading TF2 Classic ==
Create a disabled user with a home directory.
The fastest way to download TF2Classic is to use TF2CDownloader.
 
Run:


<pre>
<pre>
$ wget https://github.com/tf2classic/TF2CDownloader/releases/latest/download/TF2CDownloaderLinux
# useradd -s /bin/false -mr srcds
$ chmod +x ./TF2CDownloaderLinux
$ ./TF2CDownloaderLinux
</pre>
</pre>


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


You'll need to move the extracted directory into your SDK 2013 MP folder:
=== Installing Source SDK Base 2013 Dedicated Server (SDK 2013) ===


<pre>mv tf2classic /opt/tf2classic/server/</pre>
Switch to the new <code>srcds</code> user you made, and run SteamCMD.


=== Server Configuration ===
<pre>
Generate your server config(s) on [https://cfg.tf/ cfg.tf].
# sudo -Hu srcds bash
$ cd ~
$ . /etc/environment
$ steamcmd
</pre>


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).
You should be dropped into a SteamCMD shell. We can install the SDK 2013 now. Note that <code>force_install_dir</code> must be ran before <code>login anonymous</code>.


Upload the generated ZIP file to your server using SFTP, unzip the folder using:
<pre>
Steam>force_install_dir /home/srcds/sdk
Steam>login anonymous
Steam>app_update 244310 -beta previous2021
Steam>quit
</pre>


<pre>unzip <archive>.zip</pre>
If everything went well, <code>srcds</code> should be installed and you should be back at your user shell.
Before we continue we'll need to fix some files.


And merge the <code>cfg</code> folder with <code>/opt/tf2classic/server/tf2classic/cfg/</code>.
Valve changed some shared object file names in the SDK, but the objects included with our install of SDK 2013 have not adopted the new names.
Since these are simply renames, we can symlink them.  


=== Create symlinks to missing shared objects. ===
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.'''
'''Your server will not start without doing this.'''
Enter the bin directory by typing, exactly:
<code>
$ cd bin
</code>
Run the following commands to create the symlinks in the bin folder:


<pre>
<pre>
$ cd ~/sdk/bin
$ ln -s datacache_srv.so datacache.so
$ ln -s datacache_srv.so datacache.so
$ ln -s dedicated_srv.so dedicated.so
$ ln -s dedicated_srv.so dedicated.so
Line 113: Line 104:
</pre>
</pre>


If you've manually installed TF2 Classic instead of using the automatic installer, make sure to symlink these files too, inside TF2 Classic's bin folder:
Finally, we'll also symlink <code>steamclient.so</code> to a special directory to prevent bugs.
 
<pre>
$ mkdir -p ~/.steam/sdk32
$ ln -s ~/sdk/bin/steamclient.so ~/.steam/sdk32/
</pre>
 
== Installing TF2C ==
 
We'll be downloading the archived verison of TF2C, since it's unlikely to get updates. You have the option of using TF2CDownloader, but we won't cover it here.
 
<pre>
$ wget https://wiki.tf2classic.com/kachemak/tf2classic.zip -O /tmp/tf2classic.zip
$ mkdir ~/sdk/tf2classic
$ cd ~/sdk/tf2classic
$ 7z x /tmp/tf2classic.zip && rm /tmp/tf2classic.zip
</pre>
 
This will download the latest archive, create its directory, and extract it. If extraction succeeds it will also delete the downloaded archive.
 
We'll also need to do a quick symlink in TF2C's bin folder.


<pre>
<pre>
$ cd ../tf2classic/bin
$ cd ~/sdk/tf2classic/bin
$ rm server_srv.so
$ ln -s server.so server_srv.so
$ ln -s server.so server_srv.so
</pre>
</pre>


== Running the server ==
== Testing the server ==


=== Creating the server script ===
Before proceeding, we can manually run the server to make sure the install was successful.
Change into the server directory with:


<pre>$ cd /opt/tf2classic/server/</pre>
<pre>
$ cd ~/sdk
$ ./srcds_run -game tf2classic +map ctf_2fort +sv_password changethis
</pre>


Create a script to run the server with one simple command. Use any text editor of your choice to create runserver.sh where srcds_run is located. For the sake of those unfamiliar with terminal text editing, we'll be using nano. Run:
If all goes well, it should start.


<pre>$ nano runserver.sh</pre>
== Server Configuration ==


Fill it with this line (you may be able to paste using <code>Shift+Insert</code>):
For a basic, private server, you should only need to set a password in <code>sdk/tf2classic/cfg/server.cfg</code> by appending the file with <code>sv_password yourpassword</code>.
You can also make it LAN-only by appending <code>sv_lan 1</code> in the same file.


<pre>./srcds_run -console -game tf2classic +map pl_upward +maxplayers 24</pre>
If you want a more complicated setup, consider using [https://cfg.tf/ cfg.tf]. If you don't need this you can skip to the next section.


Feel free to change the map and maxplayers. There are more arguments, but we’ll keep it basic.
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).


Save the file by clicking <code>CRTL+X</code>, and then <code>Y</code> to write your changes.
Upload the generated ZIP file to your server, perhaps using SFTP, and unzip the folder.
 
<pre>
$ cd /tmp
$ unzip $PATH_TO_ARCHIVE</pre>


Now, make the script executable with:
And merge the <code>cfg</code> folder with <code>/home/srcds/sdk/tf2classic/cfg/</code>.


<pre>
<pre>
$ chmod +x runserver.sh
$ rsync /tmp/cfg ~/srcds/sdk/tf2classic/cfg
$ rm -rf /tmp/cfg
</pre>
</pre>


Finally, all you need to do to start the server is run <code>./runserver.sh</code>!
== Managing 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.


If you want it to run even after closing the terminal window, run <code>nohup ./runserver.sh &</code> followed by <code>disown</code>
=== Creating an SDK 2013 update script ===


=== Systemd & Crontab for automated start, restart and updating ===
We're going to create a script that will update 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.
For easier automation of server restarts, updating, and booting alongside the system, you may use systemd, which is the default init system for most modern Linux distros and cronjobs.
 
First, let's create a directory for the script.
 
<pre>
$ mkdir ~/bin
$ nano ~/bin/update-sdk.steamcmd
</pre>
 
Fill the file with the following contents:


Create file <code>ssdk2013mp-update</code> and fill in the following
<pre>
<pre>
@ShutdownOnFailedCommand 1 //set to 0 if updating multiple servers at once
@ShutdownOnFailedCommand 1 //set to 0 if updating multiple servers at once
@NoPromptForPassword 1
@NoPromptForPassword 1
force_install_dir /home/srcds/sdk
login anonymous
login anonymous
app_update 244310 -beta previous2021
app_update 244310 -beta previous2021
Line 162: Line 190:
</pre>
</pre>


Make it executable with <code>chmod +x ssdk2013mp-update</code>
You can execute this script manually by using the +runscript argument on SteamCMD.
 
<pre>
$ . /etc/environment
$ steamcmd +runscript /home/srcds/bin/update-sdk.steamcmd
</pre>


This script will update the underlying Source SDK 2013 MP Dedicated Server, you may execute it by itself, but in this case we will use it for automatic updates.
=== Creating a service file ===


Next, create a service file in <code>/etc/systemd/system/</code>
Create a service file in <code>/etc/systemd/system/</code> as root. For this guide we'll use <code>/etc/systemd/system/tf2c.service</code>.


Example <code>tf2classic.service</code>:
<pre>
<pre>
[Unit]
[Unit]
Description=TF2Classic
Description=TF2C Server
After=network-online.target
After=network-online.target
Wants=network-online.target
Wants=network-online.target


[Service]
[Service]
Type=forking
Type=simple
User=steam
User=srcds
WorkingDirectory=/home/tf2classic
StandardError=journal
RemainAfterExit=yes
StandardOutput=journal
ExecStartPre=/usr/games/steamcmd +runscript /opt/tf2classic/ssdkb2013mp-update
WorkingDirectory=/home/srcds/sdk
ExecStartPre=/opt/tf2classic/TF2CDownloaderLinux --update
RemainAfterExit=no
ExecStart=/opt/tf2classic/server/srcds_run -console -game tf2classic +map tr_walkway_fastcat_v1 -port 27020 +maxplayers 32 +sv_setsteamaccount XXXXXXX
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
TimeoutStartSec=infinity
Restart=always
Restart=always
Line 190: Line 224:
</pre>
</pre>


Then, enable the service to start with the init system:
Then, enable the service to start with Systemd on boot.
 
<pre>
<pre>
# systemctl enable tf2classic.service
# systemctl enable tf2c.service
</pre>
</pre>


Next, switch to the <code>root</code> user using <code>sudo su</code> and execute <code>crontab -e</code>. This is where you can set cronjobs, include something like the following:
You may create as many services as you have TF2C servers but remember to name the service files uniquely. When modifying service files, remember to run <code>systemctl daemon-reload</code> before restarting the service.
 
=== Automatic restarts using crontab ===
 
Cron is a program built into most Linux distros that runs scheduled commands.
 
As root, execute <code>crontab -e</code>. This will open a special file in your editor where you can declare what jobs you want to run and when. Let's add a job to run at 04:00 that will restart our server.


<pre>
<pre>
# Restart and update check for TF2Classic every day at 4 AM.
0 4 * * * systemctl restart tf2c.service
 
0 4 * * * systemctl restart tf2classic.service
</pre>
</pre>


You may create as many services as you have TF2C servers but remember to name the service files uniquely, enable them in <code>systemctl</code>, and add them to the <code>crontab</code>.
=== Manually managing services ===
 
=== 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.  
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.  


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


''</br>See also [[Dedicated_Linux_server_extras|Dedicated Linux Server Extras]].''
''</br>See also [[Dedicated_Linux_server_extras|Dedicated Linux Server Extras]].''
[[Category:Guides]]
[[Category:Guides]]

Latest revision as of 12:24, 2 March 2026

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.

Prerequisites

  • A Linux server running Ubuntu Server* on an x86_64 CPU** with root access
  • At least 20GB of free storage
  • A minimum of a 10Mbps upload speed if you intend on hosting a server over the Internet, more will be needed if you host custom content
  • An opened port on your firewall for the server
  • Optional: An SSH/SFTP client if doing remote access/file management
  • Optional: A port that's been forwarded for the server if you wish to have it accessible over the internet

* 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.

Preparing for install

Dependencies

We'll need to install some required packages and tools for our server to work, as well as for installation.

Since the legacy TF2C branch, Source SDK, and SteamCMD are built for 32-bit, we'll need to enable 32-bit packages. We'll also add the multiverse repository which has SteamCMD.

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

Next, we'll install the dialog package so the Steam Subscriber Agreement dialog works, and then the rest of the packages we need.

# 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

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

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 (SDK 2013)

Switch to the new srcds user you made, and run SteamCMD.

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

You should be dropped into a SteamCMD shell. We can install the SDK 2013 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. Before we continue we'll need to fix some files.

Valve changed some shared object file names in the SDK, but the objects included with our install of SDK 2013 have not adopted the new names. Since these are simply renames, we can symlink them.

Your server will not start without doing this.

$ 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

Finally, we'll also symlink steamclient.so to a special directory to prevent bugs.

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

Installing TF2C

We'll be downloading the archived verison of TF2C, since it's unlikely to get updates. You have the option of using TF2CDownloader, but we won't cover it here.

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

This will download the latest archive, create its directory, and extract it. If extraction succeeds it will also delete the downloaded archive.

We'll also need to do a quick symlink in TF2C's bin folder.

$ cd ~/sdk/tf2classic/bin
$ ln -s server.so server_srv.so

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

For a basic, private server, you should only need to set a password in sdk/tf2classic/cfg/server.cfg by appending the file with sv_password yourpassword. You can also make it LAN-only by appending sv_lan 1 in the same file.

If you want a more complicated setup, consider using cfg.tf. If you don't need this you can skip to the next section.

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, perhaps using SFTP, and unzip the folder.

$ 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

Managing 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 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 with 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. For this guide we'll use /etc/systemd/system/tf2c.service.

[Unit]
Description=TF2C Server
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

Then, enable the service to start with Systemd on boot.

# systemctl enable tf2c.service

You may create as many services as you have TF2C servers but remember to name the service files uniquely. When modifying service files, remember to run systemctl daemon-reload before restarting the service.

Automatic restarts using crontab

Cron is a program built into most Linux distros that runs scheduled commands.

As root, execute crontab -e. This will open a special file in your editor where you can declare what jobs you want to run and when. Let's add a job to run at 04:00 that will restart our server.

0 4 * * * systemctl restart tf2c.service

Manually managing services

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.