Team Fortress 2 Linux Dedicated Server

Vorwort

Als begeisterter und langjähriger Spieler des Online-Multiplayer-Shooters Team Fortress 2 wurde ich auch des öfteren gefragt, wie man seinen eigenen dedizierten Gameserver aufsetzt. Leider behandeln die offiziellen Seiten das Thema etwas zu oberflächlich, deshalb habe ich hier ein kleines Tutorial für Debian/Ubuntu-Nutzer gebastelt.

Software

Ich gehe hier auf meine Lieblings-Linux-Distribution

  • Debian „Lenny“ 5

ein :-) Der Großteil der Anleitung ist natürlich auch auf andere Distros übertragbar.

Vorbereitung

Das Arbeiten in einer root-Shell wird empfohlen!

sudo muss installiert sein!

x86 (32-Bit)

Es sollten keinerlei Pakete nachzuladen sein.

x64 (64-Bit)

Auf dieser Plattform müssen noch entsprechende 32-Bit Bibliotheken nachinstalliert werden:

aptitude install ia32-libs lib32gcc1

System

Aus Sicherheitsgründen lassen wir den Server nicht als Superuser laufen und geben ihm zunächst einen eigenen Systemnutzer:

useradd --system --shell /bin/false --create-home -d /home/srcds srcds

Installation

Die Linux-Version von Steam wird von dem Programm hldsupdatetool.bin angefordert und entpackt, sofern die Lizenzfrage mit yes beantwortet wird. Danach wird Steam zunächst aktualisiert und schließlich der Team Fortress 2 Content heruntergeladen:

cd /home/srcds
wget http://www.steampowered.com/download/hldsupdatetool.bin
chmod +x hldsupdatetool.bin
./hldsupdatetool.bin
./steam
./steam -command update -game tf -dir .

Dieser Vorgang kann einige Zeit dauern. Nachdem Steam seine Arbeit getan hat, müssen noch die Dateirechte adjustiert werden:

chown srcds:srcds -R /home/srcds/

Dieser Schritt ist sehr wichtig!

Startskript

SysV

Da man den Server höchstwahrscheinlich auch im Hintergrund laufen lassen bzw. ihn nach einem Reboot automatisch starten möchte, habe ich hier ein vollwertiges Init-Skript erstellt, mit dem sich auch bequem Updates laden lassen. Die Meisten der anderen Lösungen zweckentfremden dazu screen, ich verwende das dafür vorgesehene start-stop-daemon. Das folgende Schnipsel kopiert oder downloadet man sich nach /etc/init.d/:

srcds
#!/bin/sh
 
### BEGIN INIT INFO
# Provides:          hlds
# Required-Start:    $local_fs $network
# Required-Stop:     $local_fs
# Default-Start:     3 4 5
# Default-Stop:      0 1 6
# Short-Description: Linux Source Dedicated Server
# Description:       Linux version of the Source Dedicated Server.
### END INIT INFO
 
# --------- adjust this ----------
USER="srcds"
STEAM_DIR="/home/$USER"
TF2MAP="ctf_2fort"
SRCDS_OPT="-game tf +maxplayers 24 +map $TF2MAP -autoupdate"
 
# -------- DO NOT CHANGE! --------
NAME="srcds_linux"
STEAM_BIN="$STEAM_DIR/steam"
SRCDS_DIR="$STEAM_DIR/orangebox"
STEAM_ARG="-command update -game tf -dir $STEAM_DIR"
SRCDS="$SRCDS_DIR/$NAME"
 
export LD_LIBRARY_PATH="$SRCDS_DIR/bin"
 
[ -x "$SRCDS" ] || exit 0
 
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
 
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions
 
#
# Function that updates game content via steam
#
do_update() {
    $STEAM_BIN $STEAM_ARG
    return "$?"
}
 
#
# Function that starts the srcds
#
do_start() {
    chown -R $USER $STEAM_BIN
    start-stop-daemon --start --quiet --exec $SRCDS --test > /dev/null \
      || return 1
    start-stop-daemon --start --background --quiet --name $NAME --chuid $USER \
      --chdir $SRCDS_DIR --exec $SRCDS -- $SRCDS_OPT \
      || return 2
}
 
#
# Function that stops the srcds
#
do_stop() {
    start-stop-daemon --stop --quiet --retry=TERM/10/KILL/5 --name $NAME
    RETVAL="$?"
    [ "$RETVAL" = 2 ] && return 2
    return "$RETVAL"
}
 
