diff --git a/Dockerfile b/Dockerfile index 5a461bd..3ccc9ef 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:16.04 +FROM debian:stretch EXPOSE 27015/udp 27015/tcp @@ -32,6 +32,7 @@ ENTRYPOINT ["./home/entrypoint.sh"] COPY ["entrypoint.sh", "experimental.sh", "forceWorkshopDownload.sh", "installAndMountAddons.sh", "/home/"] # removed dep. lib32gcc1 libtcmalloc-minimal4:i386 gdb +#sudo dpkg --add-architecture i386; RUN dpkg --add-architecture i386 && \ apt-get update -y && \ apt-get install -y mailutils postfix curl wget file bzip2 gzip unzip bsdmainutils python util-linux ca-certificates \ @@ -49,7 +50,8 @@ RUN dpkg --add-architecture i386 && \ chmod a=rx /home/installAndMountAddons.sh && \ \ ulimit -n 2048 && \ - locale-gen en_US.UTF-8 && \ + sed -i 's/# en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen && \ + locale-gen && \ \ wget -O "$STEAM_PATH/linuxgsm.sh" "https://linuxgsm.sh" && \ chown "$DOCKER_USER:$DOCKER_USER" "$STEAM_PATH/linuxgsm.sh" && \ diff --git a/README.md b/README.md index 05b163b..8d5b0d9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# docker-ttt +# GMOD TTT GMOD TTT server image, https://hub.docker.com/r/jusito/ ## TODO @@ -38,3 +38,8 @@ https://wiki.garrysmod.de/server.cfg Path in container is: docker cp "your server.cfg path" CONTAINER:/home/steam/serverfiles/garrysmod/cfg/server.cfg + +## Additional + +### Debian Buster +Currently one dependency is missing: https://packages.debian.org/search?keywords=lib32tinfo5 diff --git a/TTT/Dockerfile b/TTT/Dockerfile new file mode 100644 index 0000000..ba294aa --- /dev/null +++ b/TTT/Dockerfile @@ -0,0 +1,9 @@ +FROM jusito/docker-ttt:gmod_debian + +ENV SERVER_GAMEMODE="+gamemode terrortown" + +COPY "server.cfg.default" "/home/server.cfg.default" + +USER "$USER_ID:$GROUP_ID" + +VOLUME "$SERVER_PATH" \ No newline at end of file diff --git a/TTT/server.cfg.default b/TTT/server.cfg.default new file mode 100644 index 0000000..d868572 --- /dev/null +++ b/TTT/server.cfg.default @@ -0,0 +1,101 @@ +hostname "" +sv_password "" +sv_voiceenable 0 + +sv_contact "unknown" + + +// rcon passsword +sv_rcon_banpenalty 5 +sv_rcon_maxfailures 3 + +//DNA +ttt_killer_dna_range 300 +ttt_killer_dna_basetime 100 + + +//Prep +ttt_firstpreptime 60 +ttt_preptime_seconds 30 +ttt_posttime_seconds 3 + + +//Round length +ttt_haste 0 +// ttt_haste_starting_minutes 5 +// ttt_haste_minutes_per_death 0.5 + +ttt_roundtime_minutes 10 + + + +//Map Switching +ttt_round_limit 10 +ttt_time_limit_minutes 75 + +//ttt_always_use_mapcycle 0 + + +//Player Counts +ttt_minimum_players 2 +ttt_traitor_pct 0.4 +ttt_traitor_max 32 +ttt_detective_pct 0.1 +ttt_detective_max 32 +ttt_detective_min_players 6 +ttt_detective_karma_min 600 + + +//Karma +ttt_karma 1 +ttt_karma_strict 1 +ttt_karma_starting 1000 +ttt_karma_max 1000 +ttt_karma_ratio 0.001 +ttt_karma_kill_penalty 50 +ttt_karma_round_increment 5 +ttt_karma_clean_bonus 30 +ttt_karma_traitordmg_ratio 0.0003 +ttt_karma_traitorkill_bonus 100 +ttt_karma_low_autokick 1 +ttt_karma_low_amount 300 +ttt_karma_low_ban 0 +ttt_karma_low_ban_minutes 60 +ttt_karma_persist 1 +ttt_karma_clean_half 0.25 + +//Other +ttt_postround_dm 0 +ttt_no_nade_throw_during_prep 0 +ttt_weapon_carrying 1 +ttt_weapon_carrying_range 50 +ttt_teleport_telefrags 1 +ttt_ragdoll_pinning 1 +ttt_ragdoll_pinning_innocents 1 +ttt_use_weapon_spawn_scripts 1 +ttt_spawn_wave_interval 2 +ttt_allow_discomb_jump 1 +ttt_debug_preventwin 0 + +// server logging +log on +sv_logbans 1 +sv_logecho 1 +sv_logfile 0 +sv_log_onefile 0 + +// operation +sv_lan 0 +sv_region 3 //Europa + +// traitor +ttt_credits_detectivekill 2 +ttt_credits_award_repeat 0.5 + +// fastdl +sv_allowdownload 1 +sv_allowupload 0 +// sv_downloadurl "your url" + +exec banned_user.cfg +exec banned_ip.cfg \ No newline at end of file diff --git a/cronTest/Dockerfile b/cronTest/Dockerfile new file mode 100644 index 0000000..a7894be --- /dev/null +++ b/cronTest/Dockerfile @@ -0,0 +1,56 @@ +FROM debian:stretch + +# Const \\ Overwrite Env \\ Configs possible \\ Configs needed +ENV STEAM_PATH="/home/steam" \ + SERVER_PATH="/home/steam/serverfiles" \ + STEAM_CMD="/home/steam/steamcmd" \ + GROUP_ID=10000 \ + USER_ID=10000 \ + DOCKER_USER=steam \ + SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.1.9/supercronic-linux-amd64 \ + SUPERCRONIC=supercronic-linux-amd64 \ + SUPERCRONIC_SHA1SUM=5ddf8ea26b56d4a7ff6faecdd8966610d5cb9d85 \ + \ + \ + DEBIAN_FRONTEND=noninteractive \ + \ + \ + DEBUGGING=false \ + CRON_MONITOR="*/5 * * * *" \ + CRON_UPDATE="*/30 * * * *" \ + CRON_FORCE_UPDATE="0 10 * * 0" \ + \ + \ + SERVER_EXECUTABLE="" \ + SERVER_GAME="" \ + TZ="US/Eastern" +#https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + +ENTRYPOINT ["./home/entrypoint.sh"] + +COPY ["entrypoint.sh", "initCron.sh", "/home/"] + +RUN dpkg --add-architecture i386 && \ + apt-get update -y && \ + apt-get install -y locales sudo curl && \ + \ + groupadd -g $GROUP_ID $DOCKER_USER && \ + useradd -d "$STEAM_PATH" -g $GROUP_ID -u $USER_ID -m $DOCKER_USER && \ + chown "$DOCKER_USER:$DOCKER_USER" /home/entrypoint.sh && \ + chown "$DOCKER_USER:$DOCKER_USER" /home/initCron.sh && \ + sudo -u "$DOCKER_USER" mkdir -p "$SERVER_PATH" && \ + chown -R "$DOCKER_USER:$DOCKER_USER" "$STEAM_PATH" && \ + chmod a=rx /home/entrypoint.sh && \ + chmod a=rx /home/initCron.sh && \ + \ + ulimit -n 2048 && \ + sed -i 's/# en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen && \ + locale-gen && \ + \ + \ + curl -fsSLO "$SUPERCRONIC_URL" && \ + echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - && \ + chmod a+rx "$SUPERCRONIC" && \ + mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" && \ + ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic + diff --git a/cronTest/entrypoint.sh b/cronTest/entrypoint.sh new file mode 100644 index 0000000..2824d96 --- /dev/null +++ b/cronTest/entrypoint.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +if [ "${DEBUGGING}" = "true" ]; then + set -o xtrace +fi + +set -o errexit +set -o pipefail + +echo "starting entrypoint.sh" +set -e + + +#start cron +bash "/home/initCron.sh" + +exec /bin/bash \ No newline at end of file diff --git a/cronTest/initCron.sh b/cronTest/initCron.sh new file mode 100644 index 0000000..9dc601d --- /dev/null +++ b/cronTest/initCron.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +if [ "${DEBUGGING}" = "true" ]; then + set -o xtrace +fi + +set -o errexit +set -o pipefail +set -o nounset + +#set up cronjob +rm -f "$STEAM_PATH/lgsm-cronjobs" || true +touch "$STEAM_PATH/lgsm-cronjobs" +# false positive +echo "*/1 * * * * date >> date.log" >> "$STEAM_PATH/lgsm-cronjobs" # out on release +echo "" >> "$STEAM_PATH/lgsm-cronjobs" diff --git a/entrypoint.sh b/entrypoint.sh index bed1618..54d04d0 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -25,7 +25,9 @@ echo "install & mount gamefiles" cd "$STEAM_PATH" #docker args -> lgsm args -export parms="-game garrysmod +gamemode terrortown "$(printf "%s " "$@") +temp="" +temp=$(printf "%s " "$@") || true +export parms="-game garrysmod +gamemode terrortown $temp" if [ -e "${STEAM_PATH}/lgsm/config-lgsm/gmodserver/gmodserver.cfg" ]; then rm -f "${STEAM_PATH}/lgsm/config-lgsm/gmodserver/gmodserver.cfg" fi @@ -49,8 +51,8 @@ IS_RUNNING="true" function stopServer() { echo "stopping server..." cd "${STEAM_PATH}" - pkill -2 srcds_linux - pkill -2 srcds_run + kill -2 "$(pidof srcds_linux)" || true + kill -2 "$(pidof srcds_run)" || true echo "server stopped!" echo "stopping entrypoint..." IS_RUNNING="false" diff --git a/experimental.sh b/experimental.sh index 96ad791..e4f0fd4 100644 --- a/experimental.sh +++ b/experimental.sh @@ -5,6 +5,8 @@ set -e function configReplace() { source="$1" target="$source \"$2\"" + #grep -c would be nicer + # shellcheck disable=SC2126 count=$(grep -Po "($source).+" "${SERVER_PATH}/garrysmod/cfg/server.cfg" | wc -l) echo "Request for replacing $source to $target, source is found $count times" @@ -23,6 +25,8 @@ function configReplace() { #create default server.config # not empty: grep -q '[^[:space:]]' < 'server.cfg' && echo "not empty" +#grep -c would be nicer +# shellcheck disable=SC2126 if [ ! -e "${SERVER_PATH}/garrysmod/cfg/server.cfg" ] || [ "0" = "$(grep -o '[^[:space:]]' "${SERVER_PATH}/garrysmod/cfg/server.cfg" | wc -l)" ]; then mkdir -p "${SERVER_PATH}/garrysmod/cfg" wget -O "${SERVER_PATH}/garrysmod/cfg/server.cfg" "https://raw.githubusercontent.com/jusito/docker-ttt/master/server.cfg" @@ -41,15 +45,7 @@ if [ -n "${SERVER_VOICE_ENABLE}" ]; then configReplace "sv_voiceenable" "$SERVER_VOICE_ENABLE" fi -#set up cronjob -crontab -r | true -rm -f "$STEAM_PATH/lgsm-cronjobs" | true -touch "$STEAM_PATH/lgsm-cronjobs" -echo "*/5 * * * * su - '$DOCKER_USER' -c '$STEAM_PATH/gmodserver monitor' > /dev/null 2>&1" >> "$STEAM_PATH/lgsm-cronjobs" -echo "*/30 * * * * su - '$DOCKER_USER' -c '$STEAM_PATH/gmodserver update' > /dev/null 2>&1" >> "$STEAM_PATH/lgsm-cronjobs" -echo "0 10 * * 0 su - '$DOCKER_USER' -c '$STEAM_PATH/gmodserver force-update' > /dev/null 2>&1" >> "$STEAM_PATH/lgsm-cronjobs" -echo "" >> "$STEAM_PATH/lgsm-cronjobs" -crontab "$STEAM_PATH/lgsm-cronjobs" + #this is a simple option for myself, but you can use it too if [ "$USE_MY_REPLACER_CONFIG" = "true" ] && [ ! -e "${SERVER_PATH}/garrysmod/data/jusito_ttt_entity_replace" ]; then diff --git a/forceWorkshopDownload.sh b/forceWorkshopDownload.sh index 6e2c130..b64668a 100644 --- a/forceWorkshopDownload.sh +++ b/forceWorkshopDownload.sh @@ -17,9 +17,9 @@ if [ "$WORKSHOP_COLLECTION_ID" = "0" ] || [ "$WORKSHOP_COLLECTION_ID" = "" ]; th echo "given ID is default, no workshop download" else touch "$LUA_FILE" - arr="$(wget -q -O - https://steamcommunity.com/sharedfiles/filedetails/?id=${WORKSHOP_COLLECTION_ID} | tr '\n' ' ' | grep -Po '"workshopItem"[^"]+"https://steamcommunity.com/sharedfiles/filedetails/\?id=(\d+)' | grep -Po '\d\d\d+' )" + arr=$(wget -q -O - https://steamcommunity.com/sharedfiles/filedetails/?id="${WORKSHOP_COLLECTION_ID}" | tr '\n' ' ' | grep -Po '"workshopItem"[^"]+"https://steamcommunity.com/sharedfiles/filedetails/\?id=(\d+)' | grep -Po '\d\d\d+' ) str="" - for i in ${arr[@]} + for i in "${arr[@]}" do str=${str}"resource.AddWorkshop( \"${i}\" )"$'\n' done diff --git a/gmod/Dockerfile b/gmod/Dockerfile new file mode 100644 index 0000000..0dc514a --- /dev/null +++ b/gmod/Dockerfile @@ -0,0 +1,40 @@ +FROM jusito/docker-ttt:lgsm_debian + +EXPOSE 27015/udp 27015/tcp + +# Const \\ Overwrite Env \\ Configs optional \\ Configs needed +ENV CSS_PATH="/home/steam/addons/css" \ + HL2_PATH="/home/steam/addons/hl2" \ + HLDM_PATH="/home/steam/addons/hldm" \ + TF2_PATH="/home/steam/addons/tf2" \ + \ + \ + SERVER_EXECUTABLE="gmodserver" \ + SERVER_GAME="gmodserver" \ + \ + \ + WORKSHOP_COLLECTION_ID= \ + SERVER_NAME="" \ + SERVER_PASSWORD="" \ + SERVER_VOICE_ENABLE="1" \ + \ + INSTALL_CSS=false \ + INSTALL_HL2=false \ + INSTALL_HLDM=false \ + INSTALL_TF2=false \ + \ + USE_MY_REPLACER_CONFIG=false \ + \ + \ + SERVER_GAMEMODE="" + +COPY ["prepareServer.sh", "initConfig.sh", "forceWorkshopDownload.sh", "installAndMountAddons.sh", "/home/"] + +RUN chown "$DOCKER_USER:$DOCKER_USER" /home/prepareServer.sh && \ + chown "$DOCKER_USER:$DOCKER_USER" /home/initConfig.sh && \ + chown "$DOCKER_USER:$DOCKER_USER" /home/forceWorkshopDownload.sh && \ + chown "$DOCKER_USER:$DOCKER_USER" /home/installAndMountAddons.sh && \ + chmod a=rx /home/prepareServer.sh && \ + chmod a=rx /home/initConfig.sh && \ + chmod a=rx /home/forceWorkshopDownload.sh && \ + chmod a=rx /home/installAndMountAddons.sh diff --git a/gmod/forceWorkshopDownload.sh b/gmod/forceWorkshopDownload.sh new file mode 100644 index 0000000..0648b76 --- /dev/null +++ b/gmod/forceWorkshopDownload.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +if [ "${DEBUGGING}" = "true" ]; then + set -o xtrace +fi + +set -o errexit +set -o nounset +set -o pipefail + +#using WORKSHOP_COLLECTION_ID +LUA_PATH="${SERVER_PATH}/garrysmod/lua/autorun/server" +LUA_FILE="${LUA_PATH}/workshop_autoload.lua" + +#remove old file +if [ -e "$LUA_FILE" ]; then + rm "$LUA_FILE" +else + mkdir -p "$LUA_PATH" +fi + +if [ "$WORKSHOP_COLLECTION_ID" = "0" ] || [ "$WORKSHOP_COLLECTION_ID" = "" ]; then + echo "given ID is default, no workshop download" +else + touch "$LUA_FILE" + arr=$(wget -q -O - https://steamcommunity.com/sharedfiles/filedetails/?id="${WORKSHOP_COLLECTION_ID}" | tr '\n' ' ' | grep -Po '"workshopItem"[^"]+"https://steamcommunity.com/sharedfiles/filedetails/\?id=(\d+)' | grep -Po '\d\d\d+' ) + str="" + for i in "${arr[@]}" + do + str=${str}"resource.AddWorkshop( \"${i}\" )"$'\n' + done + echo "$str" > "$LUA_FILE" +fi + diff --git a/gmod/initConfig.sh b/gmod/initConfig.sh new file mode 100644 index 0000000..0b9a103 --- /dev/null +++ b/gmod/initConfig.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +if [ "${DEBUGGING}" = "true" ]; then + set -o xtrace +fi + +set -o errexit +set -o nounset +set -o pipefail + +function configReplace() { + source="$1" + target="$source \"$2\"" + + count=$(grep -Poc "($source).+" "${SERVER_PATH}/garrysmod/cfg/server.cfg") + + echo "Request for replacing $source to $target, source is found $count times" + + if [ "$count" == "1" ]; then + source=$(grep -Po "($source).+" "${SERVER_PATH}/garrysmod/cfg/server.cfg" | sed 's/\\/\\\\/g' | sed 's/\//\\\//g') + target=$(echo "$target" | sed 's/\\/\\\\/g' | sed 's/\//\\\//g') + sed -i "s/$source/$target/g" "${SERVER_PATH}/garrysmod/cfg/server.cfg" + + elif [ "$count" == "0" ]; then + echo "" >> "${SERVER_PATH}/garrysmod/cfg/server.cfg" + echo "$target" >> "${SERVER_PATH}/garrysmod/cfg/server.cfg" + + else + echo "can't set $1 because there are multiple in" + fi +} + +#create default server.config +# not empty: grep -q '[^[:space:]]' < 'server.cfg' && echo "not empty" +if [ ! -e "${SERVER_PATH}/garrysmod/cfg/server.cfg" ] || [ "0" = "$(grep -oc '[^[:space:]]' "${SERVER_PATH}/garrysmod/cfg/server.cfg")" ]; then + mkdir -p "${SERVER_PATH}/garrysmod/cfg" || true + cp -f "/home/server.cfg.default" "${SERVER_PATH}/garrysmod/cfg/server.cfg" + chown "$USER_ID:$GROUP_ID" "${SERVER_PATH}/garrysmod/cfg/server.cfg" + chmod u+rw "${SERVER_PATH}/garrysmod/cfg/server.cfg" +fi + +#set hostname & password, working if only one entry is in +if [ -n "${SERVER_NAME}" ]; then + configReplace "hostname" "$SERVER_NAME" +fi +if [ -n "${SERVER_PASSWORD}" ]; then + configReplace "sv_password" "$SERVER_PASSWORD" +fi +if [ -n "${SERVER_VOICE_ENABLE}" ]; then + configReplace "sv_voiceenable" "$SERVER_VOICE_ENABLE" +fi + + + +#this is a simple option for myself, but you can use it too +if [ "$USE_MY_REPLACER_CONFIG" = "true" ] && [ ! -e "${SERVER_PATH}/garrysmod/data/jusito_ttt_entity_replace" ]; then + mkdir -p "${SERVER_PATH}/garrysmod/data/jusito_ttt_entity_replace" + wget -O "${SERVER_PATH}/garrysmod/data/jusito_ttt_entity_replace/config.txt" "https://raw.githubusercontent.com/jusito/ttt_entity_replace/master/config.txt.example_fas2" +fi + diff --git a/gmod/installAndMountAddons.sh b/gmod/installAndMountAddons.sh new file mode 100644 index 0000000..d62e460 --- /dev/null +++ b/gmod/installAndMountAddons.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +if [ "${DEBUGGING}" = "true" ]; then + set -o xtrace +fi + +set -o errexit +set -o nounset +set -o pipefail +cd "$STEAM_CMD" +mount='"mountcfg"'$'\n{\n' +if [ "$INSTALL_CSS" = "true" ]; then + echo "installing & mounting css" + ./steamcmd.sh +login anonymous +force_install_dir "$CSS_PATH" +app_update 232330 validate +quit + mount=${mount}' "cstrike" "'"${CSS_PATH}/cstrike"$'"\n' + if [ "$INSTALL_HL2" != "true" ]; then + mount=${mount}' "hl2" "'"${CSS_PATH}/hl2"$'"\n' + fi +fi +if [ "$INSTALL_HL2" = "true" ]; then + echo "installing & mounting hl2" + ./steamcmd.sh +login anonymous +force_install_dir "$HL2_PATH" +app_update 232370 validate +quit + mount=${mount}' "hl2" "'"${HL2_PATH}/hl2"$'"\n' + mount=${mount}' "hl2mp" "'"${HL2_PATH}/hl2mp"$'"\n' +fi +if [ "$INSTALL_TF2" = "true" ]; then + echo "installing & mounting tf2" + ./steamcmd.sh +login anonymous +force_install_dir "$TF2_PATH" +app_update 232250 validate +quit + mount=${mount}' "tf2" "'"${TF2_PATH}/tf"$'"\n' + if [ "$INSTALL_CSS" != "true" ] && [ "$INSTALL_HL2" != "true" ]; then + mount=${mount}' "hl2" "'"${TF2_PATH}/hl2"$'"\n' + fi +fi +if [ "$INSTALL_HLDM" = "true" ]; then + echo "installing & mounting hldm" + ./steamcmd.sh +login anonymous +force_install_dir "$HLDM_PATH" +app_update 255470 validate +quit + mount=${mount}' "hl1" "'"${HLDM_PATH}/hl1"$'"\n' + mount=${mount}' "hldm" "'"${HLDM_PATH}/hldm"$'"\n' + if [ "$INSTALL_CSS" != "true" ] && [ "$INSTALL_HL2" != "true" ] && [ "$INSTALL_TF2" != "true" ]; then + mount=${mount}' "hl2" "'"${HLDM_PATH}/hl2"$'"\n' + fi +fi +mount=${mount}$'}\n' + + +if [ ! -e "${SERVER_PATH}/garrysmod/cfg" ]; then + mkdir -p "${SERVER_PATH}/garrysmod/cfg" +fi +if [ -e "${SERVER_PATH}/garrysmod/cfg/mount.cfg" ]; then + rm "${SERVER_PATH}/garrysmod/cfg/mount.cfg" +fi +touch "${SERVER_PATH}/garrysmod/cfg/mount.cfg" +echo "$mount" > "${SERVER_PATH}/garrysmod/cfg/mount.cfg" + diff --git a/gmod/prepareServer.sh b/gmod/prepareServer.sh new file mode 100644 index 0000000..bdd5218 --- /dev/null +++ b/gmod/prepareServer.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +if [ "${DEBUGGING}" = "true" ]; then + set -o xtrace +fi + +set -o errexit +set -o nounset +#./prepareServer.sh: 9: set: Illegal option -o pipefail +#set -o pipefail + +cd "/home" +echo "check configurations" +./initConfig.sh +echo "force workshop download" +./forceWorkshopDownload.sh +echo "install & mount gamefiles" +./installAndMountAddons.sh +cd "$STEAM_PATH" + +#docker args -> lgsm args +temp="" +temp=$(printf "%s " "$@") || true +export parms="-game garrysmod $SERVER_GAMEMODE $temp" +if [ -e "${STEAM_PATH}/lgsm/config-lgsm/gmodserver/gmodserver.cfg" ]; then + rm -f "${STEAM_PATH}/lgsm/config-lgsm/gmodserver/gmodserver.cfg" +fi +mkdir -p "${STEAM_PATH}/lgsm/config-lgsm/gmodserver/" +touch "${STEAM_PATH}/lgsm/config-lgsm/gmodserver/gmodserver.cfg" +echo "fn_parms(){" > "${STEAM_PATH}/lgsm/config-lgsm/gmodserver/gmodserver.cfg" +echo "parms="'"'"$parms"'"' >> "${STEAM_PATH}/lgsm/config-lgsm/gmodserver/gmodserver.cfg" +echo "}" >> "${STEAM_PATH}/lgsm/config-lgsm/gmodserver/gmodserver.cfg" +echo "starting with $parms" \ No newline at end of file diff --git a/lgsm/Dockerfile b/lgsm/Dockerfile new file mode 100644 index 0000000..b433dcb --- /dev/null +++ b/lgsm/Dockerfile @@ -0,0 +1,64 @@ +FROM debian:stretch + +# Const \\ Overwrite Env \\ Configs possible \\ Configs needed +ENV STEAM_PATH="/home/steam" \ + SERVER_PATH="/home/steam/serverfiles" \ + STEAM_CMD="/home/steam/steamcmd" \ + GROUP_ID=10000 \ + USER_ID=10000 \ + DOCKER_USER=steam \ + SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.1.9/supercronic-linux-amd64 \ + SUPERCRONIC=supercronic-linux-amd64 \ + SUPERCRONIC_SHA1SUM=5ddf8ea26b56d4a7ff6faecdd8966610d5cb9d85 \ + \ + \ + DEBIAN_FRONTEND=noninteractive \ + \ + \ + DEBUGGING=false \ + CRON_MONITOR="*/5 * * * *" \ + CRON_UPDATE="*/30 * * * *" \ + CRON_FORCE_UPDATE="0 10 * * 0" \ + CRON_LOG_ROTATE="0 0 * * 0" \ + \ + \ + SERVER_EXECUTABLE="" \ + SERVER_GAME="" \ + TZ="Europe/Berlin" +#https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + +ENTRYPOINT ["./home/entrypoint.sh"] + +COPY ["entrypoint.sh", "initCron.sh", "/home/"] + +# procps needed for ps command +RUN dpkg --add-architecture i386 && \ + apt-get update -y && \ + apt-get install -y mailutils postfix curl wget file bzip2 gzip unzip bsdmainutils python util-linux ca-certificates \ + binutils bc jq tmux lib32gcc1 libstdc++6 libstdc++6:i386 lib32tinfo5 \ + locales procps && \ + \ + groupadd -g $GROUP_ID $DOCKER_USER && \ + useradd -d "$STEAM_PATH" -g $GROUP_ID -u $USER_ID -m $DOCKER_USER && \ + chown "$DOCKER_USER:$DOCKER_USER" /home/entrypoint.sh && \ + chown "$DOCKER_USER:$DOCKER_USER" /home/initCron.sh && \ + mkdir -p "$SERVER_PATH" && \ + chown -R "$DOCKER_USER:$DOCKER_USER" "$STEAM_PATH" && \ + chmod a=rx /home/entrypoint.sh && \ + chmod a=rx /home/initCron.sh && \ + \ + ulimit -n 2048 && \ + sed -i 's/# en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen && \ + locale-gen && \ + \ + wget -O "$STEAM_PATH/linuxgsm.sh" "https://linuxgsm.sh" && \ + chown "$DOCKER_USER:$DOCKER_USER" "$STEAM_PATH/linuxgsm.sh" && \ + chmod +x "$STEAM_PATH/linuxgsm.sh" && \ + \ + \ + wget -O "${SUPERCRONIC}" "$SUPERCRONIC_URL" && \ + echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - && \ + chmod +x "$SUPERCRONIC" && \ + mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" && \ + ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic + diff --git a/lgsm/entrypoint.sh b/lgsm/entrypoint.sh new file mode 100644 index 0000000..2f954c6 --- /dev/null +++ b/lgsm/entrypoint.sh @@ -0,0 +1,81 @@ +#!/bin/bash + +if [ "${DEBUGGING}" = "true" ]; then + set -o xtrace +fi + +set -o errexit +set -o pipefail + +echo "starting entrypoint.sh" +set -e + + + + + + +# --- Install / Update --- +cd "$STEAM_PATH" +if [ -n "$SERVER_EXECUTABLE" ] && [ -e "${STEAM_PATH}/$SERVER_EXECUTABLE" ]; then + ./"$SERVER_EXECUTABLE" update-lgsm + ./"$SERVER_EXECUTABLE" update +else + bash linuxgsm.sh "$SERVER_GAME" + ./"$SERVER_EXECUTABLE" auto-install +fi + +if [ -e "/home/prepareServer.sh" ]; then + cd /home + ./prepareServer.sh + cd "$STEAM_PATH" +fi + + + + + + +# --- Apply LGSM Workarounds --- +#force fetch of command_console.sh +if [ ! -e "${STEAM_PATH}/lgsm/functions/command_console.sh" ]; then + wget -O "${STEAM_PATH}/lgsm/functions/command_console.sh" "https://raw.githubusercontent.com/GameServerManagers/LinuxGSM/master/lgsm/functions/command_console.sh" + chmod +x "${STEAM_PATH}/lgsm/functions/command_console.sh" +fi +#skip confirmation +sed -i 's/! fn_prompt_yn "Continue?" Y/[ "1" != "1" ]/' "${STEAM_PATH}/lgsm/functions/command_console.sh" + + + + + +# --- Start Server --- +#start server +IS_RUNNING="true" +function stopServer() { + echo "stopping server..." + cd "${STEAM_PATH}" + pid=$(pidof "$SERVER_EXECUTABLE") + kill -2 "$pid" || true + echo "server stopped!" + echo "stopping entrypoint..." + IS_RUNNING="false" +} +./"$SERVER_EXECUTABLE" start +trap stopServer SIGTERM + +#start cron +bash "/home/initCron.sh" + + + + + +# --- Wait for Shutdown --- +echo "Server is running, waiting for SIGTERM" +while [ "$IS_RUNNING" = "true" ] +do + sleep 1s +done +echo "entrypoint stopped" +exit 0 \ No newline at end of file diff --git a/lgsm/initCron.sh b/lgsm/initCron.sh new file mode 100644 index 0000000..218cd10 --- /dev/null +++ b/lgsm/initCron.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +if [ "${DEBUGGING}" = "true" ]; then + set -o xtrace +fi + +set -o errexit +set -o pipefail +set -o nounset + +LOG_PATH="$STEAM_PATH/logs" +CRON="$LOG_PATH/lgsm.cron" +CRON_LOG="$LOG_PATH/cron.log" + +#set up cronjob +mkdir "$LOG_PATH" || true +rm -f "$CRON" || true +touch "$CRON" +# false positive +# shellcheck disable=SC2129 +echo "$CRON_MONITOR $STEAM_PATH/gmodserver monitor > '$LOG_PATH/monitor.log' 2>&1" >> "$CRON" +# shellcheck disable=SC2129 +echo "$CRON_UPDATE $STEAM_PATH/gmodserver update > '$LOG_PATH/update.log' 2>&1" >> "$CRON" +# shellcheck disable=SC2129 +echo "$CRON_FORCE_UPDATE $STEAM_PATH/gmodserver force-update >'$LOG_PATH/force-update.log' 2>&1" >> "$CRON" +# shellcheck disable=SC2129 +echo "$CRON_LOG_ROTATE mv -f '$CRON_LOG' '${CRON_LOG}.old'" >> "$CRON" +echo "" >> "$CRON" + +if [ -e "$CRON_LOG" ]; then + mv -f "$CRON_LOG" "${CRON_LOG}.old" +fi + +supercronic "$CRON" 2> "$LOG_PATH/cron.log" & \ No newline at end of file diff --git a/test/testBuild.sh b/test/testBuild.sh new file mode 100644 index 0000000..b644427 --- /dev/null +++ b/test/testBuild.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +if [ "${DEBUGGING:?}" = "true" ]; then + set -o xtrace +fi + +set -o errexit +set -o nounset +set -o pipefail + +docker rmi "jusito/docker-ttt:ubuntu" || true +docker build -t "jusito/docker-ttt:ubuntu" "." \ No newline at end of file diff --git a/test/testCaseQuick.sh b/test/testCaseQuick.sh new file mode 100644 index 0000000..4a2d515 --- /dev/null +++ b/test/testCaseQuick.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +if [ "${DEBUGGING}" = "true" ]; then + set -o xtrace +fi + +set -o errexit +set -o nounset +set -o pipefail + +#bash test/testStyle.sh + +echo "[testBuild][INFO]build docker-ttt:ubuntu" +docker rmi "jusito/docker-ttt:ubuntu" || true +docker build -t "jusito/docker-ttt:ubuntu" "." +echo "[testRun][INFO]running docker-ttt:ubuntu" +if ! docker run -ti --name "JusitoTesting" --rm -e TEST_MODE=true -e DEBUGGING="${DEBUGGING}" "jusito/docker-ttt:ubuntu"; then + echo "[testRun][ERROR]run test failed for docker-ttt:ubuntu" + exit 1 +fi +docker stop "JusitoTesting" || true +docker rm "JusitoTesting" || true \ No newline at end of file diff --git a/test/testCaseQuick2.sh b/test/testCaseQuick2.sh new file mode 100644 index 0000000..d60c024 --- /dev/null +++ b/test/testCaseQuick2.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +if [ "${DEBUGGING}" = "true" ]; then + set -o xtrace +else + DEBUGGING="false" +fi + +set -o errexit +set -o nounset +set -o pipefail + +#bash test/testStyle.sh + +echo "[testBuild][INFO]build" + +docker rmi "jusito/docker-ttt:lgsm_debian" || true +docker build -t "jusito/docker-ttt:lgsm_debian" "./lgsm/" + +docker rmi "jusito/docker-ttt:gmod_debian" || true +docker build -t "jusito/docker-ttt:gmod_debian" "./gmod/" + +docker rmi "jusito/docker-ttt:gmod_ttt_debian" || true +docker build -t "jusito/docker-ttt:gmod_ttt_debian" "./TTT/" + + +echo "[testRun][INFO]running" +if ! docker run -ti --name "JusitoTesting" --rm -e TEST_MODE=true -e DEBUGGING="$DEBUGGING" "jusito/docker-ttt:gmod_ttt_debian"; then + echo "[testRun][ERROR]run test failed for docker-ttt:ubuntu" + exit 1 +fi +docker stop "JusitoTesting" || true +docker rm "JusitoTesting" || true \ No newline at end of file diff --git a/test/testHealth.sh b/test/testHealth.sh new file mode 100644 index 0000000..a09c63f --- /dev/null +++ b/test/testHealth.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +if [ "${DEBUGGING:?}" = "true" ]; then + set -o xtrace +fi + +set -o errexit +set -o nounset +set -o pipefail + +docker exec -it CONTAINER ./home/steam/gmodserver details + +Status: OFFLINE -> fail Health \ No newline at end of file diff --git a/test/testRun.sh b/test/testRun.sh new file mode 100644 index 0000000..8959e2a --- /dev/null +++ b/test/testRun.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +if [ "${DEBUGGING:?}" = "true" ]; then + set -o xtrace +fi + +set -o errexit +set -o nounset +set -o pipefail + +docker stop "JusitoTesting" || true +docker rm "JusitoTesting" || true + +echo "[testRun][INFO]running docker-ttt:ubuntu" +if ! docker run -ti --name "JusitoTesting" --rm -e TEST_MODE=true -e DEBUGGING="${DEBUGGING}" "jusito/docker-ttt:ubuntu"; then + echo "[testRun][ERROR]run test failed for docker-ttt:ubuntu" + exit 1 +fi +docker stop "JusitoTesting" || true +docker rm "JusitoTesting" || true \ No newline at end of file diff --git a/test/testStyle.sh b/test/testStyle.sh new file mode 100644 index 0000000..8d26c9f --- /dev/null +++ b/test/testStyle.sh @@ -0,0 +1,54 @@ +#!/bin/sh + +if [ "${DEBUGGING}" = "true" ]; then + set -o xtrace +fi + +set -o errexit +set -o nounset +set -o pipefail + +# test sha3sums + +#if ! printf '%s %s' "$(grep -Eo "grep -Eq '\^[^\\]+" Dockerfile | sed 's/...........//')" "checkHealth.sh" | sha3sum -c ; then +# echo "[testStyle][ERROR]Sha3sum of checkHealth.sh in Dockerfile invalid" +# exit 2 +#fi + +directory="$PWD" +echo "[testStyle][INFO]workdir $directory" + +check() { + file="$1" + exclude="" + if [ -n "$2" ]; then + exclude="--exclude=$2" + fi + + echo "[testStyle][INFO]processing $file with extra arg: $exclude" + # shellcheck disable=SC2086 + if shellcheck $exclude "$file"; then + return 0 + else + echo "[testStyle][ERROR]style is bad" + return 1 + fi +} + + +find "${directory}" -maxdepth 1 -type f -iname '*.sh' | +while read -r filename +do + if ! check "$filename" ''; then + exit 1 + fi +done + +# shellcheck disable=SC2181 +if [ "$?" = "0" ]; then + echo "[testStyle][INFO]all elements passed style check" + exit 0 +else + echo "[testStyle][ERROR]style in at least one element looks bad" + exit 1 +fi \ No newline at end of file