diff --git a/Dockerfile b/Dockerfile index 2f917d2..7a4cb43 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,17 @@ +FROM golang:alpine AS build + +# Set the working directory +WORKDIR /go/src/github.com/adnanh/webhook +ENV WEBHOOK_VERSION=2.8.1 + +RUN apk add --update -t build-deps curl libc-dev gcc libgcc + +RUN curl -L --silent -o webhook.tar.gz https://github.com/adnanh/webhook/archive/${WEBHOOK_VERSION}.tar.gz && \ + tar -xzf webhook.tar.gz --strip 1 + +RUN go get -d -v +RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /usr/local/bin/webhook + FROM --platform=linux/amd64 cm2network/steamcmd:root LABEL maintainer="Sebastian Schmidt - https://github.com/jammsen/docker-palworld-dedicated-server" @@ -37,6 +51,10 @@ RUN curl -fsSLO "$RCON_URL" \ COPY --chown=steam:steam --chmod=755 backupmanager.sh servermanager.sh includes/* / +COPY --from=build /usr/local/bin/webhook /usr/local/bin/webhook +COPY remotehooks.json /remotehooks.json + +EXPOSE 9000/tcp EXPOSE 8211/udp EXPOSE 25575/tcp @@ -65,7 +83,7 @@ ENV DEBIAN_FRONTEND=noninteractive \ STEAMCMD_VALIDATE_FILES=true \ SERVER_SETTINGS_MODE=manual \ WEBHOOK_ENABLED=false \ - WEBHOOK_URL= \ + WEBHOOK_URL="" \ WEBHOOK_START_TITLE="Server is starting" \ WEBHOOK_START_DESCRIPTION="The gameserver is starting" \ WEBHOOK_START_COLOR="2328576" \ @@ -133,10 +151,10 @@ ENV DEBIAN_FRONTEND=noninteractive \ ADMIN_PASSWORD=adminPasswordHere \ SERVER_PASSWORD=serverPasswordHere \ PUBLIC_PORT=8211 \ - PUBLIC_IP= \ + PUBLIC_IP="" \ RCON_ENABLED=false \ RCON_PORT=25575 \ - REGION= \ + REGION="" \ USEAUTH=true \ BAN_LIST_URL=https://api.palworldgame.com/api/banlist.txt diff --git a/README.md b/README.md index 9b252c3..99fdad5 100644 --- a/README.md +++ b/README.md @@ -156,3 +156,4 @@ This is a confirmed bug. Changing `BaseCampWorkerMaxNum` in the `PalWorldSetting - Supercronic - https://github.com/aptible/supercronic - rcon-cli - https://github.com/gorcon/rcon-cli - Palworld Dedicated Server (APP-ID: 2394010 - https://steamdb.info/app/2394010/config/) +- Webhook (https://github.com/adnanh/webhook) diff --git a/README_ENV.md b/README_ENV.md index ab27cdc..ab956df 100644 --- a/README_ENV.md +++ b/README_ENV.md @@ -11,7 +11,7 @@ These settings control the behavior of the Docker container: > **Important:** If you want to change the server settings via environment variables use the default value (`auto`) for the environment variable `SERVER_SETTINGS_MODE`, otherwise change it to `manual` and edit the config file directly. | Variable | Description | Default value | Allowed values | -| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +|---------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | TZ | Timezone used for time stamping server backups | Europe/Berlin | See [TZ identifiers](#tz-identifiers) | | ALWAYS_UPDATE_ON_START | Updates the server on startup | true | false/true | | MULTITHREAD_ENABLED | Sets options for "Improved multi-threaded CPU performance" | true | false/true | @@ -22,6 +22,7 @@ These settings control the behavior of the Docker container: | BACKUP_RETENTION_AMOUNT_TO_KEEP | Defines how many backups in numbers to keep | 30 | Integer | | SERVER_SETTINGS_MODE | Determines whether settings can be modified via environment variables or via file, except `COMMUNITY_SERVER` and `MULTITHREAD_ENABLED`! | `auto` | `auto`: Settings are modified only by environment variables, manual edits will be ignored
`manual`: Settings are modified only by editing the file directly, environment variables are ignored | | STEAMCMD_VALIDATE_FILES | Set to enabled SteamCMD will also validate the gameserver files, making sure nothing is corrupted and also overwrite any file changes of the source
See https://developer.valvesoftware.com/wiki/SteamCMD#Downloading_an_App | true | false/true | +| REMOTE_CONTROL | If enabled server will not automatically start on container start and can be started/stopped via webhook call. Stop of the gameserver does not exit the container to allow external restart. | false | false/true | #### TZ identifiers @@ -31,6 +32,15 @@ The `TZ` setting affects logging output and the backup function. [TZ identifiers The `BACKUP_CRON_EXPRESSION` setting affects the backup function. In a Cron-Expression, you define an interval for when to run jobs. This image uses Supercronic for crons, see https://github.com/aptible/supercronic#crontab-format or https://crontab-generator.org +#### Remote Control +If you enable the container setting the Container will not autostart the gameserver, it will however provide webhooks that allow you to control the server remotely. Hooks provided are + +`{containerip}:9000/hooks/start` - starts the gameserver +`{containerip}:9000/hooks/stop` - stops the gameserver + +In order to utilize the webhooks expose port 9000 to your host/service and call them via `GET` + + ### Gameserver-Settings This section lists all the settings currently adjustable via Docker environment variables, based on the **order** and **contents of the DefaultPalWorldSettings.ini**. diff --git a/default.env b/default.env index 24ef3b1..cd790ef 100644 --- a/default.env +++ b/default.env @@ -1,22 +1,28 @@ # Change this for logging and backup, see "Environment variables" in the README.md -TZ=Europe/Berlin +TZ=Europe/Berlin ALWAYS_UPDATE_ON_START=true MULTITHREAD_ENABLED=true COMMUNITY_SERVER=true BACKUP_ENABLED=true -BACKUP_CRON_EXPRESSION=0 * * * * +BACKUP_CRON_EXPRESSION="0 * * * *" BACKUP_RETENTION_POLICY=false BACKUP_RETENTION_AMOUNT_TO_KEEP=30 STEAMCMD_VALIDATE_FILES=true # Change this to manual if you want to edit your configs yourself -SERVER_SETTINGS_MODE=auto +SERVER_SETTINGS_MODE=auto WEBHOOK_ENABLED=false WEBHOOK_URL="YOUR-URL-IN-HERE" +WEBHOOK_REMOTE_ACTION="Server remote action" WEBHOOK_START_TITLE="Server is starting" WEBHOOK_START_DESCRIPTION="The gameserver is starting" +WEBHOOK_REMOTE_START_DESCRIPTION="Remote start of gameserver initiated" +WEBHOOK_REMOTE_ISRUNNING_DESCRIPTION="Server is already running" +WEBHOOK_REMOTE_READY_DESCRIPTION="Service is ready to recieve start or stop webhook" WEBHOOK_START_COLOR="2328576" WEBHOOK_STOP_TITLE="Server has been stopped" WEBHOOK_STOP_DESCRIPTION="The gameserver has been stopped" +WEBHOOK_REMOTE_STOP_DESCRIPTION="Remote stop of gameserver initiated" +WEBHOOK_REMOTE_NOTRUNNING_DESCRIPTION="Server is not running" WEBHOOK_STOP_COLOR="7413016" WEBHOOK_INFO_TITLE="Info" WEBHOOK_INFO_DESCRIPTION="This is an info from the server" @@ -74,7 +80,7 @@ ENABLE_DEFENSE_OTHER_GUILD_PLAYER=false COOP_PLAYER_MAX_NUM=4 MAX_PLAYERS=32 SERVER_NAME=jammsen-docker-generated-###RANDOM### -SERVER_DESCRIPTION=Palworld-Dedicated-Server running in Docker by jammsen +SERVER_DESCRIPTION="Palworld-Dedicated-Server running in Docker by jammsen" ADMIN_PASSWORD=adminPasswordHere SERVER_PASSWORD=serverPasswordHere PUBLIC_PORT=8211 @@ -84,3 +90,4 @@ RCON_PORT=25575 REGION= USEAUTH=true BAN_LIST_URL=https://api.palworldgame.com/api/banlist.txt +REMOTE_CONTROL=false diff --git a/includes/remotestart.sh b/includes/remotestart.sh new file mode 100644 index 0000000..9e2308f --- /dev/null +++ b/includes/remotestart.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +if [ ${REMOTE_CONTROL:false} != "true" ]; then + echo "Remote control is not active..." + exit 0; +fi + +source /webhook.sh + +if [ ! -z "$(pidof PalServer-Linux-Test)" ]; then + echo "Server already running" + send_webhook_notification "$WEBHOOK_REMOTE_ACTION" "$WEBHOOK_REMOTE_ISRUNNING_DESCRIPTION" "$WEBHOOK_INFO_COLOR" + exit 0; +fi + +source /server.sh + +trap 'term_handler false' SIGTERM + +send_webhook_notification "$WEBHOOK_REMOTE_ACTION" "$WEBHOOK_REMOTE_START_DESCRIPTION" "$WEBHOOK_INFO_COLOR" + +start_main + +while true; do + if [ -z "$(pidof PalServer-Linux-Test)" ]; then + #server exited without termhandler e.g. rcon -> send notification + send_stop_notification + exit 0 + fi + + sleep 5 +done \ No newline at end of file diff --git a/includes/remotestop.sh b/includes/remotestop.sh new file mode 100644 index 0000000..72e0381 --- /dev/null +++ b/includes/remotestop.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +if [ ${REMOTE_CONTROL:false} != "true" ]; then + echo "Remote control is not active..." + exit 0; +fi +source /webhook.sh + +serverpid="$(pidof PalServer-Linux-Test)" + +if [ -z $serverpid ]; then + echo "Server not running" + send_webhook_notification "$WEBHOOK_REMOTE_ACTION" "$WEBHOOK_REMOTE_NOTRUNNING_DESCRIPTION" "$WEBHOOK_INFO_COLOR" + + exit 0; +fi + +source /server.sh + +send_webhook_notification "$WEBHOOK_REMOTE_ACTION" "$WEBHOOK_REMOTE_STOP_DESCRIPTION" "$WEBHOOK_INFO_COLOR" + +term_handler \ No newline at end of file diff --git a/includes/server.sh b/includes/server.sh new file mode 100644 index 0000000..bf30e5d --- /dev/null +++ b/includes/server.sh @@ -0,0 +1,74 @@ +#!/bin/bash +# Stop on errors, comment in, if needed +#set -e +source /config.sh +source /cron.sh +source /install.sh +source /rcon.sh +source /security.sh +source /webhook.sh + +GAME_PATH="/palworld" + +function start_server() { + # IF Bash extension used: + # https://stackoverflow.com/a/13864829 + # https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02 + + echo ">>> Starting the gameserver" + cd $GAME_PATH + + setup_engine_ini + setup_pal_world_settings_ini + + START_OPTIONS="" + if [[ -n $COMMUNITY_SERVER ]] && [[ $COMMUNITY_SERVER == "true" ]]; then + echo "> Setting Community-Mode to enabled" + START_OPTIONS="$START_OPTIONS EpicApp=PalServer" + fi + if [[ -n $MULTITHREAD_ENABLED ]] && [[ $MULTITHREAD_ENABLED == "true" ]]; then + echo "> Setting Multi-Core-Enchancements to enabled" + START_OPTIONS="$START_OPTIONS -useperfthreads -NoAsyncLoadingThread -UseMultithreadForDS" + fi + if [[ -n $WEBHOOK_ENABLED ]] && [[ $WEBHOOK_ENABLED == "true" ]]; then + send_start_notification + fi + ./PalServer.sh "$START_OPTIONS" +} + +function start_main() { + check_for_default_credentials + setup_crons + if [ ! -f "$GAME_PATH/PalServer.sh" ]; then + install_server + fi + if [ $ALWAYS_UPDATE_ON_START == "true" ]; then + update_server + fi + start_server +} + +term_handler() { + local stopnotification=${1:"true"} + + if [ -z "$(pidof PalServer-Linux-Test)" ]; then + exit $exit_code + fi + + if [[ ! -z ${RCON_ENABLED+x} ]]; then + save_and_shutdown_server + fi + kill -SIGTERM $(pidof PalServer-Linux-Test) + tail --pid=$(pidof PalServer-Linux-Test) -f 2>/dev/null + + if [ ${REMOTE_CONTROL:false} != "true" ]; then + kill -SIGTERM $(pidof /remotestart.sh) + tail --pid=$(pidof remotestart) -f 2>/dev/null + fi + + if [ $stopnotification == "true"]; then + send_stop_notification + fi + + exit $exit_code; +} diff --git a/includes/webhook.sh b/includes/webhook.sh index df55c4d..a631133 100644 --- a/includes/webhook.sh +++ b/includes/webhook.sh @@ -17,14 +17,16 @@ EOF # Function to send a notification to a webhook send_webhook_notification() { - local title="$1" - local description="$2" - local color="$3" - - # Debug Curl - #curl --ssl-no-revoke -H "Content-Type: application/json" -X POST -d "$(generate_post_data "$title" "$description" "$color")" "$WEBHOOK_URL" - # Prod Curl - curl --silent --ssl-no-revoke -H "Content-Type: application/json" -X POST -d "$(generate_post_data "$title" "$description" "$color")" "$WEBHOOK_URL" + if [ ${WEBHOOK_ENABLED:false} == "true" ]; then + local title="$1" + local description="$2" + local color="$3" + + # Debug Curl + #curl --ssl-no-revoke -H "Content-Type: application/json" -X POST -d "$(generate_post_data "$title" "$description" "$color")" "$WEBHOOK_URL" + # Prod Curl + curl --silent --ssl-no-revoke -H "Content-Type: application/json" -X POST -d "$(generate_post_data "$title" "$description" "$color")" "$WEBHOOK_URL" + fi } #Aliases to use in scripts diff --git a/remotehooks.json b/remotehooks.json new file mode 100644 index 0000000..474a499 --- /dev/null +++ b/remotehooks.json @@ -0,0 +1,12 @@ +[ + { + "id": "start", + "execute-command": "/remotestart.sh", + "command-working-directory": "/home/steam/steamcmd" + }, + { + "id": "stop", + "execute-command": "/remotestop.sh", + "command-working-directory": "/home/steam/steamcmd" + } +] \ No newline at end of file diff --git a/servermanager.sh b/servermanager.sh index 54fd01b..83a60ea 100755 --- a/servermanager.sh +++ b/servermanager.sh @@ -1,72 +1,21 @@ #!/bin/bash -# Stop on errors, comment in, if needed -#set -e -source /config.sh -source /cron.sh -source /install.sh -source /rcon.sh -source /security.sh -source /webhook.sh - -GAME_PATH="/palworld" - -function start_server() { - # IF Bash extension used: - # https://stackoverflow.com/a/13864829 - # https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02 - - echo ">>> Starting the gameserver" - cd $GAME_PATH - - setup_engine_ini - setup_pal_world_settings_ini - START_OPTIONS="" - if [[ -n $COMMUNITY_SERVER ]] && [[ $COMMUNITY_SERVER == "true" ]]; then - echo "> Setting Community-Mode to enabled" - START_OPTIONS="$START_OPTIONS EpicApp=PalServer" - fi - if [[ -n $MULTITHREAD_ENABLED ]] && [[ $MULTITHREAD_ENABLED == "true" ]]; then - echo "> Setting Multi-Core-Enchancements to enabled" - START_OPTIONS="$START_OPTIONS -useperfthreads -NoAsyncLoadingThread -UseMultithreadForDS" - fi - if [[ -n $WEBHOOK_ENABLED ]] && [[ $WEBHOOK_ENABLED == "true" ]]; then - send_start_notification - fi - ./PalServer.sh "$START_OPTIONS" -} - -function start_main() { - check_for_default_credentials - setup_crons - if [ ! -f "$GAME_PATH/PalServer.sh" ]; then - install_server - fi - if [ $ALWAYS_UPDATE_ON_START == "true" ]; then - update_server - fi - start_server -} - -term_handler() { - if [[ ! -z ${RCON_ENABLED+x} ]]; then - save_and_shutdown_server - fi - kill -SIGTERM $(pidof PalServer-Linux-Test) - tail --pid=$(pidof PalServer-Linux-Test) -f 2>/dev/null - if [[ -n $WEBHOOK_ENABLED ]] && [[ $WEBHOOK_ENABLED == "true" ]]; then - send_stop_notification - fi - exit 143; -} - -trap 'kill ${!}; term_handler' SIGTERM +source /server.sh +source /webhook.sh -start_main & -killpid="$!" -while true -do - wait $killpid - send_stop_notification - exit 0; -done +trap 'term_handler' SIGTERM + +if [ ${REMOTE_CONTROL:false} == "true" ]; then + webhook -hooks /remotehooks.json -verbose & + killpid=$(pidof webhook) + send_webhook_notification "$WEBHOOK_REMOTE_ACTION" "$WEBHOOK_REMOTE_READY_DESCRIPTION" "$WEBHOOK_INFO_COLOR" + wait "$killpid" +else + start_main & + killpid="$!" + wait "$killpid" + #graeful exit eg. via rcon + send_stop_notification +fi + +exit 0;