case "$1" in
  start)
    [ "$VERBOSE" != no ] && log_daemon_msg "Starting $NAME"
    do_start
	case "$?" in
        0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
        2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    esac
    ;;
  stop)
    [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $NAME"
    do_stop
    case "$?" in
        0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
        2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    esac
    ;;
  restart|force-reload|reload)
    log_daemon_msg "Restarting $NAME"
    do_stop
    case "$?" in
      0|1)
        do_start
        case "$?" in
            0) log_end_msg 0 ;;
            1) log_end_msg 1 ;; # Old process is still running
            *) log_end_msg 1 ;; # Failed to start
        esac
        ;;
      *)
        # Failed to stop
        log_end_msg 1
        ;;
    esac
    ;;
  update)
    do_stop
    [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $NAME"
    do_stop
    case "$?" in
        0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
        2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    esac
    [ "$VERBOSE" != no ] && log_daemon_msg "Updating steam content, please stand by"
    echo
    do_update
    case "$?" in
        0) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
        *) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    esac
    [ "$VERBOSE" != no ] && log_daemon_msg "Starting $NAME"
    do_start
    case "$?" in
        0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
        2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    esac
    ;;
  *)
    echo "Usage: "$1" {start|stop|restart|update}"
    exit 1
esac
 
exit 0

Schließlich noch den entsprechenden Runleveln zuweisen:

update-rc.d srcds defaults

Danach kann getestet werden, indem man z.B. Folgendes zum Updaten des Spiels aufruft:

invoke-rc.d srcds update

Die Ausgabe davon könnte etwa so aussehen (wenn das Spiel aktuell ist):

Stopping srcds_linux:.
Updating steam content, please stand by:
Checking bootstrapper version ...
Updating Installation
Checking/Installing 'Team Fortress 2 Content' version 169


Checking/Installing 'Team Fortress 2 Materials' version 71


Checking/Installing 'Base Source Shared Materials' version 8


Checking/Installing 'Base Source Shared Models' version 4


Checking/Installing 'Base Source Shared Sounds' version 4


Checking/Installing 'OB Linux Dedicated Server' version 62


HLDS installation up to date
CAsyncIOManager: 0 threads terminating.  0 reads, 0 writes, 0 deferrals.
CAsyncIOManager: 118 single object sleeps, 0 multi object sleeps
CAsyncIOManager: 0 single object alertable sleeps, 0 multi object alertable sleeps
.
Starting srcds_linux:.

Automatische Aktualisierung

Gerade Team Fortress 2 ist bekannt für seine vielen regelmäßigen Aktualisierungen, die sowohl Clients als auch Server einspielen müssen, um miteinander kommunizieren zu können. In der Praxis ist es eine gute Idee, den Server täglich zu aktualisieren. Hierzu können wir uns des crond bedienen indem wir folgende Datei nach /etc/cron.daily/ verfrachten:

srcds
#!/bin/sh
 
[ -x /etc/init.d/srcds ] || exit 1
. /etc/init.d/srcds update >/dev/null 2>&1
 
exit 0

Wenn ihr täglich per Mail über durchgeführte Aktualisierungen informiert werden wollt, einfach >/dev/null 2>&1 weglassen. Natürlich kann auch weiterhin manuell aktualisiert werden:

invoke-rc.d srcds update

Konfiguration

Natürlich wäre der Server auch ohne Konfigurationsdatei lauffähig (die Standardwerte würden benutzt), allerdings möchte man in den meisten Fällen seinen Server etwas nach eigenem Geschmack einrichten. Die hiefür notwendigen Direktiven (sog. ConVars oder Cvars) gehören in die /home/srcds/orangebox/tf/cfg/server.cfg, hier ein funktionierendes Beispiel:

server.cfg
// General Settings //
 
// Hostname for server
// this value shows up in the steam master server list
hostname Ub0r1337eRz X7r33m3 tF >2< S3rV0r
 
// Server password for private/clan servers
//sv_password "changeme"
 
// Overrides the max players reported to prospective clients
sv_visiblemaxplayers 24
 
// Maximum number of rounds to play before server changes maps
mp_maxrounds 5
 
// Set to lock per-frame time elapse
host_framerate 0
 
// Set the pause state of the server
setpause 0
 
