From 33b4629f27355ff974b9bea550f8e475049febc1 Mon Sep 17 00:00:00 2001 From: Karamel Date: Mon, 8 Jan 2024 23:03:18 +0100 Subject: [PATCH] [Doc] Add dedicated host documentation and linux scripts --- doc/hosting/AutohostConfig.md | 2 +- doc/hosting/DedicatedHost.md | 104 ++++++++++++++++++ doc/hosting/linux_scripts/common.sh | 80 ++++++++++++++ doc/hosting/linux_scripts/config_sample.sh | 46 ++++++++ doc/hosting/linux_scripts/game_sample.sh | 45 ++++++++ .../linux_scripts/wz2100host_sample.service | 17 +++ 6 files changed, 293 insertions(+), 1 deletion(-) create mode 100644 doc/hosting/DedicatedHost.md create mode 100644 doc/hosting/linux_scripts/common.sh create mode 100644 doc/hosting/linux_scripts/config_sample.sh create mode 100644 doc/hosting/linux_scripts/game_sample.sh create mode 100644 doc/hosting/linux_scripts/wz2100host_sample.service diff --git a/doc/hosting/AutohostConfig.md b/doc/hosting/AutohostConfig.md index a85d22f9274..8519bb73292 100644 --- a/doc/hosting/AutohostConfig.md +++ b/doc/hosting/AutohostConfig.md @@ -1,6 +1,6 @@ # Autohost configuration -Running the game with the `--autohost` command line argument opens a game automatically. Combined with `--headless` and `--nosound` it allows to run a dedicated server to host a game. See also `PlayerKeys.md` to add administrators with `--addlobbyadminhash` and `--addlobbyadminpublickey`. +Running the game with the `--autohost` command line argument opens a game automatically. Combined with `--headless` and `--nosound` it allows to run a dedicated server to host a game. See also `PlayerKeys.md` to add administrators with `--addlobbyadminhash` and `--addlobbyadminpublickey` and `DedicatedHost.md` for more details about running a dedicated server. The autohost option requires a configuration file set in your data directory, under the `autohost` directory. For example : `warzone2100 --autohost=my_host` will look for the configuration file `autohost/my_host`. diff --git a/doc/hosting/DedicatedHost.md b/doc/hosting/DedicatedHost.md new file mode 100644 index 00000000000..ee268f0cc9e --- /dev/null +++ b/doc/hosting/DedicatedHost.md @@ -0,0 +1,104 @@ +Running a dedicated host +======================== + +Warzone 2100 can run in background with a few command line arguments and some game configuration files. + +Setting the server and running the game manually +------------------------------------------------ + +### Running the game from the command line + +#### Basic command + +``` +warzone2100 --autohost= --gameport= --startplayers= --headless --nosound +``` + +This command will run a game without front-end for a specific game configuration. + +* `--autohost` indicates which game configuration to use. See `AutohostConfig.md` to create a file. Always use `spectatorHost: true`, the host cannot play. +* `--gameport` gives the port number to use. By default it will try to run on port 2100. Each concurrent games must have distinct ports. +* `--startplayers` holds the number of players required to start the game. +* `--headless` disables the GUI, `--nosound` disables the sound. + +A default game will start if the autohost file cannot be read or contains errors. If the requested port is not available, the command will fail and stop. + +#### Extended command + +You can provide more arguments to fine-tune your environment. + +* `--configdir=` will read the configuration file, maps, mods and store logs in the given directory. You can create a default one by providing this option on your regular game, changing your name to create the host keys and copy the newly created directory to your server. +* `--enablelobbyslashcmd` allows administrators to use slash commands to modify the settings (see below to add administrators). +* `--addlobbyadminhash=` grants admin right to the given player, identified by their hash. This argument must be repeated to add multiple administrators. See `PlayerKeys.md` for details about hashes. +* `--addlobbyadminpublickey=` grants admin rights to the given player, by their public key. This argument must be repeated to add multiple administrators. See `PlayerKeys.md` for details about keys. +* `--autorating=` overrides the autorating url. See `AutoratingServer.md` for details about the autorating server. + + +### Checking your firewall + +If your server starts but nobody can join, check that your firewall is accepting incoming TCP connections on the given port. + +#### With nftables + +Check your current rules with `nft list ruleset`. If it is not empty check that the input chain accepts the ports you use for Warzone 2100, especially if your input chain drops unknown ports. For example: + +``` +table inet filter { + chain input { + [System stuff] + tcp dport { 2100-2105 } ct state new accept # Warzone 2100 + counter drop + } + [Other chains] +} +``` + +### Managing a banlist + +You can provide a file with banned IP which contains one ban per line. It can include wildcards. + +Put this `banlist.txt` file at the root of your config directory and it will be automatically loaded at game start. + + +Scripting the server +-------------------- + +### Linux: Bash + Systemd + +#### Configuring the bash scripts + +The scripts under `linux_scripts` will start a game automatically by picking the next available port and select a random map from a pool. Those scripts can be installed anywhere but must be kept in the same directory. + +Prerequisites: + +* `bash` to run the script. +* `sed` to pick a map randomly. +* `ss` or `netstat` to check for an available port. +* `systemd` to run the scripts automatically. + +Copy `common_sample.sh` to `common.sh` and update the few variables according to your environment. + +Then copy and edit `game_sample.sh` for each game type you would like to run. + +And try to run the server by manually calling the script, if you copied `game_sample.sh` to `game.sh`: + +``` +bash game.sh +``` + +#### Automatically run the scripts with systemd + +Copy and rename a `wz2100host_sample.service` to `/etc/systemd/system/`, one for each simultaneously opened game and edit those few lines: + +* `WorkingDirectory=` set it to the directory where the bash scripts are. +* `ExecStart=bash ` set to the game script. +* `User=` pick the system user that will run the game. + +Then for each service created, enable and start the service. Enabling the service will automatically run it at boot and starting the service runs it manually without requiring to reboot. + +``` +systemctl enable +systemctl start +``` + +You can then check the status for each game with `systemctl status `. diff --git a/doc/hosting/linux_scripts/common.sh b/doc/hosting/linux_scripts/common.sh new file mode 100644 index 00000000000..f7587eefdca --- /dev/null +++ b/doc/hosting/linux_scripts/common.sh @@ -0,0 +1,80 @@ +#!/bin/bash -e + +function check { + if [ ! $(command -v netstat) ] && [ ! $(command -v ss) ]; then + echo "[ERROR] netstat or ss is required to check for available ports" + exit 1 + fi + if [ ! $(command -v $wz2100cmd) ]; then + echo "[ERROR] Cannot execute \"$wz2100cmd\"." + exit 1 + fi + if [ "$players" == "" ] || [ ! $players -gt 0 ]; then + echo "[ERROR] The number of players is not set." + exit 1 + fi + if [ "$hostfile" == "" ]; then + echo "[ERROR] No hostfile given." + exit 1 + fi + if [ "$portmin" == "" ] || [ ! $portmin -gt 0 ]; then + portmin=2100 + fi + if [ "$portmax" == "" ] || [ $portmax -lt $portmin ]; then + portmax=$portmin + fi +} + +function run_host { + check + hostpath="$cfgdir/autohost" + # Find next available port + port=$((portmin - 1)) + while true; do + port=$((port + 1)) + if [ $(command -v netstat) ]; then + ports="$(netstat -nt | grep [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*:${port})" + else + ports="$(ss -ntO | grep [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*:${port})" + fi + if [ "$ports" == "" ] || [ "$port" -gt "$portmax" ]; then + break + fi + done + + if [ "$port" -gt "$portmax" ]; then + echo "No more port available" + return 1 + fi + # Set random map + if [ ${#maps[@]} -gt 0 ]; then + if [ "$cfgdir" == "" ]; then + echo "[ERROR] cfgdir must be set to edit autohost file" + return 1 + fi + if [ ! -f "$hostpath/$hostfile" ]; then + echo "[ERROR] Host file \"$hostpath/$hostfile\" not found." + return 1 + fi + rnd=$(($RANDOM % ${#maps[@]})) + map=${maps[$rnd]} + sed -i "s/\"map\": \"\(.*\)\",$/\"map\": \"$map\",/g" $hostpath/$hostfile + fi + # Set admin list + admcmd="" + for adm in ${adminkeys[@]} + do + admcmd+=" --addlobbyadminpublickey=${adm}" + done + for adm in ${adminhashes[@]} + do + admcmd+=" --addlobbyadminhash=${adm}" + done + if [ "$cfgdir" == "" ]; then + configdir="" + else + configdir="--configdir=$cfgdir" + fi + # Run game + $wz2100cmd $configdir --autohost=$hostfile --gameport=$port --startplayers=$players --enablelobbyslashcmd $admcmd --headless --nosound +} diff --git a/doc/hosting/linux_scripts/config_sample.sh b/doc/hosting/linux_scripts/config_sample.sh new file mode 100644 index 00000000000..279b974600c --- /dev/null +++ b/doc/hosting/linux_scripts/config_sample.sh @@ -0,0 +1,46 @@ +#!/bin/bash -e + +## Common configuration values +## This file is shared between all games + +## Administrators +################# +## adminhashes: the list of admin players' hash +## adminkeys: the list of admin players' public key +## The host is always administrator +## Put keys and/or hashes according to your likings and between quotes. +adminkeys=( +# 'admin1 key' +# 'admin2 key' +) +adminhashes=( +# 'admin3 hash' +# 'admin4 hash' +) + +## Ports +######## +## portmin: the lowest port to use if available +## portmax: the highest port to use +## Set a range of ports slightly larger than the maximum number of simultaneous +## games in case a game crashes and cannot release the port properly before the +## next game is created. +portmin=2100 +portmax=2105 + +## Game command +############### +## Uncomment or modifiy the command to run Warzone 2100. +## The script will add all the required parameters to run the game. + +## Installed from snap +#wz2100cmd="snap run warzone2100" + +## Installed from flatpack +#wz2100cmd="flatpak run net.wz2100.wz2100" + +## Installed in PATH +#wz2100cmd="warzone2100" + +## Built from source +#wz2100cmd="////bin/warzone2100" diff --git a/doc/hosting/linux_scripts/game_sample.sh b/doc/hosting/linux_scripts/game_sample.sh new file mode 100644 index 00000000000..87e88549ffa --- /dev/null +++ b/doc/hosting/linux_scripts/game_sample.sh @@ -0,0 +1,45 @@ +#!/bin/bash -e + +## Game configuration values +## One file for each game type + +## Warzone2100 configuration directory +## Leave commented to use the default one +## Required to randomize maps +## Snap default +#cfgdir="$HOME/snap/warzone2100/common/warzone2100" +## Flatpak default +#cfgdir="$HOME/.var/app/net.wz2100.wz2100/data/warzone2100/" +## Home default +#cfgdir="$HOME/.local/share/warzone2100" + +## Map pool +## Leave commented to skip randomized maps or provide a list of map names. +## The autohost file will be updated each time with one of these values +#maps=("map1" "map2" "map3") + +## Host file +## The name of the file in your 'autohost' directory inside cfgdir. +hostfile="my_game.json" + +## Players +## The number of players required to start the game. +players=2 + + +## Run script +## Do not edit below +DIR="${BASH_SOURCE%/*}" +if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi +if [ ! -f "$DIR/common.sh" ]; then + echo "[ERROR] common.sh not found." + exit 1 +fi +if [ ! -f "$DIR/config.sh" ]; then + echo "[ERROR] config.sh not found." + echo "Copy 'config_sample.sh' to 'config.sh' and check if the file is readable." + exit 1 +fi +. "$DIR/common.sh" +. "$DIR/config.sh" +run_host diff --git a/doc/hosting/linux_scripts/wz2100host_sample.service b/doc/hosting/linux_scripts/wz2100host_sample.service new file mode 100644 index 00000000000..eb398a4ac38 --- /dev/null +++ b/doc/hosting/linux_scripts/wz2100host_sample.service @@ -0,0 +1,17 @@ +[Unit] +Description=Host a Warzone2100 game +Wants=network.target + +[Service] +# Edit those three lines +WorkingDirectory=//// +ExecStart=bash game.sh +User=warzone2100 + +Type=simple +PrivateTmp=true +Restart=on-success +RestartSec=3 + +[Install] +WantedBy=multi-user.target