# TF2 GameServer Setup ![](0.png) In this tutorial we're going to look at how to install a tf2 server on a ubuntu 16.04 host. ## **Initial Setup** I'm setting it up on an Ubuntu LXC container on proxmox: [ 10.66.66.2/32 ] [ /dev/pts/10 ] [Github/blog/HTB] → ssh root@10.0.0.180 -i ~/.ssh/mainpc root@tf2:~# dpkg --add-architecture i386 root@tf2:~# apt update -y ; apt upgrade -y root@tf2:~# apt-get install -y software-properties-common root@tf2:~# apt-get install -y --no-install-recommends --no-install-suggests lib32gcc1 lib32z1 libncurses5:i386 libbz2-1.0:i386 lib32gcc1 lib32stdc++6 libtinfo5:i386 libcurl3-gnutls:i386 wget unzip gettext-base libbsd0 curl tmux screen vim -y root@tf2:~# rm -rf /var/lib/apt/lists/* root@tf2local:~# curl -sqL "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz" | tar zxvf - steamcmd.sh linux32/steamcmd linux32/steamerrorreporter linux32/libstdc++.so.6 linux32/crashhandler.so root@tf2local:~# ./steamcmd.sh Redirecting stderr to '/home/steam/Steam/logs/stderr.txt' ILocalize::AddFile() failed to load file "public/steambootstrapper_english.txt". [ 0%] Checking for available update... [----] Downloading update (0 of 53901 KB)... [ 0%] Downloading update (738 of 53901 KB)... [ 1%] Downloading update (2417 of 53901 KB)... [ 4%] Downloading update (3721 of 53901 KB)... [ 6%] Downloading update (5180 of 53901 KB)... [ 9%] Downloading update (6593 of 53901 KB)... [...] WARNING: setlocale('en_US.UTF-8') failed, using locale: 'C'. International characters may not work. Redirecting stderr to '/home/steam/Steam/logs/stderr.txt' [ 0%] Checking for available updates... [----] Verifying installation... Steam Console Client (c) Valve Corporation -- type 'quit' to exit -- Loading Steam API...OK. Steam>login anonymous Connecting anonymously to Steam Public...Logged in OK Waiting for user info...OK Steam>force_install_dir ./tf2/ Steam>app_update 232250 validate Update state (0x3) reconfiguring, progress: 0.00 (0 / 0) Update state (0x3) reconfiguring, progress: 0.00 (0 / 0) Update state (0x3) reconfiguring, progress: 0.00 (0 / 0) Update state (0x3) reconfiguring, progress: 0.00 (0 / 0) [...] (after like 20 minutes) Update state (0x101) committing, progress: 92.11 (7808672823 / 8477794661) Update state (0x101) committing, progress: 94.61 (8020772689 / 8477794661) Update state (0x101) committing, progress: 95.87 (8127457161 / 8477794661) Update state (0x101) committing, progress: 97.11 (8233117403 / 8477794661) Update state (0x101) committing, progress: 98.41 (8343138174 / 8477794661) Success! App '232250' fully installed. Steam>exit root@tf2local:~$ ls Steam linux32 linux64 package public siteserverui steamcmd.sh tf2 root@tf2local:~$ cd tf2/ root@tf2local:~/tf2$ ls bin hl2 platform srcds_linux srcds_run steamapps tf thirdpartylegalnotices.txt root@tf2local:~/tf2$ cd tf/ root@tf2local:~/tf2/tf$ ls bin maps tf2_misc_000.vpk tf2_misc_006.vpk tf2_misc_012.vpk tf2_misc_018.vpk tf2_misc_024.vpk tf2_textures_dir.vpk cfg materials tf2_misc_001.vpk tf2_misc_007.vpk tf2_misc_013.vpk tf2_misc_019.vpk tf2_misc_dir.vpk workshop custom media tf2_misc_002.vpk tf2_misc_008.vpk tf2_misc_014.vpk tf2_misc_020.vpk tf2_sound_misc.vpk.sound.cache download resource tf2_misc_003.vpk tf2_misc_009.vpk tf2_misc_015.vpk tf2_misc_021.vpk tf2_sound_misc_dir.vpk gameinfo.txt scripts tf2_misc_004.vpk tf2_misc_010.vpk tf2_misc_016.vpk tf2_misc_022.vpk tf2_sound_vo_english.vpk.sound.cache item_whitelist_example.txt steam.inf tf2_misc_005.vpk tf2_misc_011.vpk tf2_misc_017.vpk tf2_misc_023.vpk tf2_sound_vo_english_dir.vpk Now that srcds is installed, we can start configuring our server, Basically first i want the server to run a few game commands as it boots up, to do that i can either pass those commands as arguements to the **srcds_run** binary like so: ./srcds_run -game tf +map ctf_2fort +maxplayers 24 If you have that steamclient.so error do the following: root@tf2local:~# ls Steam linux32 linux64 package public siteserverui steamcmd.sh tf2 root@tf2local:~# cd tf2/ root@tf2local:~/tf2# ls bin hl2 platform srcds_linux srcds_run steamapps tf thirdpartylegalnotices.txt root@tf2local:~/tf2# ./srcds_run [...] ProtoDefs post data loaded. ProtoDefs post data loaded. dlopen failed trying to load: /root/.steam/sdk32/steamclient.so with error: /root/.steam/sdk32/steamclient.so: cannot open shared object file: No such file or directory Looking up breakpad interfaces from steamclient Calling BreakpadMiniDumpSystemInit Unknown command "r_decal_cullsize" Unknown command "startupmenu" Network: IP 10.0.0.180, mode MP, dedicated Yes, ports 27015 SV / 27005 CL Fri Jul 2 22:17:18 UTC 2021: Server Quit root@tf2local:~/tf2# mkdir -p ~/.steam/sdk32 root@tf2local:~/tf2# updatedb root@tf2local:~/tf2# locate steamclient.so /root/linux32/steamclient.so /root/linux64/steamclient.so /root/tf2/bin/steamclient.so root@tf2local:~/tf2# ln -s $HOME/linux32/steamclient.so ~/.steam/sdk32/ root@tf2local:~/tf2# ./srcds_run That's how i fixed the steamclient.so error. Now instead of running the srcds binary ourselves, we can can just specify those commands in the **tf/cfg/server.cfg** file, if you don't know what to put in here you can just use [cfg.tf](https://cfg.tf/server/): root@tf2local:~/tf2/tf/cfg$ vim server.cfg root@tf2local:~/tf2/tf/cfg$ cat server.cfg hostname "void.yt" sv_password "" sv_lan 1 sv_cheats 1 rcon_password "changeme" sv_rcon_banpenalty 15 sv_rcon_minfailures 15 sv_rcon_maxfailures 15 log off sv_logfile 0 sv_logecho 0 sv_logbans 0 sm_maxhealth 100000 tf_bot_add 1 soldier expert tf_bot_force_class soldier sv_pure -1 sv_pure_kick_clients 0 sv_alltalk 1 mp_allowspectators 0 mp_autoteambalance 0 mp_teams_unbalance_limit 30 mp_disable_respawn_times 1 tf_bot_force_class soldier mp_forcecamera 0 sv_allow_wait_command 0 sv_cheats 0 sv_pausable 0 mp_stalemate_enable 0 mp_stalemate_timelimit 240 mp_winlimit 0 mp_timelimit 0 tf_weapon_criticals 0 tf_use_fixed_weaponspreads 0 sv_maxrate 50000 sv_minrate 7500 sv_maxupdaterate 66 sv_minupdaterate 20 sv_maxcmdrate 66 sv_mincmdrate 0 sv_allow_point_servercommand always since this server will run only one map i specified it in server.cfg [terminal 1] [ 10.66.66.2/32 ] [ /dev/pts/16 ] [Github/blog/HTB] → cd /mnt/vault/steam/steamapps/common/Team\ Fortress\ 2/tf/maps [ 10.66.66.2/32 ] [ /dev/pts/14 ] [~/Downloads] → python3 -m http.server 9090 Serving HTTP on 0.0.0.0 port 9090 (http://0.0.0.0:9090/) ... [terminal 2] root@tf2local:~/tf2/tf/cfg$ cd .. root@tf2local:~/tf2/tf$ cd maps/ root@tf2local:~/tf2/tf/maps# wget http://10.0.0.10:9090/airborne2.bsp --2021-07-02 22:49:26-- http://10.0.0.10:9090/airborne2.bsp ; chmod 755 airborne2.bsp Connecting to 10.0.0.10:9090... connected. HTTP request sent, awaiting response... 200 OK Length: 157192 (154K) [model/vnd.valve.source.compiled-map] Saving to: 'airborne2.bsp' airborne2.bsp 100%[==============================================================================================>] 153.51K --.-KB/s in 0.01s 2021-07-02 22:49:26 (11.5 MB/s) - 'airborne2.bsp' saved [157192/157192] root@tf2local:~/tf2/tf/maps# cd ../cfg root@tf2local:~/tf2/tf/cfg# cat mapcycle.txt airborne2 We can run the srcds binary to check that it's working: root@tf2local:~/tf2# ./srcds_run -game tf +map airborne2 ************** WARNING *************** Running the dedicated server as root is highly discouraged. It is generally unnecessary to use root privileges to execute the dedicated server. ************************************** Auto detecting CPUntinue to launch in 1 secondss Using default binary: ./srcds_linux Server will auto-restart if there is a crash. Using Breakpad minidump system. Version: 6623512 AppID: 232250 Setting breakpad minidump AppID = 232250 Using breakpad crash handler Loaded 10223 VPK file hashes from /root/tf2/tf/tf2_textures.vpk for pure server operation. Loaded 10223 VPK file hashes from /root/tf2/tf/tf2_textures.vpk for pure server operation. Loaded 476 VPK file hashes from /root/tf2/tf/tf2_sound_vo_english.vpk for pure server operation. Loaded 476 VPK file hashes from /root/tf2/tf/tf2_sound_vo_english.vpk for pure server operation. Loaded 1343 VPK file hashes from /root/tf2/tf/tf2_sound_misc.vpk for pure server operation. Loaded 1343 VPK file hashes from /root/tf2/tf/tf2_sound_misc.vpk for pure server operation. Loaded 2634 VPK file hashes from /root/tf2/tf/tf2_misc.vpk for pure server operation. Loaded 2634 VPK file hashes from /root/tf2/tf/tf2_misc.vpk for pure server operation. Loaded 2634 VPK file hashes from /root/tf2/tf/tf2_misc.vpk for pure server operation. Loaded 1217 VPK file hashes from /root/tf2/hl2/hl2_textures.vpk for pure server operation. Loaded 574 VPK file hashes from /root/tf2/hl2/hl2_sound_vo_english.vpk for pure server operation. Loaded 383 VPK file hashes from /root/tf2/hl2/hl2_sound_misc.vpk for pure server operation. Loaded 451 VPK file hashes from /root/tf2/hl2/hl2_misc.vpk for pure server operation. Loaded 451 VPK file hashes from /root/tf2/hl2/hl2_misc.vpk for pure server operation. Loaded 5 VPK file hashes from /root/tf2/platform/platform_misc.vpk for pure server operation. Loaded 5 VPK file hashes from /root/tf2/platform/platform_misc.vpk for pure server operation. server_srv.so loaded for "Team Fortress" For FCVAR_REPLICATED, ConVar must be defined in client and game .dlls (sv_use_steam_voice) ProtoDefs post data loaded. ProtoDefs loaded. 16.46 MB used ProtoDefs post data loaded. ProtoDefs loaded. 16.46 MB used maxplayers set to 24 No '-replayserverdir' parameter found - using default replay folder. Replay: Creating thread pool...succeeded. Replay: Starting thread pool with 4 threads...succeeded. Cleaning files from temp dir, "/root/tf2/tf/replay/server/tmp/" ...no files removed. ProtoDefs post data loaded. ProtoDefs post data loaded. Looking up breakpad interfaces from steamclient Calling BreakpadMiniDumpSystemInit Unknown command "r_decal_cullsize" ConVarRef dev_loadtime_map_start doesn't point to an existing ConVar Unknown command "startupmenu" Network: IP 10.0.0.180, mode MP, dedicated Yes, ports 27015 SV / 27005 CL Initializing Steam libraries for secure Internet server [S_API] SteamAPI_Init(): Loaded local 'steamclient.so' OK. CAppInfoCacheReadFromDiskThread took 46 milliseconds to initialize CApplicationManagerPopulateThread took 0 milliseconds to initialize (will have waited on CAppInfoCacheReadFromDiskThread) RecordSteamInterfaceCreation (PID 453): SteamGameServer013 / RecordSteamInterfaceCreation (PID 453): SteamUtils010 / Setting breakpad minidump AppID = 440 Looking up breakpad interfaces from steamclient Calling BreakpadMiniDumpSystemInit RecordSteamInterfaceCreation (PID 453): SteamGameServer013 / RecordSteamInterfaceCreation (PID 453): SteamUtils010 / RecordSteamInterfaceCreation (PID 453): SteamNetworking006 / RecordSteamInterfaceCreation (PID 453): SteamGameServerStats001 / RecordSteamInterfaceCreation (PID 453): STEAMHTTP_INTERFACE_VERSION003 / RecordSteamInterfaceCreation (PID 453): STEAMINVENTORY_INTERFACE_V003 / RecordSteamInterfaceCreation (PID 453): STEAMUGC_INTERFACE_VERSION014 / RecordSteamInterfaceCreation (PID 453): STEAMAPPS_INTERFACE_VERSION008 / Setting breakpad minidump AppID = 232250 No account token specified; logging into anonymous game server account. (Use sv_setsteamaccount to login to a persistent account.) RecordSteamInterfaceCreation (PID 453): SteamGameServer013 / RecordSteamInterfaceCreation (PID 453): SteamUtils010 / RecordSteamInterfaceCreation (PID 453): SteamNetworking006 / RecordSteamInterfaceCreation (PID 453): SteamGameServerStats001 / RecordSteamInterfaceCreation (PID 453): STEAMHTTP_INTERFACE_VERSION003 / RecordSteamInterfaceCreation (PID 453): STEAMINVENTORY_INTERFACE_V003 / RecordSteamInterfaceCreation (PID 453): STEAMUGC_INTERFACE_VERSION014 / RecordSteamInterfaceCreation (PID 453): STEAMAPPS_INTERFACE_VERSION008 / ConVarRef room_type doesn't point to an existing ConVar Executing dedicated server config file server.cfg Using map cycle file 'cfg/mapcycle.txt'. RecordSteamInterfaceCreation (PID 453): SteamGameStats001 / Warning: failed to init SDL thread priority manager: SDL not found Set motd from file 'cfg/motd_default.txt'. ('cfg/motd.txt' was not found.) Set motd_text from file 'cfg/motd_text_default.txt'. ('cfg/motd_text.txt' was not found.) SV_ActivateServer: setting tickrate to 66.7 func_regenerate(func_regenerate) has no associated model. RecordSteamInterfaceCreation (PID 453): SteamGameCoordinator001 / Connection to game coordinator established. Current item schema is up-to-date with version 2B55A3E4. -------------------------------------------------------- sv_pure set to -1. Note: Waiting for the next changelevel to apply the current value. -------------------------------------------------------- 'airborne2.cfg' not present; not executing. Server is hibernating Connection to Steam servers successful. Assigned anonymous gameserver Steam ID [A:1:929544195:17849]. VAC secure mode is activated. From here we know that the server is running, and we can check it ingame: ![](2.png) Now that's done, we verified that we could run the srcds binary like this, however we could have a more refined approach and actually make a systemd service to run this as the debian LXC container starts. root@tf2local:~# vim /etc/systemd/system/tf2server.service root@tf2local:~/tf2# cat /etc/systemd/system/tf2server.service [Unit] Description=TF2 Server After=network.target After=systemd-user-sessions.service After=network-online.target [Service] Type=simple ExecStart=/root/tf2/srcds_run -game tf +map airborne2 ExecStop=/root/tf2/killserver.sh KillMode=process [Install] WantedBy=multi-user.target root@tf2local:~/tf2# vim killserver.sh root@tf2local:~/tf2# cat killserver.sh #!/bin/bash kill -9 $(pidof srcds_linux) root@tf2local:~/tf2# chmod +x killserver.sh root@tf2local:~# systemctl enable --now tf2server root@tf2local:~# systemctl status tf2server * tf2server.service - TF2 Server Loaded: loaded (/etc/systemd/system/tf2server.service; disabled; vendor preset: enabled) Active: active (running) since Fri 2021-07-02 21:13:15 UTC; 3s ago Main PID: 10722 (srcds_run) Tasks: 2 (limit: 7372) Memory: 1.2M CGroup: /system.slice/tf2server.service |-10722 /bin/sh /home/steam/tf2/srcds_run `-10732 sleep 1 Jul 02 23:03:55 tf2local srcds_run[778]: RecordSteamInterfaceCreation (PID 778): SteamGameServer013 / Jul 02 23:03:55 tf2local srcds_run[778]: RecordSteamInterfaceCreation (PID 778): SteamUtils010 / Jul 02 23:03:55 tf2local srcds_run[778]: RecordSteamInterfaceCreation (PID 778): SteamNetworking006 / Jul 02 23:03:55 tf2local srcds_run[778]: RecordSteamInterfaceCreation (PID 778): SteamGameServerStats001 / Jul 02 23:03:55 tf2local srcds_run[778]: RecordSteamInterfaceCreation (PID 778): STEAMHTTP_INTERFACE_VERSION003 / Jul 02 23:03:55 tf2local srcds_run[778]: RecordSteamInterfaceCreation (PID 778): STEAMINVENTORY_INTERFACE_V003 / Jul 02 23:03:55 tf2local srcds_run[778]: RecordSteamInterfaceCreation (PID 778): STEAMUGC_INTERFACE_VERSION014 / Jul 02 23:03:55 tf2local srcds_run[778]: RecordSteamInterfaceCreation (PID 778): STEAMAPPS_INTERFACE_VERSION008 / Jul 02 23:04:05 tf2local srcds_run[778]: RecordSteamInterfaceCreation (PID 778): SteamGameStats001 / Jul 02 23:04:09 tf2local srcds_run[778]: RecordSteamInterfaceCreation (PID 778): SteamGameCoordinator001 / And that's it! We managed to setup a simple local tf2 server. ## **In-game RCON and Bonus plugins** if you want to run console comamnds that require privileges to do so on your local server, you need to use rcon, and since we specified the password earlier, we do the following: ![](3.png) Obviously don't give the rcon password to anyone you don't trust. Now if you want some plugins you can install [sourcemod](https://www.sourcemod.net/downloads.php) and [metamod](http://www.sourcemm.net/downloads.php?branch=stable): ![](4.png) root@tf2local:~/tf2# cd tf/ root@tf2local:~/tf2/tf# ls bin maps steam.inf tf2_misc_006.vpk tf2_misc_013.vpk tf2_misc_020.vpk tf2_sound_misc_dir.vpk cfg materials tf2_misc_000.vpk tf2_misc_007.vpk tf2_misc_014.vpk tf2_misc_021.vpk tf2_sound_vo_english.vpk.sound.cache custom media tf2_misc_001.vpk tf2_misc_008.vpk tf2_misc_015.vpk tf2_misc_022.vpk tf2_sound_vo_english_dir.vpk download modelsounds.cache tf2_misc_002.vpk tf2_misc_009.vpk tf2_misc_016.vpk tf2_misc_023.vpk tf2_textures_dir.vpk downloadlists replay tf2_misc_003.vpk tf2_misc_010.vpk tf2_misc_017.vpk tf2_misc_024.vpk workshop gameinfo.txt resource tf2_misc_004.vpk tf2_misc_011.vpk tf2_misc_018.vpk tf2_misc_dir.vpk item_whitelist_example.txt scripts tf2_misc_005.vpk tf2_misc_012.vpk tf2_misc_019.vpk tf2_sound_misc.vpk.sound.cache root@tf2local:~/tf2/tf# wget https://sm.alliedmods.net/smdrop/1.10/sourcemod-1.10.0-git6509-linux.tar.gz --2021-07-03 17:25:03-- https://sm.alliedmods.net/smdrop/1.10/sourcemod-1.10.0-git6509-linux.tar.gz Resolving sm.alliedmods.net (sm.alliedmods.net)... 104.26.8.106, 104.26.9.106, 172.67.73.151, ... Connecting to sm.alliedmods.net (sm.alliedmods.net)|104.26.8.106|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 17422077 (17M) [application/x-gzip] Saving to: 'sourcemod-1.10.0-git6509-linux.tar.gz' sourcemod-1.10.0-git6509-linux.tar.gz 100%[===============================================================================================>] 16.61M 1.03MB/s in 17s 2021-07-03 17:25:21 (998 KB/s) - 'sourcemod-1.10.0-git6509-linux.tar.gz' saved [17422077/17422077] root@tf2local:~/tf2/tf# wget https://mms.alliedmods.net/mmsdrop/1.11/mmsource-1.11.0-git1144-linux.tar.gz --2021-07-03 17:30:14-- https://mms.alliedmods.net/mmsdrop/1.11/mmsource-1.11.0-git1144-linux.tar.gz Resolving mms.alliedmods.net (mms.alliedmods.net)... 104.26.8.106, 172.67.73.151, 104.26.9.106, ... Connecting to mms.alliedmods.net (mms.alliedmods.net)|104.26.8.106|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 1859179 (1.8M) [application/x-gzip] Saving to: 'mmsource-1.11.0-git1144-linux.tar.gz' mmsource-1.11.0-git1144-linux.tar.gz 100%[===============================================================================================>] 1.77M 677KB/s in 2.7s 2021-07-03 17:30:18 (677 KB/s) - 'mmsource-1.11.0-git1144-linux.tar.gz' saved [1859179/1859179] then extract both files: root@tf2local:~/tf2/tf# tar -xzf mmsource-1.11.0-git1144-linux.tar.gz root@tf2local:~/tf2/tf# tar -xzf sourcemod-1.10.0-git6509-linux.tar.gz root@tf2local:~/tf2/tf# rm mmsource-1.11.0-git1144-linux.tar.gz root@tf2local:~/tf2/tf# rm sourcemod-1.10.0-git6509-linux.tar.gz root@tf2local:~/tf2/tf# ls -lash addons/ total 24K 4.0K drwx------ 4 1000 1000 4.0K May 6 2018 . 4.0K drwxr-xr-x 15 root root 4.0K Jul 3 17:32 .. 4.0K drwx------ 3 1000 1000 4.0K May 6 2018 metamod 4.0K -rw------- 1 1000 1000 50 May 26 2014 metamod.vdf 4.0K -rw------- 1 1000 1000 58 Dec 20 2017 metamod_x64.vdf 4.0K drwx------ 11 1000 1000 4.0K Oct 1 2019 sourcemod Now that's done we have our addons folder, we will need to configure **admins_simple.ini** root@tf2local:~/tf2/tf# cd addons/sourcemod/configs/ root@tf2local:~/tf2/tf/addons/sourcemod/configs# ls admin_groups.cfg admin_overrides.cfg adminmenu_custom.txt adminmenu_sorting.txt admins_simple.ini core.cfg geoip maplists.cfg admin_levels.cfg adminmenu_cfgs.txt adminmenu_grouping.txt admins.cfg banreasons.txt databases.cfg languages.cfg sql-init-scripts root@tf2local:~/tf2/tf/addons/sourcemod/configs# vim admins_simple.ini Basically in here we add our **SteamID** with the **"99:z"** permissions root@tf2local:~/tf2/tf/addons/sourcemod/configs# tail -n 3 admins_simple.ini "STEAM_0:0:576829438" "99:z" And with this we can restart our tf2 server: root@tf2local:~/tf2/tf/addons/sourcemod/configs# systemctl restart tf2server Now when we connect back to the server we can type **!sm_admin** in chat to use the sourcemod admin commands pannel: ![](5.png) If you need to make any custom scripts, for example making players and bots spawn with extra health, you can use the **scripting** directory in sourcemod: root@tf2local:~/tf2/tf/addons/sourcemod# cd scripting/ root@tf2local:~/tf2/tf/addons/sourcemod/scripting# ls -l total 1080 drwx------ 2 1000 1000 4096 May 6 2018 admin-flatfile -rw------- 1 1000 1000 9857 May 6 2018 admin-sql-prefetch.sp -rw------- 1 1000 1000 21482 Dec 17 2018 admin-sql-threaded.sp -rw------- 1 1000 1000 4822 Jul 12 2018 adminhelp.sp drwx------ 2 1000 1000 4096 Sep 15 2019 adminmenu -rw------- 1 1000 1000 7284 May 29 2019 adminmenu.sp -rw------- 1 1000 1000 3637 Dec 17 2018 antiflood.sp drwx------ 2 1000 1000 4096 Dec 17 2018 basebans -rw------- 1 1000 1000 9755 Dec 17 2018 basebans.sp -rw------- 1 1000 1000 12112 May 6 2018 basechat.sp drwx------ 2 1000 1000 4096 Oct 24 2020 basecomm -rw------- 1 1000 1000 7206 Dec 17 2018 basecomm.sp drwx------ 2 1000 1000 4096 Oct 7 2019 basecommands -rw------- 1 1000 1000 11414 Feb 25 2020 basecommands.sp -rw------- 1 1000 1000 12849 Jul 12 2018 basetriggers.sp drwx------ 2 1000 1000 4096 Mar 3 2019 basevotes -rw------- 1 1000 1000 12326 May 12 2019 basevotes.sp -rw------- 1 1000 1000 4386 May 6 2018 clientprefs.sp -rwx------ 1 1000 1000 452 May 6 2018 compile.sh drwx------ 2 1000 1000 4096 May 6 2018 funcommands -rw------- 1 1000 1000 10977 Oct 12 2018 funcommands.sp drwx------ 2 1000 1000 4096 May 6 2018 funvotes -rw------- 1 1000 1000 10707 May 12 2019 funvotes.sp drwx------ 2 1000 1000 4096 Jun 25 15:36 include -rw------- 1 1000 1000 34195 May 29 2019 mapchooser.sp -rw------- 1 1000 1000 6878 May 6 2018 nextmap.sp -rw------- 1 1000 1000 13402 Apr 30 2020 nominations.sp drwx------ 2 1000 1000 4096 May 6 2018 playercommands -rw------- 1 1000 1000 3351 May 6 2018 playercommands.sp -rw------- 1 1000 1000 3484 May 6 2018 randomcycle.sp -rw------- 1 1000 1000 8191 May 6 2018 reservedslots.sp -rw------- 1 1000 1000 7322 Jul 12 2018 rockthevote.sp -rw------- 1 1000 1000 3712 May 6 2018 sounds.sp -rwx------ 1 1000 1000 333328 Jun 25 15:37 spcomp -rwx------ 1 1000 1000 434152 Jun 25 15:38 spcomp64 -rw------- 1 1000 1000 25196 Apr 6 2019 sql-admin-manager.sp drwx------ 2 1000 1000 4096 May 6 2018 testsuite root@tf2local:~/tf2/tf/addons/sourcemod/scripting# cat maxhealth.sp /** * MaxHealth Changer by bl4nk * * Description: * Change the max health of players at spawn. * */ #pragma semicolon 1 #include <****sourcemod> // Global Definitions #define PLUGIN_VERSION "1.0.0" new Handle:cvarAmount; public Plugin:myinfo = { name = "MaxHealth Changer", author = "bl4nk", description = "Change the max health of players at spawn", version = PLUGIN_VERSION, url = "http://forums.alliedmods.net" }; public OnPluginStart() { CreateConVar("sm_maxhealthchanger_version", PLUGIN_VERSION, "MaxHealth Changer Version"); cvarAmount = CreateConVar("sm_maxhealth", "200", "Amount of life to change health to upon spawn"); HookEvent("player_spawn", event_PlayerSpawn); } public event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) { new client = GetClientOfUserId(GetEventInt(event,"userid")); CreateTimer(0.1, timer_PlayerSpawn, client); } public Action:timer_PlayerSpawn(Handle:timer, any:client) { new MaxHealth = GetConVarInt(cvarAmount); SetEntData(client, FindDataMapInfo(client, "m_iMaxHealth"), MaxHealth, 4, true); SetEntData(client, FindDataMapInfo(client, "m_iHealth"), MaxHealth, 4, true); } Now before we move on we need to compile that .sp file: root@tf2local:~/tf2/tf/addons/sourcemod/scripting# ./compile.sh maxhealth.sp Compiling maxhealth.sp... SourcePawn Compiler 1.10.0.6509 Copyright (c) 1997-2006 ITB CompuPhase Copyright (c) 2004-2018 AlliedModders LLC Code size: 3668 bytes Data size: 2600 bytes Stack/heap size: 16384 bytes Total requirements: 22652 bytes root@tf2local:~/tf2/tf/addons/sourcemod/scripting# ls -lash compiled/ total 16K 4.0K drwxr-xr-x 2 root root 4.0K Jul 3 18:17 . 4.0K drwx------ 14 1000 1000 4.0K Jul 3 18:30 .. 8.0K -rw-r--r-- 1 root root 4.3K Jul 3 18:26 maxhealth.smx root@tf2local:~/tf2/tf/addons/sourcemod/scripting# cp compiled/maxhealth.smx ../plugins/maxhealth.smx Now that we moved the compiled plugin into the plugins directory, we restart the server to reload the configs: root@tf2local:~/tf2/tf/addons/sourcemod/scripting# cd .. root@tf2local:~/tf2/tf/addons/sourcemod# systemctl restart tf2server We restart the server to reload the configs, and we can verify it is working by executing the **sm_maxhealth x** command, if you use it ingame you need to use **rcon sm_maxhealth x** : ![](6.png) ![](7.png) likewise, we can also just put it in the **server.cfg** file or just pass it as arguements when we run the **srcds_run** binary. root@tf2local:~/tf2/tf/cfg# vim server.cfg root@tf2local:~/tf2/tf/cfg# cat server.cfg hostname "void.yt" sv_password "" sv_lan 1 sv_cheats 1 rcon_password "void.yt" mp_enableroundwaittime 0 sv_rcon_banpenalty 15 sv_rcon_minfailures 15 sv_rcon_maxfailures 15 log off sv_logfile 0 sv_logecho 0 sv_logbans 0 sm_maxhealth 100000 tf_bot_force_class soldier sv_pure -1 sv_pure_kick_clients 0 sv_alltalk 1 mp_allowspectators 0 mp_autoteambalance 0 mp_teams_unbalance_limit 30 mp_disable_respawn_times 1 tf_bot_force_class soldier mp_forcecamera 0 sv_allow_wait_command 0 sv_cheats 0 sv_pausable 0 mp_stalemate_enable 0 mp_stalemate_timelimit 240 mp_winlimit 0 mp_timelimit 0 tf_weapon_criticals 0 tf_use_fixed_weaponspreads 0 sv_maxrate 50000 sv_minrate 7500 sv_maxupdaterate 66 sv_minupdaterate 20 sv_maxcmdrate 66 sv_mincmdrate 0 sv_allow_point_servercommand always tf_bot_add 1 soldier red expert root@tf2local:~/tf2/tf/cfg# systemctl restart tf2server And that's how i setup my own personal TF2 training server! ## **Docker Setup** With further testing, i realised that setting up tf2 servers is dependant on old 32 bit librairies, and you can face any number of problems (most notably the segmentation fault core dumped crashes that will never tell you the source of the issue, even with the -debug flag). So instead let's set it up using docker: root@docker0:/home# mkdir -p /home/tf2/server/tf/maps/ root@docker0:/home# tree . . ├── nothing └── tf2 └── server └── tf └── maps └── altar.bsp root@docker0:~# cd ~ ; root@docker0:~# docker pull cm2network/tf2:latest root@docker0:~# docker pull cm2network/tf2:sourcemod root@docker0:~# mkdir tf2 root@docker0:~/tf2# vim docker-compose.yml root@docker0:~/tf2# cat docker-compose.yml version: "3" services: tf2: image: cm2network/tf2:sourcemod container_name: tf2 environment: - SRCDS_RCONPW=void.yt - SRCDS_PW=void.yt - SRCDS_PORT=27015 - SRCDS_TV_PORT=27020 #- SRCDS_NET_PUBLIC_ADDRESS="0" - SRCDS_IP="0" - SRCDS_FPSMAX=300 - SRCDS_TICKRATE=66 - SRCDS_MAXPLAYERS=14 - SRCDS_HOSTNAME=void.yt - SRCDS_TOKEN="void.yt" - SRCDS_STARTMAP="altar" volumes: - ./data:/home/steam/tf-dedicated/ - ./logs:/home/steam/Steam/logs ports: - 27015:27015 - 27020:27020 network_mode: host root@docker0:~/tf2# mkdir data root@docker0:~/tf2# mkdir logs root@docker0:~/tf2# chmod 777 data/ root@docker0:~/tf2# chmod 777 logs/ root@docker0:~/tf2# docker-compose up #let it finish then CTRL+C #move altar.bsp in ~/tf2/data/tf/maps root@docker0:~/tf2/data/tf/maps# ls -lash altar.bsp 172K -rw-r--r-- 1 root root 169K Oct 30 16:12 altar.bsp #append the sourcemodded commands you want to server.cfg : root@docker0:~# tail -n13 tf2/data/tf/cfg/server.cfg sm_maxhealth 100000 tf_bot_add 1 soldier expert tf_bot_force_class soldier mp_allowspectators 0 mp_autoteambalance 0 mp_teams_unbalance_limit 30 mp_disable_respawn_times 1 tf_bot_force_class soldier sv_allow_point_servercommand always Then compile the maxhealth mod in the container: root@docker0:~# docker exec -it tf2 bash steam@docker0:~/tf-dedicated/tf/addons/sourcemod/scripting$ nano maxhealth.sp steam@docker0:~/tf-dedicated/tf/addons/sourcemod/scripting$ cat maxhealth.sp /** * MaxHealth Changer by bl4nk * * Description: * Change the max health of players at spawn. * */ #pragma semicolon 1 #include // Global Definitions #define PLUGIN_VERSION "1.0.0" new Handle:cvarAmount; public Plugin:myinfo = { name = "MaxHealth Changer", author = "bl4nk", description = "Change the max health of players at spawn", version = PLUGIN_VERSION, url = "http://forums.alliedmods.net" }; public OnPluginStart() { CreateConVar("sm_maxhealthchanger_version", PLUGIN_VERSION, "MaxHealth Changer Version"); cvarAmount = CreateConVar("sm_maxhealth", "200", "Amount of life to change health to upon spawn"); HookEvent("player_spawn", event_PlayerSpawn); } public event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) { new client = GetClientOfUserId(GetEventInt(event,"userid")); CreateTimer(0.1, timer_PlayerSpawn, client); } public Action:timer_PlayerSpawn(Handle:timer, any:client) { new MaxHealth = GetConVarInt(cvarAmount); SetEntData(client, FindDataMapInfo(client, "m_iMaxHealth"), MaxHealth, 4, true); SetEntData(client, FindDataMapInfo(client, "m_iHealth"), MaxHealth, 4, true); } steam@docker0:~/tf-dedicated/tf/addons/sourcemod/scripting$ ./compile.sh maxhealth.sp Compiling maxhealth.sp... SourcePawn Compiler 1.10.0.6522 Copyright (c) 1997-2006 ITB CompuPhase Copyright (c) 2004-2018 AlliedModders LLC Code size: 3668 bytes Data size: 2600 bytes Stack/heap size: 16384 bytes Total requirements: 22652 bytes steam@docker0:~/tf-dedicated/tf/addons/sourcemod/scripting$ cp compiled/maxhealth.smx ../plugins/maxhealth.smx steam@docker0:~/tf-dedicated/tf/addons/sourcemod/configs# vim admins_simple.ini "STEAM_0:0:576829438" "99:z" Then restart the container: CTRL+C root@docker0:~/tf2# docker-compose up [ 10.66.66.2/32 ] [ /dev/pts/19 ] [~] → cat tf2.sh #!/bin/sh /usr/bin/steam -silent -no-browser -offline -applaunch 440 -windowed -w 3840 -h 2160 +connect 192.168.0.200 -noborder -console -novid +viewmodel_fov 130 >/dev/null 2>/dev/null & echo 'rcon_password void.yt ; rcon sv_cheats 1; rcon tf_bot_add 2 soldier red expert; rcon buddha' root@tf2:~# apt update -y ; apt upgrade -y ; apt install sudo -y root@tf2:~# adduser gameserver Adding user `gameserver' ... Adding new group `gameserver' (1000) ... Adding new user `gameserver' (1000) with group `gameserver' ... Creating home directory `/home/gameserver' ... Copying files from `/etc/skel' ... New password: Retype new password: passwd: password updated successfully Changing the user information for gameserver Enter the new value, or press ENTER for the default Full Name []: Room Number []: Work Phone []: Home Phone []: Other []: Is the information correct? [Y/n] y root@tf2:~# usermod -aG sudo gameserver root@tf2:~# su - gameuser su: user gameuser does not exist root@tf2:~# su - gameserver gameserver@tf2:~$ pwd /home/gameserver gameserver@tf2:~$ ls -l total 0 gameserver@tf2:~$ ls -lash total 20K 4.0K drwxr-xr-x 2 gameserver gameserver 4.0K Dec 12 13:27 . 4.0K drwxr-xr-x 3 root root 4.0K Dec 12 13:27 .. 4.0K -rw-r--r-- 1 gameserver gameserver 220 Dec 12 13:27 .bash_logout 4.0K -rw-r--r-- 1 gameserver gameserver 3.5K Dec 12 13:27 .bashrc 4.0K -rw-r--r-- 1 gameserver gameserver 807 Dec 12 13:27 .profile gameserver@tf2:~$ mkdir hlserver gameserver@tf2:~$ cd hlserver/ gameserver@tf2:~/hlserver$ wget https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz --2021-12-12 13:27:48-- https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz Resolving steamcdn-a.akamaihd.net (steamcdn-a.akamaihd.net)... 92.123.225.26, 92.123.225.73 Connecting to steamcdn-a.akamaihd.net (steamcdn-a.akamaihd.net)|92.123.225.26|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 2428561 (2.3M) [application/octet-stream] Saving to: 'steamcmd_linux.tar.gz' steamcmd_linux.tar.gz 100%[=====================================================================================================================>] 2.32M 4.49MB/s in 0.5s 2021-12-12 13:27:49 (4.49 MB/s) - 'steamcmd_linux.tar.gz' saved [2428561/2428561] gameserver@tf2:~/hlserver$ tar zxf steamcmd_linux.tar.gz gameserver@tf2:~/hlserver$ ./steamcmd.sh +login anonymous +force_install_dir ./tf2 +app_update 232250 +quit ./steamcmd.sh: line 37: /home/gameserver/hlserver/linux32/steamcmd: No such file or directory gameserver@tf2:~$ sudo dpkg --add-architecture i386 gameserver@tf2:~$ sudo apt-get update Hit:1 http://security.debian.org buster/updates InRelease Hit:2 http://ftp.debian.org/debian buster InRelease Hit:3 http://ftp.debian.org/debian buster-updates InRelease Get:4 http://security.debian.org buster/updates/main i386 Packages [311 kB] Get:5 http://ftp.debian.org/debian buster/main i386 Packages [7863 kB] Get:6 http://ftp.debian.org/debian buster/contrib i386 Packages [46.0 kB] Get:7 http://ftp.debian.org/debian buster-updates/main i386 Packages [15.2 kB] Fetched 8236 kB in 5s (1803 kB/s) Reading package lists... Done gameserver@tf2:~$ sudo apt-get install lib32z1 libncurses5:i386 libbz2-1.0:i386 lib32gcc1 lib32stdc++6 libtinfo5:i386 libcurl3-gnutls:i386 -y gameserver@tf2:~/hlserver$ ./steamcmd.sh +login anonymous +force_install_dir ./tf2 +app_update 232250 +quit Redirecting stderr to '/home/gameserver/Steam/logs/stderr.txt' ILocalize::AddFile() failed to load file "public/steambootstrapper_english.txt". [ 0%] Checking for available update... [----] Downloading update (0 of 53822 KB)... [ 0%] Downloading update (1235 of 53822 KB)... [ 2%] Downloading update (2823 of 53822 KB)... [ 5%] Downloading update (4637 of 53822 KB)... [ 8%] Downloading update (6584 of 53822 KB)... [ 12%] Downloading update (8194 of 53822 KB)... [ 15%] Downloading update (9681 of 53822 KB)... [ 17%] Downloading update (11333 of 53822 KB)... [ 21%] Downloading update (12822 of 53822 KB)... gameserver@tf2:~/hlserver$ cd tf2/ gameserver@tf2:~/hlserver/tf2$ cd tf/maps gameserver@tf2:~/hlserver/tf2/tf/maps$ wget https://cloud.void.yt/s/wGeqMTLzyyGBfiD/download/altar.bsp gameserver@tf2:~/hlserver$ cd tf2 gameserver@tf2:~/hlserver/tf2$ ls -lash total 104K 4.0K drwxr-xr-x 7 gameserver gameserver 4.0K Dec 12 13:59 . 4.0K drwxr-xr-x 8 gameserver gameserver 4.0K Dec 12 13:59 .. 4.0K drwxr-xr-x 2 gameserver gameserver 4.0K Dec 12 13:53 bin 4.0K drwxr-xr-x 4 gameserver gameserver 4.0K Dec 12 13:53 hl2 4.0K drwxr-xr-x 6 gameserver gameserver 4.0K Dec 12 13:53 platform 12K -rwxr-xr-x 1 gameserver gameserver 12K Dec 12 13:48 srcds_linux 12K -rwxr-xr-x 1 gameserver gameserver 9.6K Dec 12 13:48 srcds_run 4.0K drwxr-xr-x 5 gameserver gameserver 4.0K Dec 12 13:53 steamapps 4.0K drwxr-xr-x 12 gameserver gameserver 4.0K Dec 12 13:53 tf 4.0K -rwxr-xr-x 1 gameserver gameserver 77 Dec 12 13:56 tf2.sh 48K -rwxr-xr-x 1 gameserver gameserver 47K Dec 12 13:48 thirdpartylegalnotices.txt gameserver@tf2:~/hlserver/tf2$ cat tf2.sh #!/bin/sh ./srcds_run -console -game tf +sv_pure 1 +map altar +maxplayers 24 gameserver@tf2:~/hlserver/tf2$ sudo apt install mlocate -y gameserver@tf2:~/hlserver/tf2$ sudo updatedb gameserver@tf2:~/hlserver/tf2$ locate steamclient.so /home/gameserver/hlserver/linux32/steamclient.so /home/gameserver/hlserver/linux64/steamclient.so /home/gameserver/hlserver/tf2/bin/steamclient.so gameserver@tf2:~/hlserver$ mkdir -p /home/gameserver/.steam/sdk32/ gameserver@tf2:~/hlserver$ ln -s /home/gameserver/hlserver/linux32/steamclient.so /home/gameserver/.steam/sdk32/ gameserver@tf2:~/hlserver/tf2$ sudo vim /etc/systemd/system/tf2server.service gameserver@tf2:~/hlserver/tf2$ cat /etc/systemd/system/tf2server.service [Unit] Description=TF2 Server After=network.target After=systemd-user-sessions.service After=network-online.target [Service] Type=simple User=gameserver ExecStart=/home/gameserver/hlserver/tf2/srcds_run -game tf +map altar +sv_pure 1 +maxplayers 24 -console ExecStop=/home/gameserver/hlserver/tf2/killserver.sh KillMode=process [Install] WantedBy=multi-user.target gameserver@tf2:~/hlserver/tf2$ vim killserver.sh gameserver@tf2:~/hlserver/tf2$ cat killserver.sh #!/bin/bash kill -9 $(pidof srcds_linux) gameserver@tf2:~/hlserver/tf2$ chmod +x killserver.sh gameserver@tf2:~/hlserver/tf2$ sudo systemctl daemon-reload gameserver@tf2:~/hlserver/tf2$ sudo systemctl start tf2server gameserver@tf2:~/hlserver/tf2$ cd tf gameserver@tf2:~/hlserver/tf2/tf$ cd cfg gameserver@tf2:~/hlserver/tf2/tf/cfg$ vim server.cfg gameserver@tf2:~/hlserver/tf2/tf/cfg$ cat server.cfg hostname "void.yt" sv_password "" sv_lan 1 sv_cheats 1 rcon_password "void.yt" sm_maxhealth 100000 mp_allowspectators 0 mp_autoteambalance 0 mp_teams_unbalance_limit 30 mp_disable_respawn_times 1 mp_timelimit 0 mp_stalemate_enable 0 gameserver@tf2:~/hlserver/tf2/tf$ wget https://mms.alliedmods.net/mmsdrop/1.11/mmsource-1.11.0-git1145-linux.tar.gz --2021-12-12 15:00:16-- https://mms.alliedmods.net/mmsdrop/1.11/mmsource-1.11.0-git1145-linux.tar.gz Resolving mms.alliedmods.net (mms.alliedmods.net)... 104.26.9.106, 172.67.73.151, 104.26.8.106, ... Connecting to mms.alliedmods.net (mms.alliedmods.net)|104.26.9.106|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 1859188 (1.8M) [application/x-gzip] Saving to: 'mmsource-1.11.0-git1145-linux.tar.gz' mmsource-1.11.0-git1145-linux.tar.gz 100%[=====================================================================================================================>] 1.77M 4.40MB/s in 0.4s 2021-12-12 15:00:16 (4.40 MB/s) - 'mmsource-1.11.0-git1145-linux.tar.gz' saved [1859188/1859188] gameserver@tf2:~/hlserver/tf2/tf$ wget https://sm.alliedmods.net/smdrop/1.10/sourcemod-1.10.0-git6528-linux.tar.gz --2021-12-12 15:00:25-- https://sm.alliedmods.net/smdrop/1.10/sourcemod-1.10.0-git6528-linux.tar.gz Resolving sm.alliedmods.net (sm.alliedmods.net)... 104.26.9.106, 172.67.73.151, 104.26.8.106, ... Connecting to sm.alliedmods.net (sm.alliedmods.net)|104.26.9.106|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 17500442 (17M) [application/x-gzip] Saving to: 'sourcemod-1.10.0-git6528-linux.tar.gz' sourcemod-1.10.0-git6528-linux.tar.gz 100%[=====================================================================================================================>] 16.69M 5.35MB/s in 3.1s 2021-12-12 15:00:28 (5.35 MB/s) - 'sourcemod-1.10.0-git6528-linux.tar.gz' saved [17500442/17500442] gameserver@tf2:~/hlserver/tf2/tf$ tar -xzf mmsource-1.11.0-git1144-linux.tar.gz gameserver@tf2:~/hlserver/tf2/tf$ tar -xzf sourcemod-1.10.0-git6509-linux.tar.gz gameserver@tf2:~/hlserver/tf2/tf$ cd addons/sourcemod/configs/ gameserver@tf2:~/hlserver/tf2/tf/addons/sourcemod/configs$ vim admins_simple.ini gameserver@tf2:~/hlserver/tf2/tf/addons/sourcemod/configs$ cat admins_simple.ini "STEAM_0:0:29598280" "99:z" gameserver@tf2:~/hlserver/tf2/tf/addons/sourcemod/scripting$ vim maxhealth.sp gameserver@tf2:~/hlserver/tf2/tf/addons/sourcemod/scripting$ cat maxhealth.sp /** * MaxHealth Changer by bl4nk * * Description: * Change the max health of players at spawn. * */ #pragma semicolon 1 #include <****sourcemod> // Global Definitions #define PLUGIN_VERSION "1.0.0" new Handle:cvarAmount; public Plugin:myinfo = { name = "MaxHealth Changer", author = "bl4nk", description = "Change the max health of players at spawn", version = PLUGIN_VERSION, url = "http://forums.alliedmods.net" }; public OnPluginStart() { CreateConVar("sm_maxhealthchanger_version", PLUGIN_VERSION, "MaxHealth Changer Version"); cvarAmount = CreateConVar("sm_maxhealth", "200", "Amount of life to change health to upon spawn"); HookEvent("player_spawn", event_PlayerSpawn); } public event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) { new client = GetClientOfUserId(GetEventInt(event,"userid")); CreateTimer(0.1, timer_PlayerSpawn, client); } public Action:timer_PlayerSpawn(Handle:timer, any:client) { new MaxHealth = GetConVarInt(cvarAmount); SetEntData(client, FindDataMapInfo(client, "m_iMaxHealth"), MaxHealth, 4, true); SetEntData(client, FindDataMapInfo(client, "m_iHealth"), MaxHealth, 4, true); } gameserver@tf2:~/hlserver/tf2/tf/addons/sourcemod/scripting$ ./compile.sh maxhealth.sp Compiling maxhealth.sp... SourcePawn Compiler 1.10.0.6509 Copyright (c) 1997-2006 ITB CompuPhase Copyright (c) 2004-2018 AlliedModders LLC Code size: 3668 bytes Data size: 2600 bytes Stack/heap size: 16384 bytes Total requirements: 22652 bytes gameserver@tf2:~/hlserver/tf2/tf/addons/sourcemod/scripting$ cp compiled/maxhealth.smx ../plugins/maxhealth.smx gameserver@tf2:~/hlserver/tf2/tf/addons/sourcemod/scripting$ sudo systemctl restart tf2server script to run daily to ensure the tf2 server is always up to date gameserver@tf2:~/hlserver$ ./steamcmd.sh +login anonymous +app_update 232250 validate gameserver@tf2:~/hlserver$ exit logout root@tf2:~# crontab -e 0 3 * * * /home/gameserver/hlserver/steamcmd.sh +login anonymous +app_update 232250 validate 0 4 * * * systemctl restart tf2server