// Control where the client gets content from 
// 0 = anywhere, 1 = anywhere listed in white list, 2 = steam official content only
sv_pure 1
 
// Is the server pausable
sv_pausable 0
 
// Type of server 0=internet 1=lan
sv_lan 0
 
// Whether the server enforces file consistency for critical files
sv_consistency 1
 
// Collect CPU usage stats
sv_stats 1
 
 
 
// Execute Banned Users //
exec banned_user.cfg
exec banned_ip.cfg
writeid
writeip
 
 
 
// Contact & Region //
 
// Contact email for server sysop
sv_contact owen@example.com
 
// The region of the world to report this server in.
// -1 is the world, 0 is USA east coast, 1 is USA west coast
// 2 south america, 3 europe, 4 asia, 5 australia, 6 middle east, 7 africa
sv_region 3
 
 
 
// Rcon Settings //
 
// Password for rcon authentication
rcon_password changeme
 
// Number of minutes to ban users who fail rcon authentication
sv_rcon_banpenalty 1440
 
// Max number of times a user can fail rcon authentication before being banned
sv_rcon_maxfailures 5
 
 
 
// Log Settings //
 
// Enables logging to file, console, and udp < on | off >.
log on
 
// Log server information to only one file.
sv_log_onefile 0
 
// Log server information in the log file.
sv_logfile 1
 
// Log server bans in the server logs.
sv_logbans 1
 
// Echo log information to the console.
sv_logecho 1
sv_logsdir "logs"
 
 
 
// Rate Settings //
 
// Frame rate limiter
fps_max 600
 
// Min bandwidth rate allowed on server, 0 == unlimited
sv_minrate 0
 
// Max bandwidth rate allowed on server, 0 == unlimited
sv_maxrate 20000
 
// Minimum updates per second that the server will allow
sv_minupdaterate 10
 
// Maximum updates per second that the server will allow
sv_maxupdaterate 66
 
 
 
// Download Settings //
 
// Allow clients to upload customizations files
sv_allowupload 1
 
// Allow clients to download files
sv_allowdownload 1
 
// Maximum allowed file size for uploading in MB
net_maxfilesize 15
 
 
 
// Team Balancing //
 
// Enable team balancing
mp_autoteambalance 1 
 
// Time after the teams become unbalanced to attempt to switch players.
mp_autoteambalance_delay 60
 
// Time after the teams become unbalanced to print a balance warning
mp_autoteambalance_warning_delay 30
 
// Teams are unbalanced when one team has this many more players than the other team. (0 disables check)
mp_teams_unbalance_limit 1
 
 
 
// Round and Game Times //
 
// Enable timers to wait between rounds.
// WARNING: Setting this to 0 has been known to cause a bug with setup times lasting 5:20 
// (5 minutes 20 seconds) on some servers!
mp_enableroundwaittime 1
 
// Time after round win until round restarts
mp_bonusroundtime 8
 
// If non-zero, the current round will restart in the specified number of seconds
mp_restartround 0
 
//Enable sudden death
mp_stalemate_enable 1
 
// Timelimit (in seconds) of the stalemate round.
mp_stalemate_timelimit 60
 
// game time per map in minutes
mp_timelimit 35
 
// no respawn wait time
mp_disable_respawn_times 1
 
 
 
// Client CVARS //
 
// Restricts spectator modes for dead players
mp_forcecamera 0
 
// toggles whether the server allows spectator mode or not
mp_allowspectators 1
 
// toggles footstep sounds
mp_footsteps 1
 
// toggles game cheats
sv_cheats 0
 
// After this many seconds without a message from a client, the client is dropped
sv_timeout 900
 
// Maximum time a player is allowed to be idle (in minutes), made this and sv_timeout equal same time?
mp_idlemaxtime 15
 
// Deals with idle players 1=send to spectator 2=kick
mp_idledealmethod 2
 
// time (seconds) between decal sprays
decalfrequency 30
 
 
 
// Communications //
 
// enable voice communications
sv_voiceenable 1
 
// Players can hear all other players, no team restrictions 0=off 1=on
sv_alltalk 1
 
// amount of time players can chat after the game is over
mp_chattime 10
 
// enable party mode
//tf_birthday 1

Damit es Wirkung zeigt, muss man den Server neu starten:

invoke-rc.d srcds restart

Danach kann der Spielspaß losgehen :-)

Quellen

Kommentare