diff --git a/.env.example b/.env.example index ba55b7c..9ad5afe 100644 --- a/.env.example +++ b/.env.example @@ -9,8 +9,8 @@ CFG_PASSWORD="" CFG_COMMUNITY_WEBSITE="www.longvinter.com" CFG_COOP_PLAY=false CFG_COOP_SPAWN=0 -CFG_SERVER_TAG="none" +CFG_TAG="none" CFG_ADMIN_STEAM_ID="" -CFG_ENABLE_PVP=true +CFG_PVP=true CFG_TENT_DECAY=true CFG_MAX_TENTS=2 diff --git a/Dockerfile b/Dockerfile index ed01faf..e92589a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,20 +18,20 @@ LABEL maintainer="me@kimzuni.com" \ # set envs # SUPERCRONIC: Latest releases available at https://github.com/aptible/supercronic/releases +# DEPOT_DOWNLOADER: Latest releases available at https://github.com/SteamRE/DepotDownloader/releases # NOTICE: edit SUPERCRONIC_SHA1SUM when using binaries of another version or arch. ARG SUPERCRONIC_SHA1SUM_ARM64="d5e02aa760b3d434bc7b991777aa89ef4a503e49" ARG SUPERCRONIC_SHA1SUM_AMD64="9f27ad28c5c57cd133325b2a66bba69ba2235799" ARG SUPERCRONIC_VERSION="0.2.30" - -SHELL ["/bin/bash", "-o", "pipefail", "-c"] +ARG DEPOT_DOWNLOADER_VERSION="2.6.0" # update and install dependencies # hadolint ignore=DL3008 RUN apt-get update && \ apt-get install --no-install-recommends --no-install-suggests -y \ - curl \ - net-tools \ - ca-certificates \ + wget \ + net-tools=2.10-0.1 \ + ca-certificates=20230311 \ lib32gcc-s1-amd64-cross=12.2.0-14cross1 \ procps=2:4.0.2-3 \ gettext-base=0.21-12 \ @@ -39,29 +39,40 @@ RUN apt-get update && \ jo=1.9-1 \ jq=1.6-2.1 \ netcat-traditional=1.10-47 \ - && curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash \ - && apt-get --no-install-recommends --no-install-suggests -y \ - install git git-lfs \ + libicu72=72.1-3 \ + unzip=6.0-28 \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* -# install supercronic +# install supercronic and DepotDownloader +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + ARG TARGETARCH -RUN case ${TARGETARCH} in \ - "amd64") SUPERCRONIC_SHA1SUM=${SUPERCRONIC_SHA1SUM_AMD64} ;; \ - "arm64") SUPERCRONIC_SHA1SUM=${SUPERCRONIC_SHA1SUM_ARM64} ;; \ +RUN case "${TARGETARCH}" in \ + "amd64") SUPERCRONIC_SHA1SUM="${SUPERCRONIC_SHA1SUM_AMD64}" ;; \ + "arm64") SUPERCRONIC_SHA1SUM="${SUPERCRONIC_SHA1SUM_ARM64}" ;; \ esac \ - && curl -sfSL "https://github.com/aptible/supercronic/releases/download/v${SUPERCRONIC_VERSION}/supercronic-linux-${TARGETARCH}" -o supercronic \ + && wget --progress=dot:giga "https://github.com/aptible/supercronic/releases/download/v${SUPERCRONIC_VERSION}/supercronic-linux-${TARGETARCH}" -O supercronic \ && echo "${SUPERCRONIC_SHA1SUM}" supercronic | sha1sum -c - \ && chmod +x supercronic \ && mv supercronic /usr/local/bin/supercronic +RUN case "${TARGETARCH}" in \ + "amd64") DEPOT_DOWNLOADER_FILENAME="DepotDownloader-linux-x64.zip" ;; \ + "arm64") DEPOT_DOWNLOADER_FILENAME="DepotDownloader-linux-arm64.zip" ;; \ + esac \ + && wget --progress=dot:giga "https://github.com/SteamRE/DepotDownloader/releases/download/DepotDownloader_${DEPOT_DOWNLOADER_VERSION}/${DEPOT_DOWNLOADER_FILENAME}" -O DepotDownloader.zip \ + && unzip DepotDownloader.zip \ + && rm -rf DepotDownloader.zip DepotDownloader.xml \ + && chmod +x DepotDownloader \ + && mv DepotDownloader /usr/local/bin/DepotDownloader + # hadolint ignore=DL3044 -ENV TZ="UTC" \ +ENV HOME=/home/steam \ + TZ="UTC" \ PUID=1000 \ PGID=1000 \ PORT=7777 \ - QUERY_PORT=27016 \ UPDATE_ON_BOOT=true \ BACKUP_ENABLED=true \ BACKUP_CRON_EXPRESSION="0 0 * * *" \ @@ -80,7 +91,7 @@ ENV TZ="UTC" \ AUTO_REBOOT_EVEN_IF_PLAYERS_ONLINE=false \ BROADCAST_COUNTDOWN_SUSPEND_MESSAGE="Suspends countdown because there are no players." \ BROADCAST_COUNTDOWN_SUSPEND_MESSAGE_ENABLE=true \ - TARGET_COMMIT_ID= \ + TARGET_MANIFEST_ID= \ DISCORD_WEBHOOK_URL="" \ DISCORD_SUPPRESS_NOTIFICATIONS=false \ DISCORD_CONNECT_TIMEOUT=30 \ @@ -100,9 +111,6 @@ ENV TZ="UTC" \ DISCORD_PRE_START_MESSAGE="Server has been started!" \ DISCORD_PRE_START_MESSAGE_ENABLED=true \ DISCORD_PRE_START_MESSAGE_URL="" \ - DISCORD_PRE_START_MESSAGE_WITH_GAME_SETTINGS=true \ - DISCORD_PRE_START_MESSAGE_WITH_SERVER_IP=false \ - DISCORD_PRE_START_MESSAGE_WITH_DOMAIN="" \ DISCORD_PRE_SHUTDOWN_MESSAGE="Server is shutting down..." \ DISCORD_PRE_SHUTDOWN_MESSAGE_ENABLED=true \ DISCORD_PRE_SHUTDOWN_MESSAGE_URL="" \ @@ -135,7 +143,9 @@ ENV TZ="UTC" \ DISABLE_GENERATE_SETTINGS=false \ ENABLE_PLAYER_LOGGING=true \ PLAYER_LOGGING_POLL_PERIOD=5 \ - ARM64_DEVICE=generic + ARM64_DEVICE=generic \ + USE_DEPOT_DOWNLOADER=false \ + INSTALL_BETA_VERSION=false # Sane Box64 config defaults # hadolint ignore=DL3044 @@ -150,7 +160,7 @@ ENV BOX64_DYNAREC_STRONGMEM=1 \ ARG GIT_VERSION_TAG=unspecified COPY --chmod=755 ./scripts /home/steam/server -RUN for file in backup.sh update.sh restore.sh reboot.sh broadcast.sh; do \ +RUN for file in backup.sh update.sh restore.sh broadcast.sh; do \ mv /home/steam/server/"$file" /usr/local/bin/"${file%.sh}"; \ done diff --git a/docker-compose.yml b/docker-compose.yml index 3ff36ad..afb11a7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,9 +24,9 @@ services: CFG_COMMUNITY_WEBSITE: "www.longvinter.com" CFG_COOP_PLAY: false CFG_COOP_SPAWN: 0 - CFG_SERVER_TAG: "none" + CFG_TAG: "none" CFG_ADMIN_STEAM_ID: "" - CFG_ENABLE_PVP: true + CFG_PVP: true CFG_TENT_DECAY: true CFG_MAX_TENTS: 2 volumes: diff --git a/docs/en/README.md b/docs/en/README.md index bf810df..ba4b17b 100644 --- a/docs/en/README.md +++ b/docs/en/README.md @@ -25,61 +25,62 @@ to generate this image. This Docker container has been tested and will work on the following OS: -- Windows 11 -- Ubuntu 22.04 +* Windows 11 +* Ubuntu 22.04 This container has also been tested and will work on both `x64` and `ARM64` based CPU architecture. > [!WARNING] -> At the moment, All related features have been replaced and removed because Longvinter does not support RCON. +> At the moment, All related features have been replaced and removed because Longvinter does not support RCON/REST API. > -> Therefore, we would like to inform you that if you do not save the server and proceed -> with server shutdown, and recovery, the history of your play for up to 12 minutes may be rolled back. -> (Server is Automatically saved every 10~12 minutes.) +> As a result, containers don't have the ability to save servers, +> so using some features without saving servers can result +> in a rollback of about 5 minutes of play history. +> (Server is Automatically saved every 5 minutes) ## Official URL -- [Longvinter](https://www.longvinter.com/) - - [Wiki](https://wiki.longvinter.com) - - [X(Twitter)](https://twitter.com/longvinter) - - [Reddit](https://www.reddit.com/r/Longvinter/) - - [TicTok](https://www.tiktok.com/@longvinter) - - [Instagram](https://www.instagram.com/longvintergame) - - [Server Docs](https://docs-server.longvinter.com/) - - [Discord](https://discord.gg/longvinter) -- [Uuvana](https://www.uuvana.com/) - - [X(Twitter)](https://twitter.com/uuvanastudios) - - [Youtube](https://www.youtube.com/@uuvana) - - [Instagram](https://www.instagram.com/uuvanastudios/) - - [Media Kit](https://longvinter.com/press) - - [Forum](https://forum.uuvana.com/) - - ~~[FAQ(Frequently Asked Questions)](https://contact.uuvana.com/)~~ +* [Longvinter](https://www.longvinter.com/) + * [Wiki](https://wiki.longvinter.com) + * [X(Twitter)](https://twitter.com/longvinter) + * [Reddit](https://www.reddit.com/r/Longvinter/) + * [TicTok](https://www.tiktok.com/@longvinter) + * [Instagram](https://www.instagram.com/longvintergame) + * [Server Docs](https://docs-server.longvinter.com/) + * [Discord](https://discord.gg/longvinter) +* [Uuvana](https://www.uuvana.com/) + * [X(Twitter)](https://twitter.com/uuvanastudios) + * [Youtube](https://www.youtube.com/@uuvana) + * [Instagram](https://www.instagram.com/uuvanastudios/) + * [Media Kit](https://longvinter.com/press) + * [Forum](https://forum.uuvana.com/) + * ~~[FAQ(Frequently Asked Questions)](https://contact.uuvana.com/)~~ ## Server Requirements -> - OS: Min. 64-bit -> - RAM: Min. 2GB +* OS: Min. 64-bit +* RAM: Min. 2GB -from: +from -## How to Use +## How to use Keep in mind that you'll need to change the [environment variables](#environment-variables). -After running the server, you can check the server log with the command `docker log longvinter-server`. +After running the server, you can check the server log with the command `docker logs longvinter-server`. To check in real time, add `-f` at the end. ### Docker Compose This repository includes an example [docker-compose.yml](/docker-compose.yml) file you can use to set up your server. -Write the file first and then execute the command `docker compose up -d` from that directory. +To run the server, Write the file first and then execute the command `docker compose up -d` from that directory. -```yaml +```yml services: - longvinter-server: - container_name: longvinter-server + longvinter: image: kimzuni/longvinter-docker-server:latest restart: unless-stopped + container_name: longvinter-server stop_grace_period: 30s # Set to however long you are willing to wait for the container to gracefully stop logging: driver: json-file @@ -100,9 +101,9 @@ services: CFG_COMMUNITY_WEBSITE: "www.longvinter.com" CFG_COOP_PLAY: false CFG_COOP_SPAWN: 0 - CFG_SERVER_TAG: "none" + CFG_TAG: "none" CFG_ADMIN_STEAM_ID: "" - CFG_ENABLE_PVP: true + CFG_PVP: true CFG_TENT_DECAY: true CFG_MAX_TENTS: 2 volumes: @@ -110,15 +111,15 @@ services: ``` As an alternative, you can copy the [.env.example](/.env.example) file to a new file called **.env** file. -Modify it to your needs, check out the [environment variables](#environment-variables) section to check the correct values. -Modify your [docker-compose.yml](docker-compose.yml) to this: +Modify it to your needs, check out the [environment variables](#environment-variables) section to check the correct +values. Modify your [docker-compose.yml](/docker-compose.yml) to this: ```yml services: - longvinter-server: - container_name: longvinter-server + longvinter: image: kimzuni/longvinter-docker-server:latest restart: unless-stopped + container_name: longvinter-server stop_grace_period: 30s # Set to however long you are willing to wait for the container to gracefully stop logging: driver: json-file @@ -135,7 +136,8 @@ services: ### Docker Run -You can also use the command `docker run` instead of `docker compose`. the server runs as soon as you run the command below. +You can also use the command `docker run` instead of `docker compose`. +The container is created as soon as you run the command below. ```bash docker run -d \ @@ -153,9 +155,9 @@ docker run -d \ -e CFG_COMMUNITY_WEBSITE="www.longvinter.com" \ -e CFG_COOP_PLAY=false \ -e CFG_COOP_SPAWN=0 \ - -e CFG_SERVER_TAG="none" \ + -e CFG_TAG="none" \ -e CFG_ADMIN_STEAM_ID="" \ - -e CFG_ENABLE_PVP=true \ + -e CFG_PVP=true \ -e CFG_TENT_DECAY=true \ -e CFG_MAX_TENTS=2 \ --restart unless-stopped \ @@ -164,8 +166,8 @@ docker run -d \ ``` As an alternative, you can copy the [.env.example](/.env.example) file to a new file called **.env** file. -Modify it to your needs, check out the [environment variables](#environment-variables) section to check the correct values. -Change your docker run command to this: +Modify it to your needs, check out the [environment variables](#environment-variables) section to check the +correct values. Change your docker run command to this: ```bash docker run -d \ @@ -180,11 +182,10 @@ docker run -d \ ### Update the Container -If you are running the server first, please stop: +To update the container version, stop the container first. ```bash -docker stop longvinter-server -docker rm longvinter-server +docker compose down ``` Next, remove the installed image: @@ -197,115 +198,134 @@ Finally, run the [Docker Compose](#docker-compose) or [Docker Run](#docker-run) ### Running without root -This is only for advanced users. +This is only for advanced users It is possible to run this container and [override the default user](https://docs.docker.com/engine/reference/run/#user) which is root in this image. Because you are specifiying the user and group `PUID` and `PGID` are ignored. -If you want to find your UID: `id -u`, -If you want to find your GID: `id -g`. +If you want to find your UID: `id -u` +If you want to find your GID: `id -g` -You must set user to `NUMBERICAL_UID:NUMBERICAL_GID`. +You must set user to `NUMBERICAL_UID:NUMBERICAL_GID` -Below we assume your UID is 1000 and your GID is 1001. +Below we assume your UID is 1000 and your GID is 1001 -- In [Docker Run](#docker-run) add `--user 1000:1001 \` above the last line. -- In [Docker Compose](#docker-compose) add `user: 1000:1001` above ports. +* In docker run add `--user 1000:1001 \` above the last line. +* In docker compose add `user: 1000:1001` above ports. If you wish to run it with a different UID/GID than your own you will need to change the ownership of the directory that is being bind: `chown UID:GID data/` or by changing the permissions for all other: `chmod o=rwx data/` -## Environment variables - -You can use the following values to change the settings of the server on boot. -It is highly recommended you set the following environment values before starting the server: - -| Variable | Info | Default Value | Allowed Values | Added in Version | -|----------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------|------------------| -| TZ | Timezone used for Cron and Game server. (Not applicable to Log) | UTC | See [TZ Identifiers](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#Time_Zone_abbreviations) | 0.1.0 | -| PUID\* | The uid of the user the server should run as. | 1000 | !0 | 0.1.0 | -| PGID\* | The gid of the user the server should run as. | 1000 | !0 | 0.1.0 | -| PORT\* | Game port that the server will expose. | 7777 | 1024-65535 | 0.1.0 | -| UPDATE_ON_BOOT\*\* | Update the server when the docker container starts. | true | true/false | 0.1.0 | -| BACKUP_ENABLED | Enables automatic backups. | true | true/false | 0.1.1 | -| BACKUP_CRON_EXPRESSION | Setting affects frequency of automatic backups. | 0 0 \* \* \* | Needs a Cron-Expression - See [Configuring Automatic Backups with Cron](#configuring-automatic-backups-with-cron) | 0.1.1 | -| DELETE_OLD_BACKUPS | Delete backups after a certain number of days. | false | true/false | 0.1.1 | -| OLD_BACKUP_DAYS | How many days to keep backups. | 30 | !0 | 0.1.1 | -| AUTO_UPDATE_ENABLED | Enables automatic updates. | false | true/false | 0.1.4 | -| AUTO_UPDATE_CRON_EXPRESSION | Setting affects frequency of automatic updates. | 0 \* \* \* \* | Needs a Cron-Expression - See [Configuring Automatic Updates with Cron](#configuring-automatic-updates-with-cron) | 0.1.4 | -| AUTO_UPDATE_WARN_MINUTES | How long to wait to saved and update the server, after the player were informed. (This will be ignored, if no Players are connected) | 15 | !0 | 0.1.4 | -| AUTO_UPDATE_WARN_MESSAGE | Messages to broadcast on countdown for automatic updates. | Server will update in `remaining_time` minutes. | "string" | 0.1.10 | -| AUTO_UPDATE_WARN_REMAINING_TIMES | Informing when the remaining time during countdown is included. | 1 5 10 | !0 and " "(Space) | 0.1.10 | -| AUTO_REBOOT_ENABLED | Enables automatic reboots. | false | true/false | 0.1.10 | -| AUTO_REBOOT_CRON_EXPRESSION | Setting affects frequency of automatic reboots. | 0 0 \* \* \* | Needs a Cron-Expression - See [Configuring Automatic Reboots with Cron](#configuring-automatic-reboots-with-cron) | 0.1.10 | -| AUTO_REBOOT_WARN_MINUTES | How long to wait to saved and reboot the server, after the player were informed. (This will be ignored, if no Players are connected) | 15 | !0 | 0.1.10 | -| AUTO_REBOOT_WARN_MESSAGE | Messages to broadcast on countdown for automatic reboots. | Server will reboot in `remaining_time` minutes. | "string" | 0.1.10 | -| AUTO_REBOOT_WARN_REMAINING_TIMES | Informing when the remaining time during countdown is included. | 1 5 10 | !0 and " "(Space) | 0.1.10 | -| AUTO_REBOOT_EVEN_IF_PLAYERS_ONLINE | Reboot the Server even if there are players online. | false | true/false | 0.1.10 | -| BROADCAST_COUNTDOWN_SUSPEND_MESSAGE | Discord message when countdown suspended due to no players. | Suspends countdown because there are no players. | "string" | 0.1.10 | -| BROADCAST_COUNTDOWN_SUSPEND_MESSAGE_ENABLED | If the Discord message is enabled for this message. | true | true/false | 0.1.2 | -| TARGET_COMMIT_ID | Install and run the game server at the specified version. | _(empty)_ | See [Locking Specific Game Version](#locking-specific-game-version)(#target-commit-id) | 0.1.3 | -| DISCORD_WEBHOOK_URL | Discord webhook url found after creating a webhook on a discord server. | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.0 | -| DISCORD_SUPPRESS_NOTIFICATIONS | Enables/Disables `@silent` messages for the server messages. | false | true/false | 0.1.0 | -| DISCORD_CONNECT_TIMEOUT | Discord command initial connection timeout. | 30 | !0 | 0.1.0 | -| DISCORD_MAX_TIMEOUT | Discord total hook timeout. | 30 | !0 | 0.1.0 | -| DISCORD_PRE_INSTALL_MESSAGE | Discord message sent when server begins installing. | Server is installing... | "string" | 0.1.0 | -| DISCORD_PRE_INSTALL_MESSAGE_ENABLED | If the Discord message is enabled for this message. | true | true/false | 0.1.0 | -| DISCORD_PRE_INSTALL_MESSAGE_URL | Discord Webhook URL for this message. (if left empty will use DISCORD_WEBHOOK_URL) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.0 | -| DISCORD_POST_INSTALL_MESSAGE | Discord message sent when server completes installing. | Server install complete! | "string" | 0.1.2 | -| DISCORD_POST_INSTALL_MESSAGE_ENABLED | If the Discord message is enabled for this message. | true | true/false | 0.1.2 | -| DISCORD_POST_INSTALL_MESSAGE_URL | Discord Webhook URL for this message. (if left empty will use DISCORD_WEBHOOK_URL) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.2 | -| DISCORD_PRE_UPDATE_BOOT_MESSAGE | Discord message sent when server begins updating. | Server is updating... | "string" | 0.1.0 | -| DISCORD_PRE_UPDATE_BOOT_MESSAGE_ENABLED | If the Discord message is enabled for this message. | true | true/false | 0.1.0 | -| DISCORD_PRE_UPDATE_BOOT_MESSAGE_URL | Discord Webhook URL for this message. (if left empty will use DISCORD_WEBHOOK_URL) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.0 | -| DISCORD_POST_UPDATE_BOOT_MESSAGE | Discord message sent when server completes updating. | Server update complete! | "string" | 0.1.2 | -| DISCORD_POST_UPDATE_BOOT_MESSAGE_ENABLED | If the Discord message is enabled for this message. | true | true/false | 0.1.2 | -| DISCORD_POST_UPDATE_BOOT_MESSAGE_URL | Discord Webhook URL for this message. (if left empty will use DISCORD_WEBHOOK_URL) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.2 | -| DISCORD_PRE_START_MESSAGE | Discord message sent when server begins to start. | Server has been started! | "string" | 0.1.0 | -| DISCORD_PRE_START_MESSAGE_ENABLED | If the Discord message is enabled for this message. | true | true/false | 0.1.0 | -| DISCORD_PRE_START_MESSAGE_URL | Discord Webhook URL for this message. (if left empty will use DISCORD_WEBHOOK_URL) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.0 | -| DISCORD_PRE_START_MESSAGE_WITH_GAME_SETTINGS | Send the server settings with DISCORD_PRE_START_MESSAGE. | true | true/false | 0.1.1 | -| DISCORD_PRE_START_MESSAGE_WITH_SERVER_IP | Send the server IP and Port with DISCORD_PRE_START_MESSAGE. | false | true/false | 0.1.0 | -| DISCORD_PRE_START_MESSAGE_WITH_DOMAIN | Send the Domain and Port with DISCORD_PRE_START_MESSAGE. (DISCORD_SERVER_INFO_MESSAGE_WITH_IP value ignored when set) | _(empty)_ | `example.com`, `http://example.com`, `https://example.com` | 0.1.11 | -| DISCORD_PRE_SHUTDOWN_MESSAGE | Discord message sent when server begins to shutdown. | Server is shutting down... | "string" | 0.1.0 | -| DISCORD_PRE_SHUTDOWN_MESSAGE_ENABLED | If the Discord message is enabled for this message. | true | true/false | 0.1.0 | -| DISCORD_PRE_SHUTDOWN_MESSAGE_URL | Discord Webhook URL for this message. (if left empty will use DISCORD_WEBHOOK_URL) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.0 | -| DISCORD_POST_SHUTDOWN_MESSAGE | Discord message sent when server begins to shutdown. | Server is stopped! | "string" | 0.1.0 | -| DISCORD_POST_SHUTDOWN_MESSAGE_ENABLED | If the Discord message is enabled for this message. | true | true/false | 0.1.0 | -| DISCORD_POST_SHUTDOWN_MESSAGE_URL | Discord Webhook URL for this message. (if left empty will use DISCORD_WEBHOOK_URL) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.0 | -| DISCORD_PLAYER_JOIN_MESSAGE | Discord message sent when player joins the server. | `player_name` has joined! | "string" | 0.1.9 | -| DISCORD_PLAYER_JOIN_MESSAGE_ENABLED | If the Discord message is enabled for this message. | true | true/false | 0.1.9 | -| DISCORD_PLAYER_JOIN_MESSAGE_URL | Discord Webhook URL for this message. (if left empty will use DISCORD_WEBHOOK_URL) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.9 | -| DISCORD_PLAYER_LEAVE_MESSAGE | Discord message sent when player leaves the server. | `player_name` has left. | "string" | 0.1.9 | -| DISCORD_PLAYER_LEAVE_MESSAGE_ENABLED | If the Discord message is enabled for this message. | true | true/false | 0.1.9 | -| DISCORD_PLAYER_LEAVE_MESSAGE_URL | Discord Webhook URL for this message. (if left empty will use DISCORD_WEBHOOK_URL) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.9 | -| DISCORD_PRE_BACKUP_MESSAGE | Discord message when starting to create a backup. | Creating backup... | "string" | 0.1.1 | -| DISCORD_PRE_BACKUP_MESSAGE_ENABLED | If the Discord message is enabled for this message. | true | true/false | 0.1.1 | -| DISCORD_PRE_BACKUP_MESSAGE_URL | Discord Webhook URL for this message. (if left empty will use DISCORD_WEBHOOK_URL) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.1 | -| DISCORD_POST_BACKUP_MESSAGE | Discord message when a backup has been made. | Backup created at `file_path` | "string" | 0.1.1 | -| DISCORD_POST_BACKUP_MESSAGE_ENABLED | If the Discord message is enabled for this message. | true | true/false | 0.1.1 | -| DISCORD_POST_BACKUP_MESSAGE_URL | Discord Webhook URL for this message. (if left empty will use DISCORD_WEBHOOK_URL) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.1 | -| DISCORD_PRE_BACKUP_DELETE_MESSAGE | Discord message when starting to remove older backups. | Removing backups older than `old_backup_days` days | "string" | 0.1.1 | -| DISCORD_PRE_BACKUP_DELETE_MESSAGE_ENABLED | If the Discord message is enabled for this message. | true | true/false | 0.1.1 | -| DISCORD_PRE_BACKUP_DELETE_MESSAGE_URL | Discord Webhook URL for this message. (if left empty will use DISCORD_WEBHOOK_URL) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.1 | -| DISCORD_POST_BACKUP_DELETE_MESSAGE | Discord message when successfully removed older backups. | Removed backups older than `old_backup_days` days | "string" | 0.1.1 | -| DISCORD_POST_BACKUP_DELETE_MESSAGE_ENABLED | If the Discord message is enabled for this message. | true | true/false | 0.1.1 | -| DISCORD_POST_BACKUP_DELETE_MESSAGE_URL | Discord Webhook URL for this message. (if left empty will use DISCORD_WEBHOOK_URL) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.1 | -| DISCORD_ERR_BACKUP_DELETE_MESSAGE | Discord message when there has been an error removing older backups. | Unable to delete old backups, OLD_BACKUP_DAYS is not an integer. OLD_BACKUP_DAYS=`old_backup_days` | "string" | 0.1.1 | -| DISCORD_ERR_BACKUP_DELETE_MESSAGE_ENABLED | If the Discord message is enabled for this message. | true | true/false | 0.1.1 | -| DISCORD_ERR_BACKUP_DELETE_MESSAGE_URL | Discord Webhook URL for this message. (if left empty will use DISCORD_WEBHOOK_URL) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.1 | -| DISCORD_BROADCAST_MESSAGE_ENABLE\*\* | If the Discord message is enabled for broadcast content. | true | true/false | 0.1.6 | -| DISCORD_BROADCAST_MESSAGE_URL\* | Discord Webhook URL for this message. (if left empty will use DISCORD_WEBHOOK_URL) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.6 | -| DISABLE_GENERATE_SETTINGS | Whether to automatically generate the Game.ini | false | true/false | 0.1.1 | -| ENABLE_PLAYER_LOGGING | Enables Logging and announcing when players join and leave. | true | true/false | 0.1.9 | -| PLAYER_LOGGING_POLL_PERIOD | Polling period (in seconds) to check for players who have joined or left | 5 | !0 | 0.1.9 | - -\* highly recommended to set - -\*\* Make sure you know what you are doing when running this option enabled. +### Environment variables + +You can use the following values to change the settings of the container on boot. +It is highly recommended you set the following environment values before starting the container: + +* PUID +* PGID +* PORT + +| Variable | Info | Default Value | Allowed Values | Added in Version | +|-----------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------|-------------------| +| TZ | Set the timezone in container | UTC | See [TZ Identifiers](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#Time_Zone_abbreviations) | 0.1.0 | +| PUID* | The uid of the user the server should run as | 1000 | !0 | 0.1.0 | +| PGID* | The gid of the user the server should run as | 1000 | !0 | 0.1.0 | +| PORT* | UDP port that the server will expose | 7777 | 1024-65535 | 0.1.0 | +| UPDATE_ON_BOOT** | Update the server when the docker container starts | true | true/false | 0.1.0 | +| BACKUP_ENABLED | Enables automatic backups | true | true/false | 0.1.1 | +| BACKUP_CRON_EXPRESSION | Setting affects frequency of automatic backups | 0 0 \* \* \* | Needs a Cron-Expression - See [Configuring Automatic Backups with Cron](#configuring-automatic-backups-with-cron) | 0.1.1 | +| DELETE_OLD_BACKUPS | Delete backups after a certain number of days | false | true/false | 0.1.1 | +| OLD_BACKUP_DAYS | How many days to keep backups | 30 | any positive integer | 0.1.1 | +| AUTO_UPDATE_ENABLED | Enables automatic updates | false | true/false | 0.1.4 | +| AUTO_UPDATE_CRON_EXPRESSION | Setting affects frequency of automatic updates | 0 \* \* \* \* | Needs a Cron-Expression - See [Configuring Automatic Updates with Cron](#configuring-automatic-updates-with-cron) | 0.1.4 | +| AUTO_UPDATE_WARN_MINUTES | How long to wait to saved and update the server, after the player were informed (This will be ignored, if no Players are connected) | 15 | Integer | 0.1.4 | +| AUTO_UPDATE_WARN_MESSAGE | Broadcast message sent when countdown for server updates | Server will update in `remaining_time` minutes. | "string" | 0.1.10 | +| AUTO_UPDATE_WARN_REMAINING_TIMES | Time to broadcast countdowns to players for server updates | 1 5 10 | Integer, " "(Space) | 0.1.10 | +| AUTO_REBOOT_ENABLED | Enables automatic reboots | false | true/false | 0.1.10 | +| AUTO_REBOOT_CRON_EXPRESSION | Setting affects frequency of automatic reboots | 0 0 \* \* \* | Needs a Cron-Expression - See [Configuring Automatic Reboots with Cron](#configuring-automatic-reboots-with-cron) | 0.1.10 | +| AUTO_REBOOT_WARN_MINUTES | How long to wait to saved and reboot the server, after the player were informed (This will be ignored, if no Players are connected) | 15 | Integer | 0.1.10 | +| AUTO_REBOOT_WARN_MESSAGE | Broadcast message sent when countdown for server reboots | Server will reboot in `remaining_time` minutes. | "string" | 0.1.10 | +| AUTO_REBOOT_WARN_REMAINING_TIMES | Time to broadcast countdowns to players for server reboots | 1 5 10 | Integer, " "(Space) | 0.1.10 | +| AUTO_REBOOT_EVEN_IF_PLAYERS_ONLINE | Restart the Server even if there are players online | false | true/false | 0.1.10 | +| BROADCAST_COUNTDOWN_SUSPEND_MESSAGE | Discord message sent when countdown suspended due to no players. | Suspends countdown because there are no players. | "string" | 0.1.10 | +| BROADCAST_COUNTDOWN_SUSPEND_MESSAGE_ENABLED | If the Discord message is enabled for this message. | true | true/false | 0.1.2 | +| TARGET_MANIFEST_ID | Locks game version to corespond with Manifest ID from Steam Download Depot | | See [Manifest ID Table](#locking-specific-game-version) | 1.0.0 | +| DISCORD_WEBHOOK_URL | Discord webhook url found after creating a webhook on a discord server | | `https://discord.com/api/webhooks/` | 0.1.0 | +| DISCORD_SUPPRESS_NOTIFICATIONS | Enables/Disables `@silent` messages for the server messages | false | true/false | 0.1.0 | +| DISCORD_CONNECT_TIMEOUT | Discord command initial connection timeout | 30 | !0 | 0.1.0 | +| DISCORD_MAX_TIMEOUT | Discord total hook timeout | 30 | !0 | 0.1.0 | +| DISCORD_PRE_INSTALL_MESSAGE | Discord message sent when server begins installing | Server is installing... | "string" | 0.1.0 | +| DISCORD_PRE_INSTALL_MESSAGE_ENABLED | If the Discord message is enabled for this message | true | true/false | 0.1.0 | +| DISCORD_PRE_INSTALL_MESSAGE_URL | Discord Webhook URL for this message (if left empty will use DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.0 | +| DISCORD_POST_INSTALL_MESSAGE | Discord message sent when server completes installing | Server install complete! | "string" | 0.1.2 | +| DISCORD_POST_INSTALL_MESSAGE_ENABLED | If the Discord message is enabled for this message | true | true/false | 0.1.2 | +| DISCORD_POST_INSTALL_MESSAGE_URL | Discord Webhook URL for this message (if left empty will use DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.2 | +| DISCORD_PRE_UPDATE_BOOT_MESSAGE | Discord message sent when server begins updating | Server is updating... | "string" | 0.1.0 | +| DISCORD_PRE_UPDATE_BOOT_MESSAGE_ENABLED | If the Discord message is enabled for this message | true | true/false | 0.1.0 | +| DISCORD_PRE_UPDATE_BOOT_MESSAGE_URL | Discord Webhook URL for this message (if left empty will use DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.0 | +| DISCORD_POST_UPDATE_BOOT_MESSAGE | Discord message sent when server completes updating | Server update complete! | "string" | 0.1.2 | +| DISCORD_POST_UPDATE_BOOT_MESSAGE_ENABLED | If the Discord message is enabled for this message | true | true/false | 0.1.2 | +| DISCORD_POST_UPDATE_BOOT_MESSAGE_URL | Discord Webhook URL for this message (if left empty will use DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.2 | +| DISCORD_PRE_START_MESSAGE | Discord message sent when server begins to start | Server has been started! | "string" | 0.1.0 | +| DISCORD_PRE_START_MESSAGE_ENABLED | If the Discord message is enabled for this message | true | true/false | 0.1.0 | +| DISCORD_PRE_START_MESSAGE_URL | Discord Webhook URL for this message (if left empty will use DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.0 | +| DISCORD_PRE_SHUTDOWN_MESSAGE | Discord message sent when server begins to shutdown | Server is shutting down... | "string" | 0.1.0 | +| DISCORD_PRE_SHUTDOWN_MESSAGE_ENABLED | If the Discord message is enabled for this message | true | true/false | 0.1.0 | +| DISCORD_PRE_SHUTDOWN_MESSAGE_URL | Discord Webhook URL for this message (if left empty will use DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.0 | +| DISCORD_POST_SHUTDOWN_MESSAGE | Discord message sent when server begins to shutdown | Server is stopped! | "string" | 0.1.0 | +| DISCORD_POST_SHUTDOWN_MESSAGE_ENABLED | If the Discord message is enabled for this message | true | true/false | 0.1.0 | +| DISCORD_POST_SHUTDOWN_MESSAGE_URL | Discord Webhook URL for this message (if left empty will use DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.0 | +| DISCORD_PLAYER_JOIN_MESSAGE | Discord message sent when player joins the server | `player_name` has joined! | "string" | 0.1.9 | +| DISCORD_PLAYER_JOIN_MESSAGE_ENABLED | If the Discord message is enabled for this message | true | true/false | 0.1.9 | +| DISCORD_PLAYER_JOIN_MESSAGE_URL | Discord Webhook URL for this message (if left empty will use DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.9 | +| DISCORD_PLAYER_LEAVE_MESSAGE | Discord message sent when player leaves the server | `player_name` has left. | "string" | 0.1.9 | +| DISCORD_PLAYER_LEAVE_MESSAGE_ENABLED | If the Discord message is enabled for this message | true | true/false | 0.1.9 | +| DISCORD_PLAYER_LEAVE_MESSAGE_URL | Discord Webhook URL for this message (if left empty will use DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.9 | +| DISCORD_PRE_BACKUP_MESSAGE | Discord message when starting to create a backup | Creating backup... | "string" | 0.1.1 | +| DISCORD_PRE_BACKUP_MESSAGE_ENABLED | If the Discord message is enabled for this message | true | true/false | 0.1.1 | +| DISCORD_PRE_BACKUP_MESSAGE_URL | Discord Webhook URL for this message (if left empty will use DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.1 | +| DISCORD_POST_BACKUP_MESSAGE | Discord message when a backup has been made | Backup created at `file_path` | "string" | 0.1.1 | +| DISCORD_POST_BACKUP_MESSAGE_ENABLED | If the Discord message is enabled for this message | true | true/false | 0.1.1 | +| DISCORD_POST_BACKUP_MESSAGE_URL | Discord Webhook URL for this message (if left empty will use DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.1 | +| DISCORD_PRE_BACKUP_DELETE_MESSAGE | Discord message when starting to remove older backups | Removing backups older than `old_backup_days` days | "string" | 0.1.1 | +| DISCORD_PRE_BACKUP_DELETE_MESSAGE_ENABLED | If the Discord message is enabled for this message | true | true/false | 0.1.1 | +| DISCORD_PRE_BACKUP_DELETE_MESSAGE_URL | Discord Webhook URL for this message (if left empty will use DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.1 | +| DISCORD_POST_BACKUP_DELETE_MESSAGE | Discord message when successfully removed older backups | Removed backups older than `old_backup_days` days | "string" | 0.1.1 | +| DISCORD_POST_BACKUP_DELETE_MESSAGE_ENABLED | If the Discord message is enabled for this message | true | true/false | 0.1.1 | +| DISCORD_POST_BACKUP_DELETE_MESSAGE_URL | Discord Webhook URL for this message (if left empty will use DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.1 | +| DISCORD_ERR_BACKUP_DELETE_MESSAGE | Discord message when there has been an error removing older backups | Unable to delete old backups, OLD_BACKUP_DAYS is not an integer. OLD_BACKUP_DAYS=`old_backup_days` | "string" | 0.1.1 | +| DISCORD_ERR_BACKUP_DELETE_MESSAGE_ENABLED | If the Discord message is enabled for this message | true | true/false | 0.1.1 | +| DISCORD_ERR_BACKUP_DELETE_MESSAGE_URL | Discord Webhook URL for this message (if left empty will use DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.1 | +| DISCORD_BROADCAST_MESSAGE_ENABLE | If the Discord message is enabled for broadcast message | true | true/false | 0.1.6 | +| DISCORD_BROADCAST_MESSAGE_URL | Discord Webhook URL for this message (if left empty will use DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.6 | +| DISABLE_GENERATE_SETTINGS | Whether to automatically generate the Game.ini | false | true/false | 0.1.1 | +| ENABLE_PLAYER_LOGGING | Enables Logging and announcing when players join and leave | true | true/false | 0.1.9 | +| PLAYER_LOGGING_POLL_PERIOD | Polling period (in seconds) to check for players who have joined or left | 5 | !0 | 0.1.9 | +| USE_DEPOT_DOWNLOADER | Uses DepotDownloader to download game server files instead of steamcmd. This will help hosts incompatible with steamcmd (e.g. M-series Mac) | false | true/false | 1.0.0 | + +*highly recommended to set + +** Make sure you know what you are doing when running this option enabled + + +
List of Removed + +| Variable | Available Versions | Change/Similar to | +|-----------------------------------------------|-----------------------|---------------------------------------| +| DISCORD_SERVER_INFO_MESSAGE_ENABLE | 0.1.0 | | +| DISCORD_SERVER_INFO_MESSAGE_ENABLED | 0.1.1 ~ 0.1.10 | | +| DISCORD_SERVER_INFO_MESSAGE_WITH_IP | 0.1.0 ~ 0.1.10 | | +| DISCORD_PRE_START_MESSAGE_WITH_GAME_SETTINGS | 0.1.11 ~ 0.4.0 | | +| DISCORD_PRE_START_MESSAGE_WITH_SERVER_IP | 0.1.11 ~ 0.4.0 | | +| DISCORD_PRE_START_MESSAGE_WITH_DOMAIN | 0.1.11 ~ 0.4.0 | | +| BROADCAST_COUNTDOWN_MTIMES | 0.1.6 ~ 0.1.9 | BROADCAST_COUNTDOWN_REMAINING_TIMES | +| ARM_COMPATIBILITY_MODE | 0.1.0 ~ 0.2.0 | ARM64_DEVICE | +| TARGET_COMMIT_ID | 0.1.3 ~ 0.4.0 | TARGET_MANIFEST_ID | + +
### ARM64-exclusive environment variables @@ -320,71 +340,59 @@ For the Box64 configurations, please see the their official documentation for mo > For more specific device compatibility, create an issue on the > [base image repo](https://github.com/sonroyaalmerol/steamcmd-arm64). -| Variable | Info | Default Values | Allowed Values | Added in Version | -|-------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|----------------|---------------------------|------------------| -| BOX64_DYNAREC_STRONGMEM | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_strongmem-)] Enable/Disable simulation of Strong Memory model | 1 | 0, 1, 2, 3 | 0.23.0 | -| BOX64_DYNAREC_BIGBLOCK | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_bigblock-)] Enables/Disables Box64's Dynarec building BigBlock. | 1 | 0, 1, 2, 3 | 0.23.0 | -| BOX64_DYNAREC_SAFEFLAGS | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_safeflags-)] Handling of flags on CALL/RET opcodes | 1 | 0, 1, 2 | 0.23.0 | -| BOX64_DYNAREC_FASTROUND | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_fastround-)] Enable/Disable generation of precise x86 rounding | 1 | 0, 1 | 0.23.0 | -| BOX64_DYNAREC_FASTNAN | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_fastnan-)] Enable/Disable generation of -NAN | 1 | 0, 1 | 0.23.0 | -| BOX64_DYNAREC_X87DOUBLE | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_x87double-)] Force the use of Double for x87 emulation | 0 | 0, 1 | 0.23.0 | -| ARM64_DEVICE | Specify Box64 build to be used based on host device. This setting is only applicable for ARM64 hosts. | generic | generic, m1, rpi5, adlink | 0.39.0 | - -### Removed environment variables - - -
Click to display - -| Variable | Available Versions | Reason | Changed to | -|-------------------------------------|--------------------|---------|----------------------------------------------| -| DISCORD_SERVER_INFO_MESSAGE_ENABLE | 0.1.0 | Typo | DISCORD_PRE_START_MESSAGE_WITH_GAME_SETTINGS | -| DISCORD_SERVER_INFO_MESSAGE_ENABLED | 0.1.1 ~ 0.1.10 | Fixed | DISCORD_PRE_START_MESSAGE_WITH_GAME_SETTINGS | -| DISCORD_SERVER_INFO_MESSAGE_WITH_IP | 0.1.0 ~ 0.1.10 | Fixed | DISCORD_PRE_START_MESSAGE_WITH_SERVER_IP | -| BROADCAST_COUNTDOWN_MTIMES | 0.1.6 ~ 0.1.9 | Fixed | BROADCAST_COUNTDOWN_REMAINING_TIMES | -| ARM_COMPATIBILITY_MODE | 0.1.0 ~ 0.2.0 | Removed | | - -
+| Variable | Info | Default Values | Allowed Values | Added in Version | +|---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------|---------------------------|-------------------| +| BOX64_DYNAREC_STRONGMEM | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_strongmem-)] Enable/Disable simulation of Strong Memory model | 1 | 0, 1, 2, 3 | 0.3.0 | +| BOX64_DYNAREC_BIGBLOCK | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_bigblock-)] Enables/Disables Box64's Dynarec building BigBlock | 1 | 0, 1, 2, 3 | 0.3.0 | +| BOX64_DYNAREC_SAFEFLAGS | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_safeflags-)] Handling of flags on CALL/RET opcodes | 1 | 0, 1, 2 | 0.3.0 | +| BOX64_DYNAREC_FASTROUND | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_fastround-)] Enable/Disable generation of precise x86 rounding | 1 | 0, 1 | 0.3.0 | +| BOX64_DYNAREC_FASTNAN | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_fastnan-)] Enable/Disable generation of -NAN | 1 | 0, 1 | 0.3.0 | +| BOX64_DYNAREC_X87DOUBLE | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_x87double-)] Force the use of Double for x87 emulation | 0 | 0, 1 | 0.3.0 | +| ARM64_DEVICE | Specify Box64 build to be used based on host device. This setting is only applicable for ARM64 hosts | generic | generic, m1, rpi5, adlink | 0.3.0 | ### Game Ports -| Port | Info | -|------|-----------------| -| 7777 | Game Port (UDP) | +| Port | Info | +|-------|-------------------| +| 7777 | Game Port (UDP) | -## Broadcast +## Send a broadcast Used for countdown before automatic updating/Rebooting a server. > [!IMPORTANT] -> Since the game server does not support RCON, in-game broadcasting is not possible, -> so this send it to Discord. +> This send it to Discord, not server > > See [Broadcast on Discord](#broadcast-on-discord) -### Manually Broadcast +### Manually send a broadcast + +> [!TIP] +> Use Hex to use any color you want! -You can broadcast manually using the command: +Broadcast message using the command: ```bash -docker exec longvinter-server broadcast "Message" COLOR +docker exec longvinter-server broadcast "Message" [COLOR|ALIAS|HEX] ``` -List of color: -$\color{#1132D8}Blue$(Default), -$\color{#E8D44F}Yellow$, -$\color{#D85311}Orange$, -$\color{#DF0000}Red$, -$\color{#00CC00}Green$ +Color is used when [sending to Discord](#broadcast-on-discord). (Case-insensitive) -Color is used when sending to Discord. See [Broadcast on Discord](#broadcast-on-discord) +| Color | Alias | Hex | +|---------------------------|---------------|-----------| +| $\color{#1132D8}Blue$* | info | 1132D8 | +| $\color{#E8D44F}Yellow$ | in-progress | E8D44F | +| $\color{#D85311}Orange$ | warn | D85311 | +| $\color{#DF0000}Red$ | failure | DF0000 | +| $\color{#00CC00}Green$ | success | 00CC00 | + +*Default ## Creating a backup > [!WARNING] -> Please confirm when your last save was. -> -> The server will backup the last saved. +> Current point in time is not automatically saved. To create a backup of the game's last save, use the command: @@ -392,14 +400,14 @@ To create a backup of the game's last save, use the command: docker exec longvinter-server backup ``` -This will create a backup at `/data/Longvinter/backups/` +This will create a backup at `/data/backups/` ## Restore from a backup > [!WARNING] -> Please confirm when your last save was. +> Current point in time is not automatically saved. > -> If the recovery fails, it is rolled back to the last storage point. +> If the recovery fails, it is rolled back to the last save point. To restore from a backup, use the command: @@ -411,25 +419,23 @@ docker exec -it longvinter-server restore > If docker restart is not set to policy `always` or `unless-stopped` then the server will shutdown and will need to be > manually restarted. > -> The example docker run command and docker compose file in [How to Use](#how-to-use) already uses the needed policy. +> The example docker run command and docker compose file in [How to Use](#how-to-use) already uses the needed policy ## Manually restore from a backup > [!WARNING] -> Please confirm when your last save was. -> -> It is not automatically saved when you shut down the server. +> It is not automatically saved the server when shutdown the server. -Locate the backup you want to restore in `/data/Longvinter/backups/` and decompress it. +Locate the backup you want to restore in `/data/backups/` and decompress it. Need to stop the server before task. ```bash docker compose down ``` -Delete the old saved data folder located at `data/Longvinter/Saved/`. +Delete the old saved data folder located at `data/Longvinter/Saved/SaveGames`. -Copy the contents of the newly decompressed saved data folder `Saved/` to `data/Longvinter/Saved/`. +Copy the contents of the newly decompressed saved data folder `Saved/SaveGames` to `data/Longvinter/Saved/SaveGames`. Restart the game. (If you are using Docker Compose) @@ -439,6 +445,8 @@ docker compose up -d ## Configuring Automatic Backups with Cron +The server is automatically backed up everynight at midnight according to the timezone set with TZ + Set BACKUP_ENABLED enable or disable automatic backups (Default is enabled) BACKUP_CRON_EXPRESSION is a cron expression, in a Cron-Expression you define an interval for when to run jobs. @@ -449,22 +457,26 @@ BACKUP_CRON_EXPRESSION is a cron expression, in a Cron-Expression you define an > or > [Crontab Generator](https://crontab-generator.org). +Set BACKUP_CRON_EXPRESSION to change the default schedule. Example Usage: If BACKUP_CRON_EXPRESSION to `0 2 * * *`, the backup script will run every day at 2:00 AM. -This is affected by the environment variable TZ value and the default is set to run at midnight every night. ## Configuring Automatic Updates with Cron -To be able to use automatic Updates with this Server the following environment variables have to be set to `true`: +The server is automatically update everyhour according to the timezone set with TZ +(After countdown is stopped and server is saved, start updates.) -- AUTO_UPDATE_ENABLED -- UPDATE_ON_BOOT (default is enabled) +To be able to use automatic Updates with this Server the following environment variables **have** to be set to `true`: + +* UPDATE_ON_BOOT > [!IMPORTANT] > > If docker restart is not set to policy `always` or `unless-stopped` then the server will shutdown and will need to be > manually restarted. > -> The example docker run command and docker compose file in [How to Use](#how-to-use) already uses the needed policy. +> The example docker run command and docker compose file in [How to Use](#how-to-use) already use the needed policy + +Set AUTO_UPDATE_ENABLED enable or disable automatic updates (Default is disabled) AUTO_UPDATE_CRON_EXPRESSION is a cron expression, in a Cron-Expression you define an interval for when to run jobs. @@ -474,19 +486,26 @@ AUTO_UPDATE_CRON_EXPRESSION is a cron expression, in a Cron-Expression you defin > or > [Crontab Generator](https://crontab-generator.org). -Example Usage: If AUTO_UPDATE_CRON_EXPRESSION to `0 2 * * *`, the update script will run every day at 2:00 AM. -This is affected by the environment variable TZ value and the default is set to run at every hour. +Set AUTO_UPDATE_CRON_EXPRESSION to change the default schedule. +Example Usage: If AUTO_UPDATE_CRON_EXPRESSION to `30 * * * *`, the update script will run everyhour at 30 minutes. ## Configuring Automatic Reboots with Cron -Set AUTO_REBOOT_ENABLED enable or disable automatic reboots (Default is disabled) +> [!TIP] +> With CFG_RESTART_TIME_24H, save the server and reboot it. +> But, must be written on a UTC basis. + +The server is automatically reboot everynight at midnight according to the timezone set with TZ +(After countdown is stopped and server is saved, start reboots.) > [!IMPORTANT] > > If docker restart is not set to policy `always` or `unless-stopped` then the server will shutdown and will need to be > manually restarted. > -> The example docker run command and docker compose file in [How to Use](#how-to-use) already uses the needed policy. +> The example docker run command and docker compose file in [How to Use](#how-to-use) already use the needed policy + +Set AUTO_REBOOT_ENABLED enable or disable automatic reboots (Default is disabled) AUTO_REBOOT_CRON_EXPRESSION is a cron expression, in a Cron-Expression you define an interval for when to run jobs. @@ -496,8 +515,8 @@ AUTO_REBOOT_CRON_EXPRESSION is a cron expression, in a Cron-Expression you defin > or > [Crontab Generator](https://crontab-generator.org). -Example Usage: If AUTO_REBOOT_CRON_EXPRESSION to `0 2 * * *`, the reboot script will run every day at 2:00 AM. -This is affected by the environment variable TZ value and the default is set to run at midnight every night. +Set AUTO_REBOOT_CRON_EXPRESSION to change the default schedule. +Example Usage: If AUTO_REBOOT_CRON_EXPRESSION to `0 2 * * *`, the backup script will run every day at 2:00 AM. ## Editing Server Settings @@ -506,48 +525,63 @@ This is affected by the environment variable TZ value and the default is set to > [!IMPORTANT] > > These Environment Variables/Settings are subject to change since the game is still in beta. - -Used with [environment variables](#environment-variables). - -| Variable | Info | Default Value | Allowed Values | -|------------------------------------|---------------------------------------------------------------------------------------|-------------------------------|------------------------------------------------------------------| -| CFG_SERVER_NAME | Sets the name that appears in the server browser. | Unnamed Island | "string" | -| CFG_SERVER_MOTD | Sets the Message of the Day displayed on signs around the island. | Welcome to Longvinter Island! | "string" | -| CFG_MAX_PLAYERS | Sets the maximum number of players that can connect simultaneously. | 32 | 1~ | -| CFG_PASSWORD | Sets a password for the server. | _(empty)_ | "string" | -| CFG_COMMUNITY_WEBSITE | Promotes a website, displayed with the server message and openable in-game. | www\.longvinter\.com | `example.com`, `http://example.com`, `https://example.com/path` | -| CFG_SERVER_TAG | Adds a tag for easier server searching. | None | "string" | -| CFG_COOP_PLAY | Enables or disables cooperative play mode(CFG_ENABLE_PVP must be set to false) | false | true/false | -| CFG_COOP_SPAWN | Sets the cooperative spawn point on the island. | 0 | 0(West), 1(South), 2(East). (I haven't checked it out) | -| CFG_CHECK_VPN | Enables or disables VPN checking for connecting players. | true | true/false | -| CFG_CHEST_RESPAWN_TIME | Sets the maximum respawn time (in seconds) for loot chests. | 600 | ?~ | -| CFG_DISABLE_WANDERING_TRADERS | Disables wandering traders from spawning | false | true/false | -| CFG_SERVER_REGION | Display server in a list of specified country in the server browser | _(empty)_ | AS, NA, SA, EU, OC, AF, AN or nothing | -| CFG_ADMIN_STEAM_ID | Assigns admin privileges to specified EOS IDs. You can get EOS ID from game settings. | _(empty)_ | 0-9, a-f, " "(Space) | -| CFG_ENABLE_PVP | Enables or disables Player versus Player combat. | true | true/false | -| CFG_TENT_DECAY | Enables or disables tent decay to manage abandoned tents. | true | true/false | -| CFG_MAX_TENTS | Sets the maximum number of tents players can place on the server. | 2 | 1~ | -| CFG_HARDCORE | Enables or disables Hardcore mode | false | true/false | -| CFG_MONEY_DROP_MULTIPLIER\* | Sets MK drop multiplier on death | 0.0 | 0.0~1.0 | -| CFG_WEAPON_DAMAGE_MULTIPLIER\* | Sets weapon damage multiplier | 1.0 | 0.0~ | -| CFG_ENERGY_DRAIN_MULTIPLIER\* | Sets energy drain multiplier | 1.0 | 0.0~ | -| CFG_PRICE_FLUCTUATION_MULTIPLIER\* | Sets Items price fluctuation multiplier | 1.0 | 0.0~ | - -\* Applies only in hardcore mode +> Check out the [official webpage for the supported parameters.](https://wiki.longvinter.com/server/configuration#server-configuration) + +Converting server settings to environment variables follow the same principles: + +* all capital letters +* split words by inserting an underscore +* add `CFG_` as a prefix. + +For example: + +* Password -> CFG_PASSWORD +* ServerName -> CFG_SERVER_NAME +* ServerMOTD -> CFG_SERVER_MOTD + +| Variable | Info | Default Value | Allowed Values | +|---------------------------------------|---------------------------------------------------------------------------------------|-------------------------------|-------------------------------------------------------| +| CFG_SERVER_NAME | Sets the name that appears in the server browser | Unnamed Island | String | +| CFG_SERVER_MOTD | Sets the Message of the Day displayed on signs around the island | Welcome to Longvinter Island! | String | +| CFG_MAX_PLAYERS | Sets the maximum number of players that can connect simultaneously | 32 | Integer | +| CFG_PASSWORD | Sets a password for the server | | String | +| CFG_COMMUNITY_WEBSITE | Promotes a website, displayed with the server message and openable in-game | www\.longvinter\.com | String | +| CFG_TAG | Adds a tag for easier server searching | None | String | +| CFG_COOP_PLAY | Enables or disables cooperative play mode(CFG_PVP must be set to false) | false | Boolean | +| CFG_COOP_SPAWN | Sets the cooperative spawn point on the island | 0 | 0~2** | +| CFG_CHECK_VPN | Enables or disables VPN checking for connecting players | true | Boolean | +| CFG_CHEST_RESPAWN_TIME | Sets the maximum respawn time (in seconds) for loot chests | 600 | Integer | +| CFG_DISABLE_WANDERING_TRADERS | Disables wandering traders from spawning | false | Boolean | +| CFG_SERVER_REGION | Display server in a list of specified country in the server browser | | `AS`, `NA`, `SA`, `EU`, `OC`, `AF`, `AN` or nothing | +| CFG_ADMIN_STEAM_ID | Assigns admin privileges to specified EOS IDs. You can get EOS ID from game settings | | Hexadecimal, " "(Space) | +| CFG_PVP | Enables or disables Player versus Player combat | true | Boolean | +| CFG_TENT_DECAY | Enables or disables tent decay to manage abandoned tents | true | Boolean | +| CFG_MAX_TENTS | Sets the maximum number of tents players can place on the server | 2 | Integer | +| CFG_RESTART_TIME_24H | Sets the daily restart time for the server (in 24-hour format) | | Integer | +| CFG_HARDCORE | Enables or disables Hardcore mode | false | Boolean | +| CFG_MONEY_DROP_MULTIPLIER* | Sets MK drop multiplier on death | 0.0 | Float | +| CFG_WEAPON_DAMAGE_MULTIPLIER* | Sets weapon damage multiplier | 1.0 | Float | +| CFG_ENERGY_DRAIN_MULTIPLIER* | Sets energy drain multiplier | 1.0 | Float | +| CFG_PRICE_FLUCTUATION_MULTIPLIER* | Sets Items price fluctuation multiplier | 1.0 | Float | + +*Only in hardcore mode + +** 0(West), 1(South), 2(East). Not sure ### Manually When the server starts, a `Game.ini` file will be created in the following location: `/Longvinter/Saved/Config/LinuxServer/Game.ini`. -By default, the `Game.ini` file consists of the [this environment variables](#with-environment-variables), -but if the DISABLE_GENERATE_SETTINGS value is set to 'true', the file can be modified and set directly. -See [Official Wiki](https://wiki.longvinter.com/server/configuration#server-configuration) +Please keep in mind that the ENV variables will always overwrite the changes made to `Game.ini`. +If you want to modify the file directly, set the value DISABLE_GENERATE_SETTINGS to `true`. > [!IMPORTANT] > Changes can only be made to `Game.ini` while the server is off. > > Any changes made while the server is live will be overwritten when the server stops. +For a more detailed list of server settings go to: [Longvinter Wiki](https://wiki.longvinter.com/server/configuration#server-configuration) + ## Using discord webhooks 1. Generate a webhook url for your discord server in your discord's server settings. @@ -555,7 +589,7 @@ See [Official Wiki](https://wiki.longvinter.com/server/configuration#server-conf Send discord messages with docker run: -```bash +```sh -e DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/1234567890/abcde" \ -e DISCORD_PRE_UPDATE_BOOT_MESSAGE="Server is updating..." \ ``` @@ -563,21 +597,17 @@ Send discord messages with docker run: Send discord messages with docker compose: ```yml -- DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/1234567890/abcde +- DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/1234567890/abcde" - DISCORD_PRE_UPDATE_BOOT_MESSAGE="Server is updating..." ``` ### Broadcast on Discord > [!IMPORTANT] -> -> Since the game server does not support RCON, in-game broadcasting is not possible, -> recommend using this feature. - -Set DISCORD_BROADCAST_MESSAGE_ENABLE enable or disable broadcast on Discord (Default is enabled) (Recommended for use) +> Since the game server does not support RCON/REST API, +> in-game broadcasting is not possible, send broadcast message to Discord -If you use broadcast-only Discord Channel, set the DISCORD_BROADCAST_MESSAGE_URL. -If not set, DISCORD_WEBHOOK_URL will be used. +Set DISCORD_BROADCAST_MESSAGE_ENABLE enable or disable broadcast on Discord (Default is enabled) ## Locking Specific Game Version @@ -586,6 +616,18 @@ If not set, DISCORD_WEBHOOK_URL will be used. > > **Please do so at your own risk!** -If **TARGET_COMMIT_ID** environment variable is set, will lock server version to specific commit. -The Commit ID is a hexadecimal value found on page -and please given at least 4 digits. +If **TARGET_MANIFEST_ID** environment variable is set, will lock server version to specific manifest. +The manifest corresponds to the release date/update versions. Manifests can be found using SteamCMD or websites like [SteamDB](https://steamdb.info/depot/1639882/manifests/). + +### Version To Manifest ID Table + +| Version | Manifest ID | +|-----------|-----------------------| +| 0.10 B | 7723330886973031108 | +| 0.11 R | 876347941046873366 | +| 0.12 B | 7232977979130477635 | +| 0.13 R | 3287206638975838103 | + +## Reporting Issues/Feature Requests + +Issues/Feature requests can be submitted by using [this link](https://github.com/kimzuni/longvinter-docker-server/issues/new/choose). diff --git a/docs/kr/README.md b/docs/kr/README.md index 0840863..e00a0b0 100644 --- a/docs/kr/README.md +++ b/docs/kr/README.md @@ -14,7 +14,7 @@ [English](/docs/en/README.md) | [한국어](/docs/kr/README.md) -[롱빈터](https://store.steampowered.com/app/1635450/Longvinter/) +[롱빈터](https://store.steampowered.com/app/1635450/Longvinter/). 전용 서버를 호스팅할 수 있는 도커 컨테이너입니다. 이 소스 코드는 @@ -23,63 +23,64 @@ [Uuvana-Studios/longvinter-docker-server](https://github.com/Uuvana-Studios/longvinter-docker-server) 저장소를 참고하여 작성되었습니다. -해당 도커 컨테이너는 아래 운영체제에서 테스트되었습니다. +해당 컨테이너는 아래 운영체제에서 정상적으로 작동합니다. -- Windows 11 -- Ubuntu 22.04 +* Windows 11 +* Ubuntu 22.04 -또한 `x64`, `ARM64` 두 아키텍처에서 모두 정상적으로 작동하는 것을 확인했습니다. +해당 컨테이너는 `x64` 및 `ARM64` 기반의 아키텍처에서 정상적으로 작동합니다. > [!WARNING] -> 현재 롱빈터에서 RCON을 지원하지 않기 때문에 관련된 모든 기능이 교체 및 제거되었습니다. +> 게임 서버가 RCON 및 REST API 기능을 지원하지 않아 해당 관련 기능은 모두 교체 및 제거되었습니다. > -> 따라서 서버를 저장하지 않은 채로 서버 종료, 복구 등의 작업을 진행할 경우 -> 약 5분동안 플레이한 내역이 롤백될 수 있음을 알려드립니다. +> 따라서 컨테이너는 서버를 저장할 수 있는 기능이 없기 때문에 +> 서버를 저장하지 않은 채로 일부 기능 사용 시 +> 약 5분간 플레이한 기록이 롤백될 수 있습니다. > (약 5분마다 자동 저장됩니다.) ## 공식 사이트 및 커뮤니티 -- [롱빈터](https://www.longvinter.com/) - - [위키](https://wiki.longvinter.com) - - [X(트위터)](https://twitter.com/longvinter) - - [레딧](https://www.reddit.com/r/Longvinter/) - - [틱톡](https://www.tiktok.com/@longvinter) - - [인스타그램](https://www.instagram.com/longvintergame) - - [서버 가이드 문서](https://docs-server.longvinter.com/) - - [디스코드](https://discord.gg/longvinter) -- [우바나](https://www.uuvana.com/) - - [X(트위터)](https://twitter.com/uuvanastudios) - - [유튜브](https://www.youtube.com/@uuvana) - - [인스타그램](https://www.instagram.com/uuvanastudios/) - - [이미지 및 로고](https://longvinter.com/press) - - [포럼](https://forum.uuvana.com/) - - ~~[FAQ(자주 묻는 질문)](https://contact.uuvana.com/)~~ +* [롱빈터](https://www.longvinter.com/) + * [위키](https://wiki.longvinter.com) + * [X(트위터)](https://twitter.com/longvinter) + * [레딧](https://www.reddit.com/r/Longvinter/) + * [틱톡](https://www.tiktok.com/@longvinter) + * [인스타그램](https://www.instagram.com/longvintergame) + * [서버 가이드 문서](https://docs-server.longvinter.com/) + * [디스코드](https://discord.gg/longvinter) +* [우바나](https://www.uuvana.com/) + * [X(트위터)](https://twitter.com/uuvanastudios) + * [유튜브](https://www.youtube.com/@uuvana) + * [인스타그램](https://www.instagram.com/uuvanastudios/) + * [이미지 및 로고](https://longvinter.com/press) + * [포럼](https://forum.uuvana.com/) + * ~~[FAQ(자주 묻는 질문)](https://contact.uuvana.com/)~~ ## 서버 요구사항 -> - OS(운영체제): 최소 64비트 -> - RAM(램): 최소 2GB +* OS: 64비트 이상 +* RAM: 2GB 이상 출처: ## 사용법 -[환경 변수](#환경-변수)를 설정할 수 있습니다. +먼저 [환경 변수](#환경-변수)를 변경해야 합니다. -서버를 실행한 후 `docker log longvinter-server` 명령어로 서버 로그를 확인할 수 있습니다. +서버를 실행한 후 `docker logs longvinter-server` 명령어로 서버 로그를 확인할 수 있습니다. 실시간으로 확인하려면 마지막에 `-f`를 추가해 주세요. ### Docker Compose -아래는 서버 설정에 필요한 [docker-compose.yml](/docker-compose.yml) 예시 파일에서 TZ(타임존) 값을 한국 시간대로 수정한 내용입니다. +아래는 서버 설정에 필요한 [docker-compose.yml](/docker-compose.yml) 예제 파일입니다. 서버를 실행하려면 해당 파일을 먼저 작성한 후 파일이 위치한 디렉토리에서 `docker compose up -d` 명령어를 실행해야 합니다. -```yaml +```yml services: - longvinter-server: - container_name: longvinter-server + longvinter: image: kimzuni/longvinter-docker-server:latest restart: unless-stopped + container_name: longvinter-server stop_grace_period: 30s # Set to however long you are willing to wait for the container to gracefully stop logging: driver: json-file @@ -89,7 +90,7 @@ services: ports: - "7777:7777/udp" environment: - TZ: "Asia/Seoul" + TZ: "UTC" PUID: 1000 PGID: 1000 PORT: 7777 # Optional but recommended @@ -100,25 +101,25 @@ services: CFG_COMMUNITY_WEBSITE: "www.longvinter.com" CFG_COOP_PLAY: false CFG_COOP_SPAWN: 0 - CFG_SERVER_TAG: "none" + CFG_TAG: "none" CFG_ADMIN_STEAM_ID: "" - CFG_ENABLE_PVP: true + CFG_PVP: true CFG_TENT_DECAY: true CFG_MAX_TENTS: 2 volumes: - ./data:/data ``` -위 방법 대신 [.env.example](/.env.example) 파일을 **.env** 파일로 복사한 후 내용을 수정하여 사용할 수도 있습니다. -[환경 변수](#환경-변수)를 참고하여 해당 파일을 필요에 맞게 설정해 주세요. -이 경우 [docker-compose.yml](/docker-compose.yml) 파일은 아래와 같이 수정해야 합니다. +또는 [.env.example](/.env.example) 파일을 **.env** 파일로 복사하여 사용할 수도 있습니다. +[환경 변수](#환경-변수) 부분을 참고하여 파일 내용을 필요에 맞게 수정해 주세요. +그 다음 [docker-compose.yml](/docker-compose.yml) 내용을 아래와 같이 수정해야 합니다. ```yml services: - longvinter-server: - container_name: longvinter-server + longvinter: image: kimzuni/longvinter-docker-server:latest restart: unless-stopped + container_name: longvinter-server stop_grace_period: 30s # Set to however long you are willing to wait for the container to gracefully stop logging: driver: json-file @@ -135,14 +136,15 @@ services: ### Docker Run -`docker compose` 대신 `docker run` 명령어를 사용할 수도 있습니다. 아래 명령어 실행 시 바로 서버가 실행됩니다. +`docker compose` 대신 `docker run` 명령어를 사용할 수도 있습니다. +아래 명령어를 실행하는 즉시 컨테이너가 생성됩니다. ```bash docker run -d \ --name longvinter-server \ -p 7777:7777/udp \ -v ./data:/data/ \ - -e TZ="Asia/Seoul" \ + -e TZ="UTC" \ -e PUID=1000 \ -e PGID=1000 \ -e PORT=7777 \ @@ -153,9 +155,9 @@ docker run -d \ -e CFG_COMMUNITY_WEBSITE="www.longvinter.com" \ -e CFG_COOP_PLAY=false \ -e CFG_COOP_SPAWN=0 \ - -e CFG_SERVER_TAG="none" \ + -e CFG_TAG="none" \ -e CFG_ADMIN_STEAM_ID="" \ - -e CFG_ENABLE_PVP=true \ + -e CFG_PVP=true \ -e CFG_TENT_DECAY=true \ -e CFG_MAX_TENTS=2 \ --restart unless-stopped \ @@ -180,137 +182,155 @@ docker run -d \ ### 컨테이너 업데이트 방법 -먼저 서버를 실행 중이라면 아래 명령어로 서버를 중지해 주세요. +컨테이너 버전을 업데이트하려면 먼저 서버를 중지합니다. ```bash -docker stop longvinter-server -docker rm longvinter-server +docker compose down ``` -그리고 아래 명령어를 실행햐여 설치된 이미지를 제거합니다. +그리고 설치된 이미지를 제거합니다. ```bash docker rmi $(docker images | grep -E ^"(ghcr.io\/)?kimzuni/longvinter-docker-server" | awk '{print $3}') ``` -마지막으로 `latest` 태그를 이용하여 [Docker Compose](#docker-compose) 또는 [Docker Run](#docker-run)을 실행하면 최신 버전의 컨테이너를 사용할 수 있습니다. +마지막으로 `latest` 태그를 이용하여 [Docker Compose](#docker-compose) 또는 [Docker Run](#docker-run)을 실행합니다. ### root 없이 실행하기 -고급 유저를 위한 기능입니다. +고급 사용자에게만 해당됩니다. -컨테이너를 실행할 때 해당 이미지의 +컨테이너를 실행할 때 해당 이미지의 루트인 [기본 사용자를 재정의](https://docs.docker.com/engine/reference/run/#user)할 수 있습니다. -이때 설정한 환경 변수 `PUID` 및 `PGID`의 값은 무시됩니다. +이때 환경 변수 `PUID` 및 `PGID`의 값은 무시됩니다. -현재 사용자의 UID는 `id -u` 명령어로 확인할 수 있습니다. -현재 사용자의 GID는 `id -g` 명령어로 확인할 수 있습니다. +`id -u` 명령어로 현재 사용자의 UID를 확인할 수 있습니다. +`id -g` 명령어로 현재 사용자의 GID를 확인할 수 있습니다. -사용자 및 그룹을 설정하려면 `NUMBERICAL_UID:NUMBERICAL_GID`와 같이 사용해야 합니다. +사용자 및 그룹을 설정하려면 `NUMBERICAL_UID:NUMBERICAL_GID`로 설정해야 합니다. 아래는 UID가 1000, GID가 1001이라고 가정합니다. -- [Docker Run](#docker-run)를 사용할 경우 마지막 줄 위에 `--user 1000:1001`을 추가해야 합니다. -- [Docker Compose](#docker-compose)를 사용할 경우 restart 아래에 `user: 1000:1001`을 추가해야 합니다. +* [Docker Run](#docker-run)의 경우 마지막 줄 위에 `--user 1000:1001 \`을 추가해야 합니다. +* [Docker Compose](#docker-compose)의 경우 restart 아래에 `user: 1000:1001`을 추가해야 합니다. -만약 현재 사용자의 UID/GID와 다른 UID/GID 값을 사용하려면 바인딩되는 디렉토리의 소유권을 변경해야 합니다. +만약 현재 사용자와 다른 UID/GID 값을 사용하려면 바인딩되는 디렉토리의 소유권을 변경해야 합니다. `chown UID:GID data/`명령어를 실행하여 소유권을 변경하거나 -`chmod o=rwx data/`를 실행하여 모든 사용자가 접근할 수 있도록 해주세요. +`chmod o=rwx data/`를 실행하여 모든 사용자가 접근할 수 있도록 합니다. ## 환경 변수 -아래 값들을 사용하여 서버의 설정을 변경할 수 있습니다. -서버를 실행하기 전에 값을 설정해야 적용됩니다. - -| 변수명 | 설명 | 기본값 | 설정 가능한 값 | 추가된 버전 | -|--------------------------------------------|---------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------|-----------| -| TZ | Cron 및 게임 서버에 사용되는 시간대 설정 (로그 파일에는 적용되지 않음) | UTC | [TZ Identifiers](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#Time_Zone_abbreviations) 참고 | 0.1.0 | -| PUID\* | 지정한 값을 가진 UID로 서버 실행 | 1000 | !0 | 0.1.0 | -| PGID\* | 지정한 값을 가진 GID로 서버 실행 | 1000 | !0 | 0.1.0 | -| PORT\* | 서버 게임 포트 번호 | 7777 | 1024-65535 | 0.1.0 | -| UPDATE_ON_BOOT\*\* | 서버 시작 시 자동으로 서버 업데이트 진행 | true | true/false | 0.1.0 | -| BACKUP_ENABLED | 자동 백업 할성화 | true | true/false | 0.1.1 | -| BACKUP_CRON_EXPRESSION | 자동 백업 빈도 설정 | 0 0 \* \* \* | 크론식 표현 - [Cron으로 자동 백업 설정하는 방법](#cron으로-자동-백업-설정하는-방법) 참고 바람 | 0.1.1 | -| DELETE_OLD_BACKUPS | 자동 백업 시 오래된 백업 파일 자동 삭제 | false | true/false | 0.1.1 | -| OLD_BACKUP_DAYS | 백업 파일 보관 일수 | 30 | !0 | 0.1.1 | -| AUTO_UPDATE_ENABLED | 자동 업데이트 활성화 | false | true/false | 0.1.4 | -| AUTO_UPDATE_CRON_EXPRESSION | 자동 업데이트 빈도 설정 | 0 \* \* \* \* | 크론식 표현 - [Cron으로 자동 업데이트 설정하는 방법](#cron으로-자동-업데이트-설정하는-방법) 참고 바람 | 0.1.4 | -| AUTO_UPDATE_WARN_MINUTES | 플레이어에게 알림 전송 후 서버를 업데이트할 때까지 기다리는 시간(분) | 15 | !0 | 0.1.4 | -| AUTO_UPDATE_WARN_MESSAGE | 플레이어에게 남은 시간을 알리기 위해 전송되는 메시지 | Server will update in `remaining_time` minutes. | "string" | 0.1.10 | -| AUTO_UPDATE_WARN_REMAINING_TIMES | 카운트다운 중 남은 시간이 이 값에 포함되어 있을 경우에만 플레이어에게 알림 | 1 5 10 | !0 and " "(Space) | 0.1.6 | -| AUTO_REBOOT_ENABLED | 자동 재부팅 활성화 | false | true/false | 0.1.10 | -| AUTO_REBOOT_CRON_EXPRESSION | 자동 재부팅 빈도 설정 | 0 0 \* \* \* | 크론식 표현 - [Cron으로 자동 재부팅 설정하는 방법](#cron으로-자동-재부팅-설정하는-방법) 참고 바람 | 0.1.10 | -| AUTO_REBOOT_WARN_MINUTES | 플레이어에게 알림 전송 후 서버를 재부팅할 때까지 기다리는 시간(분) | 15 | !0 | 0.1.4 | -| AUTO_REBOOT_WARN_MESSAGE | 플레이어에게 남은 시간을 알리기 위해 전송되는 메시지 | Server will update in `remaining_time` minutes. | "string" | 0.1.10 | -| AUTO_REBOOT_WARN_REMAINING_TIMES | 카운트다운 중 남은 시간이 이 값에 포함되어 있을 경우에만 플레이어에게 알림 | 1 5 10 | !0 and " "(Space) | 0.1.6 | -| AUTO_REBOOT_EVEN_IF_PLAYERS_ONLINE | 플레이어가 있을 경우에도 자동 재부팅 진행 | false | true/false | 0.1.10 | -| BROADCAST_COUNTDOWN_SUSPEND_MESSAGE | 플레이어가 없어 카운트다운이 중단된 경우 브로드캐스트할 메시지 | Suspends countdown because there are no players. | "string" | 0.1.10 | -| BROADCAST_COUNTDOWN_SUSPEND_MESSAGE_ENABLE | 이 값이 `true`인 경우에만 해당 메시지 전송 | true | true/false | 0.1.10 | -| TARGET_COMMIT_ID | 게임 서버를 지정한 Commit ID를 가진 버전으로 설치 및 실행 | _(empty)_ | [특정 게임 버전으로 고정](#특정-게임-버전으로-고정) 참고 | 0.1.3 | -| DISCORD_WEBHOOK_URL | 디스코드 서버에서 생성한 웹훅 URL | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.0 | -| DISCORD_SUPPRESS_NOTIFICATIONS | 디스코드 메시지 전송 시 멤버들에게 알림을 보내지 않음 | false | true/false | 0.1.0 | -| DISCORD_CONNECT_TIMEOUT | 지정한 시간동안 디스코드 웹훅에 연결할 수 없을 경우 연결 취소 | 30 | !0 | 0.1.0 | -| DISCORD_MAX_TIMEOUT | 지정한 시간동안 디스코드 메시지가 전송되지 않으면 강제 종료 | 30 | !0 | 0.1.0 | -| DISCORD_PRE_INSTALL_MESSAGE | 서버 설치 전 전송되는 디스코드 메시지 | Server is installing... | "string" | 0.1.0 | -| DISCORD_PRE_INSTALL_MESSAGE_ENABLED | 이 값이 `true`인 경우에만 해당 메시지 전송 | true | true/false | 0.1.0 | -| DISCORD_PRE_INSTALL_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (이 값을 비워둘 경우 DISCORD_WEBHOOK_URL 사용) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.0 | -| DISCORD_POST_INSTALL_MESSAGE | 서버 설치 후 전송되는 디스코드 메시지 | Server install complete! | "string" | 0.1.2 | -| DISCORD_POST_INSTALL_MESSAGE_ENABLED | 이 값이 `true`인 경우에만 해당 메시지 전송 | true | true/false | 0.1.2 | -| DISCORD_POST_INSTALL_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (이 값을 비워둘 경우 DISCORD_WEBHOOK_URL 사용) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.2 | -| DISCORD_PRE_UPDATE_BOOT_MESSAGE | 서버 업데이트 전 전송되는 디스코드 메시지 | Server is updating... | "string" | 0.1.0 | -| DISCORD_PRE_UPDATE_BOOT_MESSAGE_ENABLED | 이 값이 `true`인 경우에만 해당 메시지 전송 | true | true/false | 0.1.0 | -| DISCORD_PRE_UPDATE_BOOT_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (이 값을 비워둘 경우 DISCORD_WEBHOOK_URL 사용) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.0 | -| DISCORD_POST_UPDATE_BOOT_MESSAGE | 서버 업데이트 후 전송되는 디스코드 메시지 | Server update complete! | "string" | 0.1.2 | -| DISCORD_POST_UPDATE_BOOT_MESSAGE_ENABLED | 이 값이 `true`인 경우에만 해당 메시지 전송 | true | true/false | 0.1.2 | -| DISCORD_POST_UPDATE_BOOT_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (이 값을 비워둘 경우 DISCORD_WEBHOOK_URL 사용) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.2 | -| DISCORD_PRE_START_MESSAGE | 서버 시작 시 전송되는 디스코드 메시지 | Server has been started! | "string" | 0.1.0 | -| DISCORD_PRE_START_MESSAGE_ENABLED | 이 값이 `true`인 경우에만 해당 메시지 전송 | true | true/false | 0.1.0 | -| DISCORD_PRE_START_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (이 값을 비워둘 경우 DISCORD_WEBHOOK_URL 사용) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.0 | -| DISCORD_PRE_START_MESSAGE_WITH_SERVER_INFO | 서버 시작 메시지 전송 시 서버 설정 내용을 같이 전송 | true | true/false | 0.1.1 | -| DISCORD_PRE_START_MESSAGE_WITH_SERVER_IP | 서버 시작 메시지 전송 시 서버 IP 및 포트 번호를 같이 전송 | false | true/false | 0.1.0 | -| DISCORD_PRE_START_MESSAGE_WITH_DOMAIN | 서버 시작 메시지 전송 시 도메인 및 포트 번호를 같이 전송 (DISCORD_PRE_START_MESSAGE_WITH_IP 값이 무시됨) | _(empty)_ | `example.com`, `http://example.com`, `https://example.com` | 0.1.11 | -| DISCORD_PRE_SHUTDOWN_MESSAGE | 서버 종료 전 전송되는 디스코드 메시지 | Server is shutting down... | "string" | 0.1.0 | -| DISCORD_PRE_SHUTDOWN_MESSAGE_ENABLED | 이 값이 `true`인 경우에만 해당 메시지 전송 | true | true/false | 0.1.0 | -| DISCORD_PRE_SHUTDOWN_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (이 값을 비워둘 경우 DISCORD_WEBHOOK_URL 사용) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.0 | -| DISCORD_POST_SHUTDOWN_MESSAGE | 서버 종료 후 전송되는 디스코드 메시지 | Server is stopped! | "string" | 0.1.0 | -| DISCORD_POST_SHUTDOWN_MESSAGE_ENABLED | 이 값이 `true`인 경우에만 해당 메시지 전송 | true | true/false | 0.1.0 | -| DISCORD_POST_SHUTDOWN_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (이 값을 비워둘 경우 DISCORD_WEBHOOK_URL 사용) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.0 | -| DISCORD_PLAYER_JOIN_MESSAGE | 플레이어가 서버에 접속할 때 전송되는 디스코드 메시지 | `player_name` has joined! | "string" | 0.1.9 | -| DISCORD_PLAYER_JOIN_MESSAGE_ENABLED | 이 값이 `true`인 경우에만 해당 메시지 전송 | true | true/false | 0.1.9 | -| DISCORD_PLAYER_JOIN_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (이 값을 비워둘 경우 DISCORD_WEBHOOK_URL 사용) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.9 | -| DISCORD_PLAYER_LEAVE_MESSAGE | 플레이어가 서버에서 나갈 때 전송되는 디스코드 메시지 | `player_name` has left. | "string" | 0.1.9 | -| DISCORD_PLAYER_LEAVE_MESSAGE_ENABLED | 이 값이 `true`인 경우에만 해당 메시지 전송 | true | true/false | 0.1.9 | -| DISCORD_PLAYER_LEAVE_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (이 값을 비워둘 경우 DISCORD_WEBHOOK_URL 사용) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.9 | -| DISCORD_PRE_BACKUP_MESSAGE | 백업 시작 전 전송되는 메시지 | Creating backup... | "string" | 0.1.1 | -| DISCORD_PRE_BACKUP_MESSAGE_ENABLED | 이 값이 `true`인 경우에만 해당 메시지 전송 | true | true/false | 0.1.1 | -| DISCORD_PRE_BACKUP_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (이 값을 비워둘 경우 DISCORD_WEBHOOK_URL 사용) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.1 | -| DISCORD_POST_BACKUP_MESSAGE | 백업 완료 후 전송되는 메시지 | Backup created at `file_path` | "string" | 0.1.1 | -| DISCORD_POST_BACKUP_MESSAGE_ENABLED | 이 값이 `true`인 경우에만 해당 메시지 전송 | true | true/false | 0.1.1 | -| DISCORD_POST_BACKUP_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (이 값을 비워둘 경우 DISCORD_WEBHOOK_URL 사용) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.1 | -| DISCORD_PRE_BACKUP_DELETE_MESSAGE | 오래된 백업 파일 삭제 전 전송되는 메시지 | Removing backups older than `old_backup_days` days | "string" | 0.1.1 | -| DISCORD_PRE_BACKUP_DELETE_MESSAGE_ENABLED | 이 값이 `true`인 경우에만 해당 메시지 전송 | true | true/false | 0.1.1 | -| DISCORD_PRE_BACKUP_DELETE_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (이 값을 비워둘 경우 DISCORD_WEBHOOK_URL 사용) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.1 | -| DISCORD_POST_BACKUP_DELETE_MESSAGE | 오래된 백업 파일 삭제 완료 후 전송되는 메시지 | Removed backups older than `old_backup_days` days | "string" | 0.1.1 | -| DISCORD_POST_BACKUP_DELETE_MESSAGE_ENABLED | 이 값이 `true`인 경우에만 해당 메시지 전송 | true | true/false | 0.1.1 | -| DISCORD_POST_BACKUP_DELETE_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (이 값을 비워둘 경우 DISCORD_WEBHOOK_URL 사용) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.1 | -| DISCORD_ERR_BACKUP_DELETE_MESSAGE | 오래된 백업 파일 삭제 실패 시 전송되는 메시지 | Unable to delete old backups, OLD_BACKUP_DAYS is not an integer. OLD_BACKUP_DAYS=`old_backup_days` | "string" | 0.1.1 | -| DISCORD_ERR_BACKUP_DELETE_MESSAGE_ENABLED | 이 값이 `true`인 경우에만 해당 메시지 전송 | true | true/false | 0.1.1 | -| DISCORD_ERR_BACKUP_DELETE_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (이 값을 비워둘 경우 DISCORD_WEBHOOK_URL 사용) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.1 | -| DISCORD_BROADCAST_MESSAGE_ENABLE\*\* | 이 값이 `true`인 경우 브로드캐스트 메시지를 디스코드로 전송 | true | true/false | 0.1.6 | -| DISCORD_BROADCAST_MESSAGE_URL\* | 해당 메시지를 보낼 디스코드 웹훅 URL (이 값을 비워둘 경우 DISCORD_WEBHOOK_URL 사용) | _(empty)_ | `https://discord.com/api/webhooks/` | 0.1.6 | -| DISABLE_GENERATE_SETTINGS | 서버 설정 파일 `Game.ini`에 적용되는 모든 환경 변수 설정 무시 및 기본 값으로 설정 | false | true/false | 0.1.1 | -| ENABLE_PLAYER_LOGGING | 플레이어가 서버에 접속하거나 나갈 때 알림 활성화 여부 | true | true/false | 0.1.9 | -| PLAYER_LOGGING_POLL_PERIOD | 지정한 초마다 플레이어 접속 및 퇴장 체크 | 5 | !0 | 0.1.9 | - -\* 설정 권장사항 - -\*\* 기본 값 사용 권장 - -### ARM64 전용 환경변수 - -ARM64 호스트는 아래 변수를 사용하여 서버 설정을 조정할 수 있습니다. -서버 안정성 및 성능 향상을 위한 관련 설정이 포함되어 있습니다. +아래 값들을 사용하여 컨테이너의 설정을 변경할 수 있습니다. +컨테이너를 실행하기 전에 값을 설정해야 적용됩니다. + +* PUID +* PGID +* PORT + +| 변수명 | 설명 | 기본값 | 설정 가능한 값 | 추가된 버전 | +|-----------------------------------------------|---------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------|---------------| +| TZ | 컨테이너 타임존 설정 | UTC | [TZ Identifiers](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#Time_Zone_abbreviations) 참고 | 0.1.0 | +| PUID* | 서버를 실행할 UID 지정 | 1000 | !0 | 0.1.0 | +| PGID* | 서버를 실행할 GID 지정 | 1000 | !0 | 0.1.0 | +| PORT* | 게임 서버 연결 포트 (UDP) | 7777 | 1024-65535 | 0.1.0 | +| UPDATE_ON_BOOT** | 컨테이너를 시작할 때 서버 업데이트 진행 | true | true/false | 0.1.0 | +| BACKUP_ENABLED | 자동 백업 사용 | true | true/false | 0.1.1 | +| BACKUP_CRON_EXPRESSION | 자동 백업 빈도 설정 | 0 0 \* \* \* | 크론식 표현 - [Cron으로 자동 백업 설정하는 방법](#cron으로-자동-백업-설정하는-방법) 참고 바람 | 0.1.1 | +| DELETE_OLD_BACKUPS | 오래된 백업 파일 삭제 | false | true/false | 0.1.1 | +| OLD_BACKUP_DAYS | 백업 파일 보관 일수 | 30 | !0 | 0.1.1 | +| AUTO_UPDATE_ENABLED | 자동 업데이트 사용 | false | true/false | 0.1.4 | +| AUTO_UPDATE_CRON_EXPRESSION | 자동 업데이트 빈도 설정 | 0 \* \* \* \* | 크론식 표현 - [Cron으로 자동 업데이트 설정하는 방법](#cron으로-자동-업데이트-설정하는-방법) 참고 바람 | 0.1.4 | +| AUTO_UPDATE_WARN_MINUTES | 플레이어에게 알림 전송 후 서버 저장 및 업데이트할 때까지 기다리는 시간 (플레이어가 없는 경우 무시) | 15 | !0 | 0.1.4 | +| AUTO_UPDATE_WARN_MESSAGE | 서버 업데이트를 위한 카운트다운 시 전송할 브로드캐스트 메시지 | Server will update in `remaining_time` minutes. | "string" | 0.1.10 | +| AUTO_UPDATE_WARN_REMAINING_TIMES | 서버 업데이트를 위한 카운트다운을 플레이어에게 브로드캐스트하는 시간 | 1 5 10 | !0 and " "(Space) | 0.1.6 | +| AUTO_REBOOT_ENABLED | 자동 재부팅 사용 | false | true/false | 0.1.10 | +| AUTO_REBOOT_CRON_EXPRESSION | 자동 재부팅 빈도 설정 | 0 0 \* \* \* | 크론식 표현 - [Cron으로 자동 재부팅 설정하는 방법](#cron으로-자동-재부팅-설정하는-방법) 참고 바람 | 0.1.10 | +| AUTO_REBOOT_WARN_MINUTES | 플레이어에게 알림 전송 후 서버 저장 및 재부팅할 때까지 기다리는 시간 (플레이어가 없는 경우 무시) | 15 | !0 | 0.1.4 | +| AUTO_REBOOT_WARN_MESSAGE | 서버 재부팅을 위한 카운트다운 시 전송할 브로드캐스트 메시지 | Server will update in `remaining_time` minutes. | "string" | 0.1.10 | +| AUTO_REBOOT_WARN_REMAINING_TIMES | 서버 재부팅 위한 카운트다운을 플레이어에게 브로드캐스트하는 시간 | 1 5 10 | !0 and " "(Space) | 0.1.6 | +| AUTO_REBOOT_EVEN_IF_PLAYERS_ONLINE | 플레이어가 있는 경우에도 재부팅 진행 | false | true/false | 0.1.10 | +| BROADCAST_COUNTDOWN_SUSPEND_MESSAGE | 플레이어가 없어 카운트다운이 중단된 경우 보내는 디스코드 메시지 | Suspends countdown because there are no players. | "string" | 0.1.10 | +| BROADCAST_COUNTDOWN_SUSPEND_MESSAGE_ENABLE | 해당 디스코드 메시지 활성화 | true | true/false | 0.1.10 | +| TARGET_MANIFEST_ID | Steam Download Depot의 Manifest ID로 특정 게임 버전으로 고정 | | [특정 게임 버전으로 고정](#특정-게임-버전으로-고정) 참고 | 1.0.0 | +| DISCORD_WEBHOOK_URL | 디스코드 서버에서 생성한 웹훅 URL | | `https://discord.com/api/webhooks/` | 0.1.0 | +| DISCORD_SUPPRESS_NOTIFICATIONS | 디스코드 메시지를 `@silent` 메시지로 전송 | false | true/false | 0.1.0 | +| DISCORD_CONNECT_TIMEOUT | 디스코드 웹훅 연결 시간 제한 | 30 | !0 | 0.1.0 | +| DISCORD_MAX_TIMEOUT | 디스코드 웹훅 실행 총 시간 제한 | 30 | !0 | 0.1.0 | +| DISCORD_PRE_INSTALL_MESSAGE | 서버 설치를 시작하기 전 보내는 디스코드 메시지 | Server is installing... | "string" | 0.1.0 | +| DISCORD_PRE_INSTALL_MESSAGE_ENABLED | 해당 디스코드 메시지 활성화 | true | true/false | 0.1.0 | +| DISCORD_PRE_INSTALL_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (기본값: DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.0 | +| DISCORD_POST_INSTALL_MESSAGE | 서버 설치가 완료된 후 보내는 디스코드 메시지 | Server install complete! | "string" | 0.1.2 | +| DISCORD_POST_INSTALL_MESSAGE_ENABLED | 해당 디스코드 메시지 활성화 | true | true/false | 0.1.2 | +| DISCORD_POST_INSTALL_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (기본값: DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.2 | +| DISCORD_PRE_UPDATE_BOOT_MESSAGE | 서버 업데이트를 시작하기 전 보내는 디스코드 메시지 | Server is updating... | "string" | 0.1.0 | +| DISCORD_PRE_UPDATE_BOOT_MESSAGE_ENABLED | 해당 디스코드 메시지 활성화 | true | true/false | 0.1.0 | +| DISCORD_PRE_UPDATE_BOOT_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (기본값: DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.0 | +| DISCORD_POST_UPDATE_BOOT_MESSAGE | 서버 업데이트가 완료된 후 보내는 디스코드 메시지 | Server update complete! | "string" | 0.1.2 | +| DISCORD_POST_UPDATE_BOOT_MESSAGE_ENABLED | 해당 디스코드 메시지 활성화 | true | true/false | 0.1.2 | +| DISCORD_POST_UPDATE_BOOT_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (기본값: DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.2 | +| DISCORD_PRE_START_MESSAGE | 서버를 시작할 때 보내는 디스코드 메시지 | Server has been started! | "string" | 0.1.0 | +| DISCORD_PRE_START_MESSAGE_ENABLED | 해당 디스코드 메시지 활성화 | true | true/false | 0.1.0 | +| DISCORD_PRE_START_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (기본값: DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.0 | +| DISCORD_PRE_SHUTDOWN_MESSAGE | 서버를 종료하기 전 보내는 디스코드 메시지 | Server is shutting down... | "string" | 0.1.0 | +| DISCORD_PRE_SHUTDOWN_MESSAGE_ENABLED | 해당 디스코드 메시지 활성화 | true | true/false | 0.1.0 | +| DISCORD_PRE_SHUTDOWN_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (기본값: DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.0 | +| DISCORD_POST_SHUTDOWN_MESSAGE | 서버가 종료된 후 보내는 디스코드 메시지 | Server is stopped! | "string" | 0.1.0 | +| DISCORD_POST_SHUTDOWN_MESSAGE_ENABLED | 해당 디스코드 메시지 활성화 | true | true/false | 0.1.0 | +| DISCORD_POST_SHUTDOWN_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (기본값: DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.0 | +| DISCORD_PLAYER_JOIN_MESSAGE | 플레이어가 서버에 접속할 때 보내는 디스코드 메시지 | `player_name` has joined! | "string" | 0.1.9 | +| DISCORD_PLAYER_JOIN_MESSAGE_ENABLED | 해당 디스코드 메시지 활성화 | true | true/false | 0.1.9 | +| DISCORD_PLAYER_JOIN_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (기본값: DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.9 | +| DISCORD_PLAYER_LEAVE_MESSAGE | 플레이어가 서버에서 나갈 때 보내는 디스코드 메시지 | `player_name` has left. | "string" | 0.1.9 | +| DISCORD_PLAYER_LEAVE_MESSAGE_ENABLED | 해당 디스코드 메시지 활성화 | true | true/false | 0.1.9 | +| DISCORD_PLAYER_LEAVE_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (기본값: DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.9 | +| DISCORD_PRE_BACKUP_MESSAGE | 백업을 시작하기 전 보내는 디스코드 메시지 | Creating backup... | "string" | 0.1.1 | +| DISCORD_PRE_BACKUP_MESSAGE_ENABLED | 해당 디스코드 메시지 활성화 | true | true/false | 0.1.1 | +| DISCORD_PRE_BACKUP_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (기본값: DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.1 | +| DISCORD_POST_BACKUP_MESSAGE | 백업을 완료된 후 보내는 디스코드 메시지 | Backup created at `file_path` | "string" | 0.1.1 | +| DISCORD_POST_BACKUP_MESSAGE_ENABLED | 해당 디스코드 메시지 활성화 | true | true/false | 0.1.1 | +| DISCORD_POST_BACKUP_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (기본값: DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.1 | +| DISCORD_PRE_BACKUP_DELETE_MESSAGE | 오래된 백업 파일을 삭제하기 전 보내는 디스코드 메시지 | Removing backups older than `old_backup_days` days | "string" | 0.1.1 | +| DISCORD_PRE_BACKUP_DELETE_MESSAGE_ENABLED | 해당 디스코드 메시지 활성화 | true | true/false | 0.1.1 | +| DISCORD_PRE_BACKUP_DELETE_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (기본값: DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.1 | +| DISCORD_POST_BACKUP_DELETE_MESSAGE | 오래된 백업 파일 삭제가 정상적으로 완료된 후 보내는 디스코드 메시지 | Removed backups older than `old_backup_days` days | "string" | 0.1.1 | +| DISCORD_POST_BACKUP_DELETE_MESSAGE_ENABLED | 해당 디스코드 메시지 활성화 | true | true/false | 0.1.1 | +| DISCORD_POST_BACKUP_DELETE_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (기본값: DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.1 | +| DISCORD_ERR_BACKUP_DELETE_MESSAGE | 오래된 백업 파일 삭제 중 오류가 발생했을 때 보내는 디스코드 메시지 | Unable to delete old backups, OLD_BACKUP_DAYS is not an integer. OLD_BACKUP_DAYS=`old_backup_days` | "string" | 0.1.1 | +| DISCORD_ERR_BACKUP_DELETE_MESSAGE_ENABLED | 해당 디스코드 메시지 활성화 | true | true/false | 0.1.1 | +| DISCORD_ERR_BACKUP_DELETE_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (기본값: DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.1 | +| DISCORD_BROADCAST_MESSAGE_ENABLE | 디스코드 서버에 브로드캐스트 메시지 전송 | true | true/false | 0.1.6 | +| DISCORD_BROADCAST_MESSAGE_URL | 해당 메시지를 보낼 디스코드 웹훅 URL (기본값: DISCORD_WEBHOOK_URL) | | `https://discord.com/api/webhooks/` | 0.1.6 | +| DISABLE_GENERATE_SETTINGS | `Game.ini` 자동 생성 비활성화 | false | true/false | 0.1.1 | +| ENABLE_PLAYER_LOGGING | 플레이어가 서버에 접속하거나 나가는 것을 기록 | true | true/false | 0.1.9 | +| PLAYER_LOGGING_POLL_PERIOD | 플레이어 로깅 주기(초) | 5 | !0 | 0.1.9 | +| USE_DEPOT_DOWNLOADER | steamcmd 대신 DepotDownloader를 사용하여 서버 다운로드. steamcmd와 호환되지 않는(Mac의 M 시리즈 등) 호스트에 도움됨 | false | true/false | 1.0.0 | + +*설정 권장사항 + +** 기본 값 사용 권장 + + +
제거된 목록 + +| 변수명 | 사용 가능한 버전 | 대체된 변수명 | +|-----------------------------------------------|-------------------|---------------------------------------| +| DISCORD_SERVER_INFO_MESSAGE_ENABLE | 0.1.0 | | +| DISCORD_SERVER_INFO_MESSAGE_ENABLED | 0.1.1 ~ 0.1.10 | | +| DISCORD_SERVER_INFO_MESSAGE_WITH_IP | 0.1.0 ~ 0.1.10 | | +| DISCORD_PRE_START_MESSAGE_WITH_GAME_SETTINGS | 0.1.11 ~ 0.4.0 | | +| DISCORD_PRE_START_MESSAGE_WITH_SERVER_IP | 0.1.11 ~ 0.4.0 | | +| DISCORD_PRE_START_MESSAGE_WITH_DOMAIN | 0.1.11 ~ 0.4.0 | | +| BROADCAST_COUNTDOWN_MTIMES | 0.1.6 ~ 0.1.9 | BROADCAST_COUNTDOWN_REMAINING_TIMES | +| ARM_COMPATIBILITY_MODE | 0.1.0 ~ 0.2.0 | ARM64_DEVICE | +| TARGET_COMMIT_ID | 0.1.3 ~ 0.4.0 | TARGET_MANIFEST_ID | + +
+ +### ARM64 전용 환경 변수 + +ARM64 호스트는 서버의 안정성 및 성능 향상을 위해 +Box64 관련 변수를 사용하여 서버 설정을 조정할 수 있습니다. Box64 구성에 대한 자세한 내용은 해당 공식 문서를 참조해 주세요. @@ -320,88 +340,76 @@ Box64 구성에 대한 자세한 내용은 해당 공식 문서를 참조해 주 > 보다 구체적인 장치의 호환성을 위해 > [기본 이미지 저장소](https://github.com/sonroyaalmerol/steamcmd-arm64)에 Issue를 생성해 주세요. -| 변수명 | 설명 | 기본값 | 설정 가능한 값 | 추가된 버전 | -|-------------------------|------------------------------------------------------------------------------------------------------------------------------------------|---------|---------------------------|-----------| -| BOX64_DYNAREC_STRONGMEM | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_strongmem-)] Strong Memory 모델 시뮬레이션 활성화 여부 | 1 | 0, 1, 2, 3 | 0.3.0 | -| BOX64_DYNAREC_BIGBLOCK | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_bigblock-)] Box64의 Dynarec 빌딩 BigBlock 활성화 여부 | 1 | 0, 1, 2, 3 | 0.3.0 | -| BOX64_DYNAREC_SAFEFLAGS | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_safeflags-)] CALL/RET 연산자 코드의 플래그 처리 | 1 | 0, 1, 2 | 0.3.0 | -| BOX64_DYNAREC_FASTROUND | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_fastround-)] 정밀한 x86 반올림 생성 활성화 여부 | 1 | 0, 1 | 0.3.0 | -| BOX64_DYNAREC_FASTNAN | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_fastnan-)] -NAN 생성 활성화 여부 | 1 | 0, 1 | 0.3.0 | -| BOX64_DYNAREC_X87DOUBLE | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_x87double-)] x87 에뮬레이션용 Double 사용 강제 여부 | 0 | 0, 1 | 0.3.0 | -| ARM64_DEVICE | 호스트 디바이스를 기반으로 사용할 Box64 빌드를 지정하십시오. 이 설정은 ARM64 호스트에만 적용 가능합니다. | generic | generic, m1, rpi5, adlink | 0.3.0 | - -### 제거된 환경 변수 - - -
목록 보기 - -| 변수명 | 사용 가능한 버전 | 사유 | 대체된 변수명 | -|-------------------------------------|----------------|-----|----------------------------------------------| -| DISCORD_SERVER_INFO_MESSAGE_ENABLE | 0.1.0 | 오타 | DISCORD_PRE_START_MESSAGE_WITH_GAME_SETTINGS | -| DISCORD_SERVER_INFO_MESSAGE_ENABLED | 0.1.1 ~ 0.1.10 | 수정 | DISCORD_PRE_START_MESSAGE_WITH_GAME_SETTINGS | -| DISCORD_SERVER_INFO_MESSAGE_WITH_IP | 0.1.0 ~ 0.1.10 | 수정 | DISCORD_PRE_START_MESSAGE_WITH_SERVER_IP | -| BROADCAST_COUNTDOWN_MTIMES | 0.1.6 ~ 0.1.9 | 수정 | BROADCAST_COUNTDOWN_REMAINING_TIMES | -| ARM_COMPATIBILITY_MODE | 0.1.0 ~ 0.2.0 | 제거 | | - -
+| 변수명 | 설명 | 기본값 | 설정 가능한 값 | 추가된 버전 | +|---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------|-----------|---------------------------|---------------| +| BOX64_DYNAREC_STRONGMEM | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_strongmem-)] Strong Memory 모델 시뮬레이션 활성화 여부 | 1 | 0, 1, 2, 3 | 0.3.0 | +| BOX64_DYNAREC_BIGBLOCK | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_bigblock-)] Box64의 Dynarec 빌딩 BigBlock 활성화 여부 | 1 | 0, 1, 2, 3 | 0.3.0 | +| BOX64_DYNAREC_SAFEFLAGS | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_safeflags-)] CALL/RET 연산자 코드의 플래그 처리 | 1 | 0, 1, 2 | 0.3.0 | +| BOX64_DYNAREC_FASTROUND | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_fastround-)] 정밀한 x86 반올림 생성 활성화 여부 | 1 | 0, 1 | 0.3.0 | +| BOX64_DYNAREC_FASTNAN | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_fastnan-)] -NAN 생성 활성화 여부 | 1 | 0, 1 | 0.3.0 | +| BOX64_DYNAREC_X87DOUBLE | [[Box64 config](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md#box64_dynarec_x87double-)] x87 에뮬레이션용 Double 사용 강제 여부 | 0 | 0, 1 | 0.3.0 | +| ARM64_DEVICE | 호스트 디바이스를 기반으로 사용할 Box64 빌드 지정. ARM64 호스트만 적용됨 | generic | generic, m1, rpi5, adlink | 0.3.0 | ### 게임 포트 -| 포트 | 설명 | -|------|---------------| -| 7777 | 게입 포트 (UDP) | +| 포트 | 설명 | +|-------|-------------------| +| 7777 | 게입 포트 (UDP) | ## 브로드캐스트 서버 자동 업데이트/재부팅 전 카운트다운에 사용됩니다. > [!IMPORTANT] -> 게임 서버에서 RCON을 지원하지 않아 게임 내 메시지를 띄울 수 없기 때문에 -> 해당 메시지를 디스코드로 전송합니다. +> 서버가 아닌 디스코드로 전송합니다. > > [브로드캐스트 메시지를 디스코드로 전송](#브로드캐스트-메시지를-디스코드로-전송) 참고 바람 ### 수동 브로드캐스트 -아래 명령어를 사용하여 수동으로 브로드캐스트가 가능합니다. +> [!TIP] +> 원하는 색상이 없다면 Hex 값으로 직접 지정하세요! + +아래 명령어로 메시지를 브로드캐스트할 수 있습니다. ```bash -docker exec longvinter-server broadcast "Message" COLOR +docker exec longvinter-server broadcast "Message" [COLOR|ALIAS|HEX] ``` -색상은 -$\color{#1132D8}Blue$(기본값), -$\color{#E8D44F}Yellow$, -$\color{#D85311}Orange$, -$\color{#DF0000}Red$, -$\color{#00CC00}Green$ -중 선택할 수 있으며, 대/소문자를 구분하지 않습니다. +색상은 메시지를 [디스코드로 전송](#브로드캐스트-메시지를-디스코드로-전송)할 때 사용합니다. +(대/소문자를 구분하지 않음) + +| Color | Alias | Hex | +|---------------------------|---------------|-----------| +| $\color{#1132D8}Blue$* | info | 1132D8 | +| $\color{#E8D44F}Yellow$ | in-progress | E8D44F | +| $\color{#D85311}Orange$ | warn | D85311 | +| $\color{#DF0000}Red$ | failure | DF0000 | +| $\color{#00CC00}Green$ | success | 00CC00 | -색상은 메시지를 디스코드로 전송할 때 사용됩니다. [브로드캐스트 메시지를 디스코드로 전송](#브로드캐스트-메시지를-디스코드로-전송) 참고 바람 +*기본값 ## 백업 생성 > [!WARNING] -> 마지막 저장이 언제였는지 확인해 주세요. -> -> 백업 실행 시 마지막으로 저장된 시점을 백업합니다. +> 현재 시점이 자동으로 저장되지 않습니다. -아래 명령어를 실행하면 백업이 진행됩니다. +아래 명령어를 사용하여 마지막 저장 시점의 백업 파일을 생성합니다. ```bash docker exec longvinter-server backup ``` -백업 완료 시 `/data/Longvinter/backups/`에 압축 파일이 생성됩니다. +백업 파일은 `/data/backups/` 디렉토리에 생성됩니다. ## 백업 파일을 이용한 복원 > [!WARNING] -> 마지막 저장이 언제였는지 확인해 주세요. +> 현재 시점이 자동으로 저장되지 않습니다. > -> 만약 복구에 실패할 경우 마지막 저장 지점으로 롤백됩니다. +> 만약 복원에 실패할 경우 마지막 저장 지점으로 롤백됩니다. -아래 명령어를 실행하면 복구가 진행됩니다. +아래 명령어를 사용하여 백업된 서버를 복원합니다. ```bash docker exec -it longvinter-server restore @@ -409,29 +417,27 @@ docker exec -it longvinter-server restore > [!IMPORTANT] > 도커 재시작 옵션이 `always` 또는 `unless-stopped`로 설정되어 있어야 합니다. -> 그렇지 않으면 서버가 종료된 후 수동으로 서버를 다시 올려야 합니다. +> 그렇지 않으면 서버가 종료된 후 수동으로 컨테이너를 시작해야 합니다. > -> 참고로 [사용법](#사용법)에 기재된 `docker compose` 및 `docker run` 명령어의 예시에는 해당 설정이 적용되어 있습니다. +> [사용법](#사용법)의 예제 `docker compose` 파일 및 `docker run` 명령어에는 이미 적용되어 있습니다. ## 수동 복원 > [!WARNING] -> 마지막 저장이 언제였는지 확인해 주세요. -> -> 서버를 종료할 때 서버가 자동으로 저장되지 않습니다. +> 서버를 종료할 때 서버는 자동으로 저장되지 않습니다. -먼저 복구할 백업 파일을 `/data/Longvinter/backups/`에서 찾아 압축을 해제합니다. -그리고 복구하기 전 서버를 중지해야 합니다. +`/data/backups/`에서 복원할 백업 파일을 찾아 압축을 해제합니다. +작업 전 서버를 중지해야 합니다. ```bash docker compose down ``` -`data/Longvinter/Saved/`에 저장된 디렉토리들을 모두 삭제합니다. +`data/Longvinter/Saved/SaveGames` 디렉토리를 삭제합니다. -위에서 압축을 해제한 `Saved/`에 있는 내 모든 디렉토리를 `data/Longvinter/Saved/`에 복사합니다. +위에서 압축을 해제한 `Saved/SaveGames` 디렉토리를 `data/Longvinter/Saved/SaveGames`로 복사합니다. -복사가 완료되었으면 서버를 다시 시작합니다. +그리고 서버를 시작합니다. (Docker Compose를 사용하는 경우) ```bash docker compose up -d @@ -439,9 +445,11 @@ docker compose up -d ## Cron으로 자동 백업 설정하는 방법 -자동 백업을 사용하려면 환경 변수 BACKUP_ENABLED 값이 `true`로 설정되어 있어야 합니다. (기본값: `true`) +TZ로 설정된 시간대에 따라 매일 밤 자정에 서버가 자동으로 백업합니다. -BACKUP_CRON_EXPRESSION는 크론식으로, 작업을 실행할 시간 또는 주기를 설정할 수 있습니다. +환경 변수 BACKUP_ENABLED 값으로 자동 백업을 활성화 및 비활성화할 수 있습니다. (기본값은 활성화) + +BACKUP_CRON_EXPRESSION는 크론식으로, 작업을 실행할 시기의 간격을 정의합니다. > [!TIP] > 이 이미지는 Supercronic으로 Cron을 사용합니다. @@ -449,24 +457,28 @@ BACKUP_CRON_EXPRESSION는 크론식으로, 작업을 실행할 시간 또는 주 > 또는 > [Crontab Generator](https://crontab-generator.org)를 참고해 주세요. -만약 BACKUP_CRON_EXPRESSION 값을 `0 2 * * *`로 설정할 경우 매일 오전 2시에 백업이 진행됩니다. -이는 환경 변수 TZ 값의 영향을 받으며, 기본값은 매일 밤 자정에 실행되도록 설정되어 있습니다. +기본 일정을 변경하려면 BACKUP_CRON_EXPRESSION 값을 설정합니다. +예시: BACKUP_CRON_EXPRESSION 값이 `0 2 * * *`인 경우 매일 오전 2시에 백업을 진행합니다. ## Cron으로 자동 업데이트 설정하는 방법 -자동 업데이트를 사용하려면 아래 환경 변수 모두 true로 설정해야 합니다. +TZ로 설정된 시간대에 따라 매시간 정각에 서버가 자동으로 업데이트합니다. +(카운트다운이 끝나고 서버가 저장되면 업데이트를 진행합니다.) + +자동 업데이트를 사용하려면 아래환경 변수들을 모두 `true`로 설정해야 합니다. -- AUTO_UPDATE_ENABLED (기본값: `false`) -- UPDATE_ON_BOOT (기본값: `true`) +* UPDATE_ON_BOOT > [!IMPORTANT] > > 도커 재시작 옵션이 `always` 또는 `unless-stopped`로 설정되어 있어야 합니다. -> 그렇지 않으면 서버가 종료된 후 수동으로 서버를 다시 올려야 합니다. +> 그렇지 않으면 서버가 종료된 후 수동으로 컨테이너를 시작해야 합니다. > -> 참고로 [사용법](#사용법)에 기재된 `docker compose` 및 `docker run` 명령어의 예시에는 해당 설정이 적용되어 있습니다. +> [사용법](#사용법)의 예제 `docker compose` 파일 및 `docker run` 명령어에는 이미 적용되어 있습니다. + +환경 변수 AUTO_UPDATE_ENABLED 값으로 자동 업데이트를 활성화 및 비활성화할 수 있습니다. (기본값은 비활성화) -AUTO_UPDATE_CRON_EXPRESSION는 크론식으로, 작업을 실행할 시간 또는 주기를 설정할 수 있습니다. +AUTO_UPDATE_CRON_EXPRESSION는 크론식으로, 작업을 실행할 시기의 간격을 정의합니다. > [!TIP] > 이 이미지는 Supercronic으로 Cron을 사용합니다. @@ -474,21 +486,28 @@ AUTO_UPDATE_CRON_EXPRESSION는 크론식으로, 작업을 실행할 시간 또 > 또는 > [Crontab Generator](https://crontab-generator.org)를 참고해 주세요. -만약 AUTO_UPDATE_CRON_EXPRESSION 값을 `0 2 * * *`로 설정할 경우 매일 오전 2시에 업데이트가 진행됩니다. -이는 환경 변수 TZ 값의 영향을 받으며, 기본값은 매 시간 정시에 실행되도록 설정되어 있습니다. +기본 일정을 변경하려면 AUTO_UPDATE_CRON_EXPRESSION 값을 설정합니다. +예시: AUTO_UPDATE_CRON_EXPRESSION 값이 `30 * * * *`인 경우 매시 30분에 업데이트를 진행합니다. ## Cron으로 자동 재부팅 설정하는 방법 -자동 백업을 사용하려면 환경 변수 AUTO_REBOOT_ENABLED 값이 `true`로 설정되어 있어야 합니다. (기본값: `false`) +> [!TIP] +> CFG_RESTART_TIME_24H를 사용하면 서버를 저장한 후 재부팅합니다. +> 단, UTC 기준으로 작성해야 합니다. + +TZ로 설정된 시간대에 따라 매일 밤 자정에 서버가 자동으로 재부팅합니다. +(카운트다운이 끝나고 서버가 저장되면 재부팅을 진행합니다.) > [!IMPORTANT] > > 도커 재시작 옵션이 `always` 또는 `unless-stopped`로 설정되어 있어야 합니다. -> 그렇지 않으면 서버가 종료된 후 수동으로 서버를 다시 올려야 합니다. +> 그렇지 않으면 서버가 종료된 후 수동으로 컨테이너를 시작해야 합니다. > -> 참고로 [사용법](#사용법)에 기재된 `docker compose` 및 `docker run` 명령어의 예시에는 해당 설정이 적용되어 있습니다. +> [사용법](#사용법)의 예제 `docker compose` 파일 및 `docker run` 명령어에는 이미 적용되어 있습니다. -AUTO_REBOOT_CRON_EXPRESSION는 크론식으로, 작업을 실행할 시간 또는 주기를 설정할 수 있습니다. +환경 변수 AUTO_REBOOT_ENABLED 값으로 자동 재부팅을 활성화 및 비활성화할 수 있습니다. (기본값은 비활성화) + +AUTO_REBOOT_CRON_EXPRESSION는 크론식으로, 작업을 실행할 시기의 간격을 정의합니다. > [!TIP] > 이 이미지는 Supercronic으로 Cron을 사용합니다. @@ -496,8 +515,8 @@ AUTO_REBOOT_CRON_EXPRESSION는 크론식으로, 작업을 실행할 시간 또 > 또는 > [Crontab Generator](https://crontab-generator.org)를 참고해 주세요. -만약 AUTO_REBOOT_CRON_EXPRESSION 값을 `0 2 * * *`로 설정할 경우 매일 오전 2시에 재부팅이 진행됩니다. -이는 환경 변수 TZ 값의 영향을 받으며, 기본값은 매일 밤 자정에 실행되도록 설정되어 있습니다. +기본 일정을 변경하려면 AUTO_REBOOT_CRON_EXPRESSION 값을 설정합니다. +예시: AUTO_REBOOT_CRON_EXPRESSION 값이 `0 2 * * *`인 경우 매일 오전 2시에 재부팅을 진행합니다. ## 서버 설정 변경 @@ -506,47 +525,61 @@ AUTO_REBOOT_CRON_EXPRESSION는 크론식으로, 작업을 실행할 시간 또 > [!IMPORTANT] > > 게임이 아직 베타 버전이기 때문에 해당 환경 변수 및 설정은 변경될 수 있습니다. - -[환경 변수](#환경-변수)와 함께 사용되는 설정입니다. - -| 변수 | 설명 | 기본값 | 설정 가능한 값 | -|------------------------------------|-----------------------------------------------------------|-------------------------------|-----------------------------------------------------------------| -| CFG_SERVER_NAME | 비공식 서버 목록에 표시할 이름 설정 | Unnamed Island | "string" | -| CFG_SERVER_MOTD | 섬 곳곳의 표지판에 표시되는 오늘의 메시지 설정 | Welcome to Longvinter Island! | "string" | -| CFG_MAX_PLAYERS | 동시에 접속할 수 있는 최대 플레이어 수 설정 | 32 | 1~ | -| CFG_PASSWORD | 서버 비밀번호 설정 | _(empty)_ | "string" | -| CFG_COMMUNITY_WEBSITE | 서버 목록 및 게임 내에서 표시되는 URL | www\.longvinter\.com | `example.com`, `http://example.com`, `https://example.com/path` | -| CFG_SERVER_TAG | 서버 검색을 위한 태그 추가 | none | "string" | -| CFG_COOP_PLAY | 협동 플레이 활성화 (CFG_ENABLE_PVP가 false로 설정되어 있어야 함) | false | true/false | -| CFG_COOP_SPAWN | 협동 플레이 스폰 지점 설정 | 0 | 0(West), 1(South), 2(East). (확인 필요) | -| CFG_CHECK_VPN | VPN 연결 차단 | true | true/false | -| CFG_CHEST_RESPAWN_TIME | 전리품 상자의 최대 리스폰 시간(초) 설정 | 600 | ?~ | -| CFG_DISABLE_WANDERING_TRADERS | 떠돌이 상인 스폰 비활성화 | false | true/false | -| CFG_SERVER_REGION | 서버 브라우저 내 지정한 국가 목록에 서버 표시 | _(empty)_ | AS, NA, SA, EU, OC, AF, AN or nothing | -| CFG_ADMIN_STEAM_ID | 해당 EOSID 값을 가진 플레이어를 관리자로 설정 (인게임에서 확인 가능) | _(empty)_ | 0-9, a-f, " "(Space) | -| CFG_ENABLE_PVP | PvP 활성화 | true | true/false | -| CFG_TENT_DECAY | 텐트 자동 철거 활성화 | true | true/false | -| CFG_MAX_TENTS | 플레이어가 서버에 설치할 수 있는 최대 텐트 수 설정 | 2 | 1~ | -| CFG_HARDCORE | 하드코어 모드 활성화 | false | true/false | -| CFG_MONEY_DROP_MULTIPLIER\* | 사망 시 MK 드랍률 | 0.0 | 0.0~1.0 | -| CFG_WEAPON_DAMAGE_MULTIPLIER\* | 무기 데미지 비율 | 1.0 | 0.0~ | -| CFG_ENERGY_DRAIN_MULTIPLIER\* | 에너지 소비율 | 1.0 | 0.0~ | -| CFG_PRICE_FLUCTUATION_MULTIPLIER\* | 아이템 가격 변동률 | 1.0 | 0.0~ | - -\* 하드코어 모드에서만 적용됨 +> [공식 위키](https://wiki.longvinter.com/server/configuration#server-configuration) 참고 + +아래 규칙을 따라 서버 설정이 환경 변수명으로 변환됩니다. + +* 모두 대문자로 변환 +* 단어를 언더바로 구분 +* 접두사로 `CFG_`를 추가 + +예시: + +* Password -> CFG_PASSWORD +* ServerName -> CFG_SERVER_NAME +* ServerMOTD -> CFG_SERVER_MOTD + +| 변수 | 설명 | 기본값 | 설정 가능한 값 | +|---------------------------------------|-----------------------------------------------------------------------|-------------------------------|-------------------------------------------------------| +| CFG_SERVER_NAME | 비공식 서버 목록에 표시할 이름 설정 | Unnamed Island | String | +| CFG_SERVER_MOTD | 섬 곳곳의 표지판에 표시되는 오늘의 메시지 설정 | Welcome to Longvinter Island! | String | +| CFG_MAX_PLAYERS | 동시에 접속할 수 있는 최대 플레이어 수 설정 | 32 | Integer | +| CFG_PASSWORD | 서버 비밀번호 설정 | | String | +| CFG_COMMUNITY_WEBSITE | 서버 목록 및 게임 내에서 표시되는 URL | www\.longvinter\.com | String | +| CFG_TAG | 서버 검색을 위한 태그 추가 | none | String | +| CFG_COOP_PLAY | 협동 플레이 활성화 (CFG_PVP가 false로 설정되어 있어야 함) | false | Boolean | +| CFG_COOP_SPAWN | 협동 플레이 스폰 지점 설정 | 0 | 0~2** | +| CFG_CHECK_VPN | VPN 연결 차단 | true | Boolean | +| CFG_CHEST_RESPAWN_TIME | 전리품 상자의 최대 리스폰 시간(초) 설정 | 600 | Integer | +| CFG_DISABLE_WANDERING_TRADERS | 떠돌이 상인 스폰 비활성화 | false | Boolean | +| CFG_SERVER_REGION | 서버 브라우저 내 지정한 국가 목록에 서버 표시 | | `AS`, `NA`, `SA`, `EU`, `OC`, `AF`, `AN` or nothing | +| CFG_ADMIN_STEAM_ID | 해당 EOSID 값을 가진 플레이어를 관리자로 설정 (인게임에서 확인 가능) | | Hexadecimal, " "(Space) | +| CFG_PVP | PvP 활성화 | true | Boolean | +| CFG_TENT_DECAY | 텐트 자동 철거 활성화 | true | Boolean | +| CFG_MAX_TENTS | 플레이어가 서버에 설치할 수 있는 최대 텐트 수 설정 | 2 | Integer | +| CFG_RESTART_TIME_24H | 재시작 시간 설정 (24시간 형식) | | Integer | +| CFG_HARDCORE | 하드코어 모드 활성화 | false | Boolean | +| CFG_MONEY_DROP_MULTIPLIER* | 사망 시 MK 드랍률 | 0.0 | Float | +| CFG_WEAPON_DAMAGE_MULTIPLIER* | 무기 데미지 비율 | 1.0 | Float | +| CFG_ENERGY_DRAIN_MULTIPLIER* | 에너지 소비율 | 1.0 | Float | +| CFG_PRICE_FLUCTUATION_MULTIPLIER* | 아이템 가격 변동률 | 1.0 | Float | + +*하드코어 모드 전용 +** 0(West), 1(South), 2(East). 확인되지 않음 ### 수동 설정 -서버가 시작된 후 `/Longvinter/Saved/Config/LinuxServer/` 폴더 내 `Game.ini` 파일이 생성됩니다. -기본적으로 `Game.ini` 파일은 [위 환경 변수](#서버-관련-환경-변수)들로 구성되지만 -DISABLE_GENERATE_SETTINGS 값을 `true`로 설정할 경우에는 직접 파일을 수정하여 설정할 수 있습니다. +서버가 시작되면 `Game.ini` 파일이 `/Longvinter/Saved/Config/LinuxServer/Game.ini` 위치에 생성됩니다. -[공식 위키 사이트](https://wiki.longvinter.com/server/configuration#server-configuration) 참고 +기본적으로 환경 변수는 `Game.ini` 파일의 내용을 덮어씁니다. +해당 파일을 직접 수정하려면 DISABLE_GENERATE_SETTINGS 값을 `true`로 설정하세요. > [!IMPORTANT] -> 서버가 중지되어 있을 때만 `Game.ini` 파일을 변경할 수 있습니다. +> 서버가 중지되어 있을 때만 `Game.ini` 파일을 수정할 수 있습니다. > -> 서버가 실행 중이라면 중지할 때 해당 파일을 덮어쓰기 때문에 서버를 중지한 후 수정해야 합니다. +> 서버가 실행 중일 때 변경된 내용은 서버가 중지되면 덮어씁니다. + +서버 설정에 대한 자세한 목록은 [공식 위키 사이트](https://wiki.longvinter.com/server/configuration#server-configuration)를 참고하세요. ## 디스코드 웹훅 사용법 @@ -555,7 +588,7 @@ DISABLE_GENERATE_SETTINGS 값을 `true`로 설정할 경우에는 직접 파일 Docker Run 실행 시 사용하는 방법: -```bash +```sh -e DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/1234567890/abcde" \ -e DISCORD_PRE_UPDATE_BOOT_MESSAGE="Server is updating..." \ ``` @@ -563,29 +596,37 @@ Docker Run 실행 시 사용하는 방법: Docker Compose로 사용하는 방법 ```yml -- DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/1234567890/abcde +- DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/1234567890/abcde" - DISCORD_PRE_UPDATE_BOOT_MESSAGE="Server is updating..." ``` ### 브로드캐스트 메시지를 디스코드로 전송 > [!IMPORTANT] -> -> 게임 서버에서 RCON을 지원하지 않아 게임 내 메시지를 띄울 수 없기 때문에 -> 해당 기능 사용을 권장합니다. +> 게임 서버에서 RCON 및 REST API 기능을 지원하지 않기 때문에 +> 인게임 브로드캐스트가 불가능하므로 메시지를 디스코드로 전송합니다. -브로드캐스트 메시지를 디스코드로 전송하려면 환경 변수 DISCORD_BROADCAST_MESSAGE_ENABLE 값이 `true`로 설정되어 있어야 합니다. (기본값: `true`) - -환경 변수 DISCORD_BROADCAST_MESSAGE_URL 값을 설정하여 브로드캐스트 전용 채널을 사용할 수 있으며, -설정하지 않으면 DISCORD_WEBHOOK_URL 값이 사용됩니다. +환경 변수 DISCORD_BROADCAST_MESSAGE_ENABLE 값으로 이 기능을 활성화 및 비활성화할 수 있습니다. (기본값은 활성화) ## 특정 게임 버전으로 고정 > [!WARNING] -> 해당 설정 사용 시 서버를 구버전으로 설치 및 다운그레이드를 진행합니다. 이 설정으로 인해 어떠한 문제가 발생할 지 알 수 없음을 알려드립니다. +> 하위 버전으로 다운그레이드는 가능하지만, 기존 세이브에 어떤 영향을 비칠지는 알 수 없습니다. > -> **꼭 필요한 경우에만 사용해 주세요!** +> **문제가 생기더라도 책임지지 않습니다!** + +환경 변수 **TARGET_MANIFEST_ID** 값이 설정된 경우 서버 버전이 해당 매니페스트에 고정됩니다. +매니페스트는 출시일/업데이트 버전에 해당합니다. 매너페스트는 SteamCMD 또는 [SteamDB](https://steamdb.info/depot/1639882/manifests/) 사이트에서 찾을 수 있습니다. + +### 일부 Manifest ID 표 + +| 버전 | Manifest ID | +|-----------|-----------------------| +| 0.10 B | 7723330886973031108 | +| 0.11 R | 876347941046873366 | +| 0.12 B | 7232977979130477635 | +| 0.13 R | 3287206638975838103 | + +## 이슈 및 기능 요청 -환경 변수 **TARGET_COMMIT_ID** 값이 설정된 경우 서버 버전이 해당 커밋의 버전으로 실행됩니다. -Commit ID는 페이지에서 확인할 수 있는 16진수 값이며, -4자리 이상이 필요합니다. +이슈 및 기능 요청은 [여기](https://github.com/kimzuni/longvinter-docker-server/issues/new/choose)서 제출할 수 있습니다. diff --git a/scripts/reboot.sh b/scripts/auto_reboot.sh similarity index 100% rename from scripts/reboot.sh rename to scripts/auto_reboot.sh diff --git a/scripts/backup.sh b/scripts/backup.sh index c3508fd..4be18c7 100644 --- a/scripts/backup.sh +++ b/scripts/backup.sh @@ -7,9 +7,9 @@ source "/home/steam/server/helper_functions.sh" DiscordMessage "Backup" "${DISCORD_PRE_BACKUP_MESSAGE}" "in-progress" "${DISCORD_PRE_BACKUP_MESSAGE_ENABLED}" "${DISCORD_PRE_BACKUP_MESSAGE_URL}" -DATE=$(date +"%s") -FILE_PATH="$BACKUP_DIRECTORY_PATH/Saved-Backup-${DATE}.tar.gz" -cd "$GIT_REPO_PATH/Longvinter" || exit +DATE=$(date +"%Y-%m-%d_%H-%M-%S") +FILE_PATH="$BACKUP_DIR/longvinter-save-${DATE}.tar.gz" +cd "$DATA_DIR/Longvinter" || exit LogAction "Creating backup" tar -zcf "$FILE_PATH" "Saved/" @@ -36,11 +36,11 @@ if [[ "${OLD_BACKUP_DAYS}" =~ ^[0-9]+$ ]]; then LogAction "Removing Old Backups" LogInfo "Removing backups older than ${OLD_BACKUP_DAYS} days" DiscordMessage "Backup" "${DISCORD_PRE_BACKUP_DELETE_MESSAGE//old_backup_days/${OLD_BACKUP_DAYS}}" "in-progress" "${DISCORD_PRE_BACKUP_DELETE_MESSAGE_ENABLED}" "${DISCORD_PRE_BACKUP_DELETE_MESSAGE_URL}" - find "$BACKUP_DIRECTORY_PATH" -mindepth 1 -maxdepth 1 -mtime "+${OLD_BACKUP_DAYS}" -type f -name 'Saved-Backup-*.tar.gz' -print -delete + find "$BACKUP_DIR" -mindepth 1 -maxdepth 1 -mtime "+${OLD_BACKUP_DAYS}" -type f -name 'Saved-Backup-*.tar.gz' -print -delete DiscordMessage "Backup" "${DISCORD_POST_BACKUP_DELETE_MESSAGE//old_backup_days/${OLD_BACKUP_DAYS}}" "success" "${DISCORD_POST_BACKUP_DELETE_MESSAGE_ENABLED}" "${DISCORD_POST_BACKUP_DELETE_MESSAGE_URL}" exit 0 fi LogError "Unable to delete old backups, OLD_BACKUP_DAYS is not an integer. OLD_BACKUP_DAYS=${OLD_BACKUP_DAYS}" DiscordMessage "Backup" "${DISCORD_ERR_BACKUP_DELETE_MESSAGE//old_backup_days/${OLD_BACKUP_DAYS}}" "failure" "${DISCORD_ERR_BACKUP_DELETE_MESSAGE_ENABLED}" "${DISCORD_ERR_BACKUP_DELETE_MESSAGE_URL}" -exit 1 \ No newline at end of file +exit 1 diff --git a/scripts/broadcast.sh b/scripts/broadcast.sh index 160a80d..2d2a810 100644 --- a/scripts/broadcast.sh +++ b/scripts/broadcast.sh @@ -7,4 +7,8 @@ source "/home/steam/server/helper_functions.sh" message="$1" level="$2" -DiscordMessage "Broadcast" "$message" "$level" "$DISCORD_BROADCAST_MESSAGE_ENABLE" "$DISCORD_BROADCAST_MESSAGE_URL" +if [ -z "$message" ]; then + INFO "Usage: ${0} Message [LEVEL]" +else + DiscordMessage "Broadcast" "$message" "$level" "$DISCORD_BROADCAST_MESSAGE_ENABLE" "$DISCORD_BROADCAST_MESSAGE_URL" +fi diff --git a/scripts/compile-settings.sh b/scripts/compile-settings.sh index 6b42dc1..56e7457 100644 --- a/scripts/compile-settings.sh +++ b/scripts/compile-settings.sh @@ -2,19 +2,35 @@ # shellcheck source=scripts/helper_functions.sh source "/home/steam/server/helper_functions.sh" +config_file="$CONFIG_FILE_FULL_PATH" +config_dir=$(dirname "$config_file") + +mkdir -p "$config_dir" || exit +# If file exists then check if it is writable +if [ -f "$config_file" ]; then + if ! isWritable "$config_file"; then + LogError "Unable to create $config_file" + exit 1 + fi +# If file does not exist then check if the directory is writable +elif ! isWritable "$config_dir"; then + # Exiting since the file does not exist and the directory is not writable. + LogError "Unable to create $config_file" + exit 1 +fi + LogAction "Compiling Game.ini" CFG_SERVER_REGION_FULL=${CFG_SERVER_REGION:+"ServerRegion=$CFG_SERVER_REGION"} -CFG_RESTART_TIME_24H_FULL=${CFG_RESTART_TIME_24H:+"RestartTime24h=$CFG_RESTART_TIME_24H"} -cat << EOF > "$CONFIG_FILE_FULL_PATH" +cat << EOF | grep -Ev ^"[[:space:]]?+"$ | sed "2,\$s/^\[/\n\[/g" > "$config_file" [/Game/Blueprints/Server/GI_AdvancedSessions.GI_AdvancedSessions_C] ServerName="$CFG_SERVER_NAME" ServerMOTD="$CFG_SERVER_MOTD" MaxPlayers=$CFG_MAX_PLAYERS Password="$CFG_PASSWORD" CommunityWebsite="${CFG_COMMUNITY_WEBSITE#http*://}" -Tag="$CFG_SERVER_TAG" +Tag="$CFG_TAG" CoopPlay=$CFG_COOP_PLAY CoopSpawn=$CFG_COOP_SPAWN CheckVPN=$CFG_CHECK_VPN @@ -24,10 +40,10 @@ $CFG_SERVER_REGION_FULL [/Game/Blueprints/Server/GM_Longvinter.GM_Longvinter_C] AdminSteamID="$CFG_ADMIN_STEAM_ID" -PVP=$CFG_ENABLE_PVP +PVP=$CFG_PVP TentDecay=$CFG_TENT_DECAY MaxTents=$CFG_MAX_TENTS -$CFG_RESTART_TIME_24H_FULL +RestartTime24h=$CFG_RESTART_TIME_24H SaveBackups=$CFG_SAVE_BACKUPS Hardcore=$CFG_HARDCORE MoneyDropMultiplier=$CFG_MONEY_DROP_MULTIPLIER @@ -37,9 +53,9 @@ PriceFluctuationMultiplier=$CFG_PRICE_FLUCTUATION_MULTIPLIER EOF if [ "${DEBUG,,}" = true ]; then - echo "====Debug====" - grep -Ev "^[[:space:]]*(\[.*)?$" "$CONFIG_FILE_FULL_PATH" - echo "====Debug====" + echo "====Debug====" + grep -Ev "^[[:space:]]*(\[.*)?$" "$config_file" + echo "====Debug====" fi LogSuccess "Compiling Game.ini done!" diff --git a/scripts/discord.sh b/scripts/discord.sh index ef60739..fecf867 100644 --- a/scripts/discord.sh +++ b/scripts/discord.sh @@ -56,18 +56,18 @@ if [ -n "${LEVEL}" ]; then COLOR=$DISCORD_GREEN ;; * ) - LogWarn "Could not find \"${LEVEL}\", using \"${DEFAULT_LEVEL}\"" - COLOR=$DISCORD_BLUE + if [[ "${LEVEL,,}" =~ ^[0-9a-f]{1,6}$ ]]; then + COLOR=$(( 16#$LEVEL )) + else + LogWarn "Could not find \"${LEVEL}\", using \"${DEFAULT_LEVEL}\"" + COLOR=$DISCORD_BLUE + fi ;; esac else COLOR=$DISCORD_BLUE fi -if [ "${TITLE,,}" == "start" ]; then - MESSAGE=$(echo -e "$MESSAGE\n"; Server_Info | sed -E "s/([^:]+):(.+)/**\1**:\2/g") -fi - JSON=$(jo embeds[]="$(jo title="$TITLE" description="$MESSAGE" color=$COLOR)" flags="$DISCORD_FLAGS") if [ "$ENABLED" = true ]; then diff --git a/scripts/helper_functions.sh b/scripts/helper_functions.sh index 9e88df1..5c2e644 100644 --- a/scripts/helper_functions.sh +++ b/scripts/helper_functions.sh @@ -127,7 +127,7 @@ Log() { DiscordMessage() { local title="$1" local message="$2" - local level="${3:-info}" + local level="$3" local enabled="$4" local webhook_url="$5" if [ -n "${DISCORD_WEBHOOK_URL}" ]; then @@ -227,23 +227,18 @@ get_latest_version() { # Use it when you have to wait for it to be saved automatically because it does not support RCON. wait_save() { - local title="$1" - local message="$2" - local level="$3" - local enabled="$4" - local webhook_url="$5" - local timestamp livetime + local curr_time timestamp if ! player_check; then - livetime="$(date "+%s")" + curr_time="$(date "+%s")" timestamp="$(grep "RemovePlayer" "$SERVER_LOG_PATH" | tail -1 | awk -F "\\\[|\\\]|\.|-|:" '{printf("%s/%s/%s %s:%s:%s\n", $2, $3, $4, $5, $6, $7)}' | date_to_timestamp UTC)" - if [ -z "$timestamp" ] || save_check "$((livetime - timestamp))"; then + if [ -z "$timestamp" ] || save_check "$((curr_time - timestamp))"; then return fi fi LogWarn "$message" - DiscordMessage "$title" "$message" "$level" "$enabled" "$webhook_url" + DiscordMessage "$@" while ! save_check; do sleep 1s @@ -255,10 +250,10 @@ wait_save() { # Returns 1 if not find save log save_check() { local spare="${1:-10}" - local livetime savetime + local curr_time save_time - livetime="$(date "+%s")" - savetime=$( + curr_time="$(date "+%s")" + save_time=$( grep -rE ^"\[[a-zA-Z]{3} [0-9, :]+ [AP]M\] Game saved!" "$SERVER_LOG_DIR" \ | awk -F "\\\[|\\\]" '{print $2}' \ | sed "s/Jan/1/g; s/Feb/2/g; s/Mar/3/g; s/Apr/4/g; s/May/5/g; s/Jun/6/g; s/Jul/7/g; s/Aug/8/g; s/Sep/9/g; s/Oct/10/g; s/Nov/11/g; s/Dec/12/g" \ @@ -266,7 +261,7 @@ save_check() { | sort --version-sort | tail -1 | date_to_timestamp ) - if [ $((livetime - savetime)) -ge $((spare - 5)) ]; then + if [ $((curr_time - save_time)) -ge $((spare - 5)) ]; then return 1 fi return 0 @@ -284,40 +279,9 @@ date_to_timestamp() { fi } -Server_Info() { - local IP INFO - local HTTP URL="$CFG_COMMUNITY_WEBSITE" - - if ! [[ "$URL" =~ ^https?:// ]] && [ -n "$URL" ]; then - HTTP="http://" - fi - - if [ -n "$DISCORD_PRE_START_MESSAGE_WITH_DOMAIN" ]; then - IP="${DISCORD_PRE_START_MESSAGE_WITH_DOMAIN#http*://}" - elif [ "$DISCORD_PRE_START_MESSAGE_WITH_SERVER_IP" = true ]; then - IP="$(curl -sfSL ipv4.icanhazip.com)" - fi - if [ -n "$IP" ]; then - INFO="Server IP: $IP"$'\n'"Server Port: $PORT"$'\n' - fi - - if [ "$DISCORD_PRE_START_MESSAGE_WITH_GAME_SETTINGS" = true ]; then - INFO=$( -cat << END -Server Name: $CFG_SERVER_NAME -${INFO}Server Password: $CFG_PASSWORD - -Message of the Day: $CFG_SERVER_MOTD -Community URL: $HTTP${URL:-None} -Max Player: $CFG_MAX_PLAYERS -PVP: $CFG_ENABLE_PVP -Tent Decay: $CFG_TENT_DECAY -Max Tent: $CFG_MAX_TENTS -Coop Play: $CFG_COOP_PLAY -Coop Spawn: $CFG_COOP_SPAWN -END - ) - fi - - echo "$INFO" +# Returns 0 if port is open +# Returns not 0 if port is not open +port_check() { + nc -uz 127.0.0.1 "${PORT}" + return $? } diff --git a/scripts/helper_install.sh b/scripts/helper_install.sh index 09a91d7..87beb7e 100644 --- a/scripts/helper_install.sh +++ b/scripts/helper_install.sh @@ -2,129 +2,205 @@ # shellcheck source=scripts/helper_functions.sh source "/home/steam/server/helper_functions.sh" -# Returns 0 if valid TARGET_COMMIT_ID or is empty -# Returns 1 if Invalid TARGET_COMMIT_ID -IsValidCommitID() { - local COMMIT_ID="$1" - local URL="$GIT_REPO_API/commits/$COMMIT_ID" - - if ! curl -sfSL "$URL" > /dev/null 2>&1; then - return 1 - fi -} - # Returns 0 if game is installed # Returns 1 if game is not installed IsInstalled() { - if [ -d "$GIT_REPO_PATH/.git" ]; then + if [ -e "$DATA_DIR/LongvinterServer.sh" ] && [ -e "$MANIFEST_PATH" ]; then return 0 fi return 1 } -# Returns 0 if Update successful -# Returns 1 if Update Failed -InstallSteamapp() { - LogAction "Checking for new Steamworks SDK Redist updates" +CreateACFFile() { + local manifestId="$1" +cat > "$MANIFEST_PATH" << EOL +"AppState" { + "appid" "$APPID" + "Universe" "1" + "name" "Longvinter Dedicated Server" + "StateFlags" "4" + "installdir" "Longvinter Dedicated Server" + "StagingSize" "0" + "buildid" "15237642" + "UpdateResult" "0" + "TargetBuildID" "0" + "AutoUpdateBehavior" "0" + "AllowOtherDownloadsWhileRunning" "0" + "ScheduledAutoUpdate" "0" + "InstalledDepots" + { + "1006" + { + "manifest" "7138471031118904166" + } + "$DEPOTID" + { + "manifest" "${manifestId}" + } + } + "UserConfig" + { + } + "MountedConfig" + { + } +} +EOL +} - local CURRENT_MANIFEST LATEST_MANIFEST temp_file http_code +# Returns 0 if Update Required +# Returns 1 if Update NOT Required +# Returns 2 if Check Failed +UpdateRequired() { + LogAction "Checking for new Longvinter Server updates" + + # define local variables + local CURRENT_MANIFEST LATEST_MANIFEST temp_file http_code updateAvailable - #check steam for latest version + # check steam for latest version temp_file=$(mktemp) - http_code=$(curl https://api.steamcmd.net/v1/info/1007 --output "$temp_file" --silent --location --write-out "%{http_code}") + http_code=$(curl "https://api.steamcmd.net/v1/info/$APPID" --output "$temp_file" --silent --location --write-out "%{http_code}") + if [ "$http_code" -ne 200 ]; then LogError "There was a problem reaching the Steam api. Unable to check for updates!" DiscordMessage "Install" "There was a problem reaching the Steam api. Unable to check for updates!" "failure" rm "$temp_file" - return 1 + return 2 fi # Parse temp file for manifest id - LATEST_MANIFEST=$(grep -Po '"1006".*"gid": "\d+"' <"$temp_file" | sed -r 's/.*("[0-9]+")$/\1/' | tr -d '"') + LATEST_MANIFEST=$(grep -Po "\"$APPID\""'.*"gid": "\d+"' <"$temp_file" | sed -r 's/.*("[0-9]+")$/\1/' | tr -d '"') rm "$temp_file" if [ -z "$LATEST_MANIFEST" ]; then LogError "The server response does not contain the expected BuildID. Unable to check for updates!" DiscordMessage "Install" "Steam servers response does not contain the expected BuildID. Unable to check for updates!" "failure" - return 1 + return 2 fi # Parse current manifest from steam files - CURRENT_MANIFEST=$(awk '/manifest/{count++} count==1 {print $2; exit}' "$DATA_DIR/steamapps/appmanifest_1007.acf" | tr -d '"') + CURRENT_MANIFEST=$(awk '/manifest/{count++} count==2 {print $2; exit}' "$MANIFEST_PATH" | tr -d '"') LogInfo "Current Version: $CURRENT_MANIFEST" - # Checking current version is latest version - if [ "$CURRENT_MANIFEST" == "$LATEST_MANIFEST" ]; then - LogSuccess "The server is up to date!" - return 0 + # Log any updates available + local updateAvailable=false + if [ "$CURRENT_MANIFEST" != "$LATEST_MANIFEST" ]; then + LogInfo "An Update Is Available. Latest Version: $LATEST_MANIFEST." + updateAvailable=true fi - LogInfo "An Update Is Available. Latest Version: $LATEST_MANIFEST." - - # Update - /home/steam/steamcmd/steamcmd.sh +@sSteamCmdForcePlatformType linux +@sSteamCmdForcePlatformBitness 64 +force_install_dir "$DATA_DIR" +login anonymous +app_update 1007 validate +quit -} -# Returns 0 if Update Required -# Returns 1 if Update NOT Required -UpdateRequired() { - LogAction "Checking for new Longvinter Server updates" + # If INSTALL_BETA_VERSION is set to true, install the latest beta version + if [ "${INSTALL_BETA_VERSION}" == true ]; then + return 0 + fi - CURRENT_COMMIT=$(git -C "$GIT_REPO_PATH" log HEAD -1 --format=format:%H) - LATEST_COMMIT=$(curl -sfSL "$GIT_REPO_API/commits/main" | jq .sha -r) + # No TARGET_MANIFEST_ID env set & update needed + if [ "$updateAvailable" == true ] && [ -z "${TARGET_MANIFEST_ID}" ]; then + return 0 + fi - LogInfo "Current Version: $CURRENT_COMMIT" + if [ -n "${TARGET_MANIFEST_ID}" ] && [ "$CURRENT_MANIFEST" != "${TARGET_MANIFEST_ID}" ]; then + LogInfo "Game not at target version. Target Version: ${TARGET_MANIFEST_ID}" + return 0 + fi - if [ -n "$TARGET_COMMIT_ID" ]; then - if [[ "$CURRENT_COMMIT" =~ ^"$TARGET_COMMIT_ID" ]]; then - LogSuccess "Game is the target version" - return 1 - else - LogInfo "Game not at target version. Target Version: ${TARGET_COMMIT_ID}" - return 0 - fi - else - if [ "$CURRENT_COMMIT" == "$LATEST_COMMIT" ]; then - LogSuccess "The server is up to date!" - return 1 - else - LogInfo "An Update Is Available. Latest Version: $LATEST_COMMIT." - return 0 - fi + # Warn if version is locked + if [ "$updateAvailable" == false ]; then + LogSuccess "The server is up to date!" + return 1 fi -} -BeforeInstall() { - if [ "$ARCHITECTURE" == "arm64" ] && [ "$PAGESIZE" != "4096" ]; then - LogWarn "WARNING: Only ARM64 hosts with 4k page size is supported when running steamcmd. Expect server installation to fail." + if [ -n "${TARGET_MANIFEST_ID}" ]; then + LogWarn "Unable to update. Locked by TARGET_MANIFEST_ID." + return 1 fi } InstallServer() { - BeforeInstall - - cd "$GIT_REPO_PATH" || exit - DiscordMessage "Install" "${DISCORD_PRE_INSTALL_MESSAGE}" "in-progress" "${DISCORD_PRE_INSTALL_MESSAGE_ENABLED}" "${DISCORD_PRE_INSTALL_MESSAGE_URL}" + local DISCORD_PRE_MESSAGE DISCORD_PRE_MESSAGE_ENABLED DISCORD_PRE_MESSAGE_URL + local DISCORD_POST_MESSAGE DISCORD_POST_MESSAGE_ENABLED DISCORD_POST_MESSAGE_URL + + if IsInstalled; then + DISCORD_PRE_MESSAGE="$DISCORD_PRE_UPDATE_BOOT_MESSAGE" + DISCORD_PRE_MESSAGE_ENABLED="$DISCORD_PRE_UPDATE_BOOT_MESSAGE_ENABLED" + DISCORD_PRE_MESSAGE_URL="$DISCORD_PRE_UPDATE_BOOT_MESSAGE_URL" + DISCORD_POST_MESSAGE="$DISCORD_POST_UPDATE_BOOT_MESSAGE" + DISCORD_POST_MESSAGE_ENABLED="$DISCORD_POST_UPDATE_BOOT_MESSAGE_ENABLED" + DISCORD_POST_MESSAGE_URL="$DISCORD_POST_UPDATE_BOOT_MESSAGE_URL" + else + DISCORD_PRE_MESSAGE="$DISCORD_PRE_INSTALL_MESSAGE" + DISCORD_PRE_MESSAGE_ENABLED="$DISCORD_PRE_INSTALL_MESSAGE_ENABLED" + DISCORD_PRE_MESSAGE_URL="$DISCORD_PRE_INSTALL_MESSAGE_URL" + DISCORD_POST_MESSAGE="$DISCORD_POST_INSTALL_MESSAGE" + DISCORD_POST_MESSAGE_ENABLED="$DISCORD_POST_INSTALL_MESSAGE_ENABLED" + DISCORD_POST_MESSAGE_URL="$DISCORD_POST_INSTALL_MESSAGE_URL" + fi - git init - git remote add origin "$GIT_REPO_URL" - git fetch origin "$GIT_REPO_BRANCH" - git checkout "${TARGET_COMMIT_ID:-$GIT_REPO_BRANCH}" - - DiscordMessage "Install" "${DISCORD_POST_INSTALL_MESSAGE}" "in-progress" "${DISCORD_POST_INSTALL_MESSAGE_ENABLED}" "${DISCORD_POST_INSTALL_MESSAGE_URL}" -} + # Check kernel page size for arm64 hosts before running steamcmd + if [ "$ARCHITECTURE" == "arm64" ] && [ "$PAGESIZE" != "4096" ] && [ "${USE_DEPOT_DOWNLOADER}" != true ]; then + LogWarn "WARNING: Only ARM64 hosts with 4k page size is supported when running steamcmd. Please set USE_DEPOT_DOWNLOADER to true." + fi -UpdateServer() { - BeforeInstall + if [ -z "${TARGET_MANIFEST_ID}" ]; then + DiscordMessage "Install" "${DISCORD_PRE_MESSAGE}" "in-progress" "${DISCORD_PRE_MESSAGE_ENABLED}" "${DISCORD_PRE_MESSAGE_URL}" + # If INSTALL_BETA_VERSION is set to true, install the latest beta version + if [ "${INSTALL_BETA_VERSION}" == true ]; then + LogWarn "Installing latest beta version" + if [ "${USE_DEPOT_DOWNLOADER}" == true ]; then + LogWarn "Downloading server files using DepotDownloader" + DepotDownloader -app "$APPID" -osarch 64 -dir "$DATA_DIR" -beta experimental -validate + DepotDownloader -app "$APPID" -depot "$DEPOTID" -osarch 64 -dir /tmp -beta experimental -manifest-only + else + /home/steam/steamcmd/steamcmd.sh +@sSteamCmdForcePlatformType linux +@sSteamCmdForcePlatformBitness 64 +force_install_dir "$DATA_DIR" +login anonymous +app_update "$APPID" -beta experimental validate +quit + fi + else + if [ "${USE_DEPOT_DOWNLOADER}" == true ]; then + LogWarn "Downloading server files using DepotDownloader" + DepotDownloader -app "$APPID" -osarch 64 -dir "$DATA_DIR" -validate + DepotDownloader -app "$APPID" -depot "$DEPOTID" -osarch 64 -dir /tmp -manifest-only + else + /home/steam/steamcmd/steamcmd.sh +@sSteamCmdForcePlatformType linux +@sSteamCmdForcePlatformBitness 64 +force_install_dir "$DATA_DIR" +login anonymous +app_update "$APPID" validate +quit + fi + fi - cd "$GIT_REPO_PATH" || exit - DiscordMessage "Update" "${DISCORD_PRE_UPDATE_BOOT_MESSAGE}" "in-progress" "${DISCORD_PRE_UPDATE_BOOT_MESSAGE_ENABLED}" "${DISCORD_PRE_UPDATE_BOOT_MESSAGE_URL}" + # Create ACF file for DepoDownloader downloads for script compatibility + if [ "${USE_DEPOT_DOWNLOADER}" == true ]; then + local manifestFile + manifestFile=$(find /tmp -type f -name "manifest_${DEPOTID}_*.txt" | head -n 1) + + if [ -z "$manifestFile" ]; then + echo "DepotDownloader manifest file not found." + else + local manifestId + manifestId=$(grep -oP 'Manifest ID / date\s*:\s*\K[0-9]+' "$manifestFile") + if [ -z "$manifestId" ]; then + echo "Manifest ID not found in DepotDownloader manifest file." + else + mkdir -p "$DATA_DIR/steamapps" + CreateACFFile "$manifestId" + fi + + rm -rf "$manifestFile" + fi + fi - git stash - if [ -z "$TARGET_COMMIT_ID" ] || ! git log -1 "${TARGET_COMMIT_ID}" > /dev/null 2>&1; then - git fetch origin "$GIT_REPO_BRANCH" + DiscordMessage "Install" "${DISCORD_POST_MESSAGE}" "success" "${DISCORD_POST_MESSAGE_ENABLED}" "${DISCORD_POST_MESSAGE_URL}" + return fi - git checkout "${TARGET_COMMIT_ID:-origin/$GIT_REPO_BRANCH}" - git stash clear - DiscordMessage "Update" "${DISCORD_POST_UPDATE_BOOT_MESSAGE}" "in-progress" "${DISCORD_POST_UPDATE_BOOT_MESSAGE_ENABLED}" "${DISCORD_POST_UPDATE_BOOT_MESSAGE_URL}" + local targetManifest + targetManifest="${TARGET_MANIFEST_ID}" + + LogWarn "Installing Target Version: $targetManifest" + DiscordMessage "Install" "${DISCORD_PRE_MESSAGE}" "in-progress" "${DISCORD_PRE_MESSAGE_ENABLED}" "${DISCORD_PRE_MESSAGE_URL}" + if [ "${USE_DEPOT_DOWNLOADER}" == true ]; then + LogWarn "Downloading server files using DepotDownloader" + DepotDownloader -app "$APPID" -depot "$DEPOTID" -manifest "$targetManifest" -osarch 64 -dir "$DATA_DIR" -validate + DepotDownloader -app "$APPID" -depot 1006 -osarch 64 -dir "$DATA_DIR" -validate + else + /home/steam/steamcmd/steamcmd.sh +@sSteamCmdForcePlatformType linux +@sSteamCmdForcePlatformBitness 64 +force_install_dir "$DATA_DIR" +login anonymous +download_depot "$APPID" "$DEPOTID" "$targetManifest" +quit + cp -vr "/home/steam/steamcmd/linux32/steamapps/content/app_$APPID/depot_$DEPOTID/Longvinter/Server/." "$DATA_DIR" + fi + CreateACFFile "$targetManifest" + DiscordMessage "Install" "${DISCORD_POST_MESSAGE}" "success" "${DISCORD_POST_MESSAGE_ENABLED}" "${DISCORD_POST_MESSAGE_URL}" } diff --git a/scripts/init.sh b/scripts/init.sh index dd60e51..933a254 100644 --- a/scripts/init.sh +++ b/scripts/init.sh @@ -2,17 +2,14 @@ # shellcheck source=scripts/variables.sh source "/home/steam/server/variables.sh" +# shellcheck source=scripts/major_update.sh +source "/home/steam/server/major_update.sh" + # shellcheck source=scripts/helper_functions.sh source "/home/steam/server/helper_functions.sh" -if ! dirExists "$DATA_DIR"; then - LogError "$DATA_DIR is not mounted." - exit 1 -fi - -mkdir -p "$BACKUP_DIRECTORY_PATH" if [[ "$(id -u)" -eq 0 ]] && [[ "$(id -g)" -eq 0 ]]; then if [[ "${PUID}" -ne 0 ]] && [[ "${PGID}" -ne 0 ]]; then LogAction "EXECUTING USERMOD" @@ -28,16 +25,19 @@ elif [[ "$(id -u)" -eq 0 ]] || [[ "$(id -g)" -eq 0 ]]; then exit 1 fi +if ! [ -w "$DATA_DIR" ]; then + LogError "$DATA_DIR is not writable." + exit 1 +fi + +mkdir -p "$BACKUP_DIR" + term_handler() { DiscordMessage "Shutdown" "${DISCORD_PRE_SHUTDOWN_MESSAGE}" "in-progress" "${DISCORD_PRE_SHUTDOWN_MESSAGE_ENABLED}" "${DISCORD_PRE_SHUTDOWN_MESSAGE_URL}" - if ! shutdown_server; then - LogWarn "Unable to shutdown the server for unknown reasons." - DiscordMessage "Shutdown" "Unable to shutdown the server for unknown reasons." "failure" "${DISCORD_PRE_SHUTDOWN_MESSAGE_ENABLED}" "${DISCORD_PRE_SHUTDOWN_MESSAGE_URL}" - return 1 - fi + shutdown_server tail --pid="$killpid" -f 2>/dev/null } @@ -72,3 +72,11 @@ if [ "${#restore_pids[@]}" -ne 0 ]; then tail --pid="$pid" -f 2>/dev/null done fi + +mapfile -t discord_pids < <(pgrep discord) +if [ "${#discord_pids[@]}" -ne 0 ]; then + LogInfo "Waiting for discord to finish" + for pid in "${discord_pids[@]}"; do + tail --pid="$pid" -f 2>/dev/null + done +fi diff --git a/scripts/major_update.sh b/scripts/major_update.sh new file mode 100644 index 0000000..fb28f23 --- /dev/null +++ b/scripts/major_update.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# Temporary scripts to fix incompatible issues caused by version updates + +# shellcheck source=scripts/helper_functions.sh +source "/home/steam/server/helper_functions.sh" + + + +if [ -n "$QUERY_PORT" ]; then + LogWarn "QUERY_PORT is no longer supported." +fi +if [ -n "$DISCORD_PRE_START_MESSAGE_WITH_GAME_SETTINGS" ] || [ -n "$DISCORD_PRE_START_MESSAGE_WITH_SERVER_IP" ] || [ -n "$DISCORD_PRE_START_MESSAGE_WITH_DOMAIN" ]; then + LogWarn "All variables starting with DISCORD_PRE_START_MESSAGE_WITH_ are no longer supported." +fi +if [ -n "$CFG_SERVER_TAG" ]; then + LogWarn "CFG_SERVER_TAG will be removed soon. Please use CFG_TAG" + export CFG_TAG="$CFG_SERVER_TAG" +fi +if [ -n "$CFG_ENABLE_PVP" ]; then + LogWarn "CFG_ENABLE_PVP will be removed soon. Please use CFG_PVP" + export CFG_PVP="$CFG_ENABLE_PVP" +fi +if [ -n "$TARGET_COMMIT_ID" ] || ! [[ "$TARGET_MANIFEST_ID" =~ ^[0-9]?+$ ]]; then + LogError "TARGET_COMMIT_ID is no longer used." + LogError "See https://github.com/kimzuni/longvinter-docker-server#locking-specific-game-version" + exit 1 +fi + + + +if dirExists "$DATA_DIR/.git" > /dev/null; then + OLD_BACKUP_DIR="$DATA_DIR/Longvinter/Backup" + if dirExists "$OLD_BACKUP_DIR" > /dev/null; then + mkdir -p "$BACKUP_DIR" + mapfile -t backup_files < <(ls -A "$OLD_BACKUP_DIR") + for file in "${backup_files[@]}"; do + rename="$file" + if [[ "$file" =~ ^Saved-Backup-[0-9]+\.tar\.gz$ ]]; then + timestamp="$(grep -Eo "[0-9]+" <<< "$file")" + date=$(date -d "@$timestamp" +"%Y-%m-%d_%H-%M-%S") + rename="${file/$timestamp/$date}" + fi + mv "$OLD_BACKUP_DIR/$file" "$BACKUP_DIR/$rename" + done + rmdir "$OLD_BACKUP_DIR" + fi + + LogWarn "Server will be reinstall because container version update." + find "$DATA_DIR/steamapps" -name "*1007*" -exec rm -rf {} \; 2> /dev/null + rm -rf "$DATA_DIR/Steam" "$DATA_DIR"/.git* +fi diff --git a/scripts/player_logging.sh b/scripts/player_logging.sh index 89e0eaf..eff437c 100644 --- a/scripts/player_logging.sh +++ b/scripts/player_logging.sh @@ -11,18 +11,17 @@ get_eosid() { sed -E "s/.*([0-9a-f]{32}).*/\1/g" <<< "$log" } -get_playername() { +eosid_to_playername() { local eosid="$1" grep "Login request.*$eosid" "$SERVER_LOG_PATH" | tail -1 | awk -F "Name=| userId:" '{print $2}' | tr -d "\r" } # Wait until game port is open -while ! nc -uz 127.0.0.1 "${PORT}"; do +while ! port_check; do sleep 5s LogInfo "Waiting for server start for show player logging..." done -# joins=() last_line=0 while true; do server_pid=$(pidof LongvinterServer-Linux-Shipping) @@ -37,9 +36,6 @@ while true; do # Notify Discord and log all players who have joined *"Join succeeded"* ) player_name="$(awk -F "Join succeeded: " '{print $NF}' <<< "$log")" - # eosid="$(get_eosid "$(grep -m 1 "?Name=$player_name userId:" "$SERVER_LOG_PATH")")" - # joins+=("$eosid") - LogInfo "${player_name} has joined" # Replace ${player_name} with actual player's name @@ -48,9 +44,7 @@ while true; do # Notify Discord and log all players who have left *"RemovePlayer"* ) eosid="$(get_eosid "$log")" - player_name="$(get_playername "$eosid")" - # mapfile -t joins < <(tr ' ' '\n' <<< "${joins[@]/$eosid}" | grep -v ^$) - + player_name="$(eosid_to_playername "$eosid")" LogInfo "${player_name} has left" # Replace ${player_name} with actual player's name @@ -60,4 +54,4 @@ while true; do done fi sleep "${PLAYER_LOGGING_POLL_PERIOD}s" -done \ No newline at end of file +done diff --git a/scripts/restore.sh b/scripts/restore.sh index e9c7f9a..791c69f 100644 --- a/scripts/restore.sh +++ b/scripts/restore.sh @@ -6,10 +6,10 @@ source "/home/steam/server/variables.sh" source "/home/steam/server/helper_functions.sh" # Restore path -RESTORE_PATH="$GIT_REPO_PATH/Longvinter" +RESTORE_PATH="$DATA_DIR/Longvinter" # Copy the save file before restore temporary path -TMP_SAVE_PATH="$BACKUP_DIRECTORY_PATH/restore-"$(date +"%s") +TMP_SAVE_PATH="$BACKUP_DIR/restore-$(date +"%Y-%m-%d_%H-%M-%S")" # shellcheck disable=SC2317 term_error_handler() { @@ -35,18 +35,9 @@ restore_error_handler() { exit 1 } -# Timestamp included in the file name is converted to date and added -add_date() { - local stamp - while read -r path; do - stamp=$(basename "$path" | tr -cd "0-9") - echo "$path ($(date -d @"$stamp" "+%Y.%m.%d %H:%M:%S"))" - done -} - # Show up backup list LogInfo "Backup List:" -mapfile -t BACKUP_FILES < <(find "$BACKUP_DIRECTORY_PATH" -type f -name "*.tar.gz" | sort | add_date) +mapfile -t BACKUP_FILES < <(find "$BACKUP_DIR" -type f -name "*.tar.gz" | sort) select BACKUP_FILE in "${BACKUP_FILES[@]}"; do if [ -n "$BACKUP_FILE" ]; then LogInfo "Selected backup: $BACKUP_FILE" @@ -56,7 +47,6 @@ select BACKUP_FILE in "${BACKUP_FILES[@]}"; do fi done -BACKUP_FILE="${BACKUP_FILE%.tar.gz*}.tar.gz" if [ -f "$BACKUP_FILE" ]; then LogInfo "This script has been designed to help you restore; however, I am not responsible for any data loss. It is recommended that you create a backup beforehand, and in the event of script failure, be prepared to restore it manually." LogInfo "Do you understand the above and would you like to proceed with this command?" @@ -100,7 +90,7 @@ if [ -f "$BACKUP_FILE" ]; then fi # Create tmp directory - TMP_PATH=$(mktemp -d -p "$BACKUP_DIRECTORY_PATH") + TMP_PATH=$(mktemp -d -p "$BACKUP_DIR") if [ "$(id -u)" -eq 0 ]; then chown steam:steam "$TMP_PATH" fi @@ -129,4 +119,4 @@ if [ -f "$BACKUP_FILE" ]; then else LogError "The selected backup file does not exist." exit 1 -fi \ No newline at end of file +fi diff --git a/scripts/start.sh b/scripts/start.sh index 5dbc047..3a91f11 100644 --- a/scripts/start.sh +++ b/scripts/start.sh @@ -10,18 +10,7 @@ dirExists "$DATA_DIR" || exit isWritable "$DATA_DIR" || exit isExecutable "$DATA_DIR" || exit -cd "$GIT_REPO_PATH" || exit 1 - -if [ -n "$TARGET_COMMIT_ID" ] && ! IsValidCommitID "$TARGET_COMMIT_ID"; then - LogError "Invalid TARGET_COMMIT_ID($TARGET_COMMIT_ID)" - LogError "Please change the value and restart the server." - DiscordMessage "Error" "Invalid TARGET_COMMIT_ID($TARGET_COMMIT_ID). Please change the value and restart the server." "failure" - # This is written because GitHub API can only be used 60 times per hour - sleep infinity - exit 1 -fi - -InstallSteamapp +cd "$DATA_DIR" || exit 1 IsInstalled ServerInstalled=$? @@ -37,22 +26,27 @@ if [ "$ServerInstalled" == 0 ] && [ "${UPDATE_ON_BOOT,,}" == true ]; then IsUpdateRequired=$? if [ "$IsUpdateRequired" == 0 ]; then LogAction "Starting Update" - UpdateServer + InstallServer fi fi # Check if the architecture is arm64 if [ "$ARCHITECTURE" == "arm64" ]; then - sed -i "s|^\(\"\$UE4_PROJECT_ROOT\/Longvinter\/Binaries\/Linux\/LongvinterServer-Linux-Shipping\" Longvinter \"\$@\"\)|LD_LIBRARY_PATH=/home/steam/steamcmd/linux64:\$LD_LIBRARY_PATH /usr/local/bin/box64 \1|" "./LongvinterServer.sh" + # create an arm64 version of ./LongvinterServer.sh + cp ./LongvinterServer.sh ./LongvinterServer-arm64.sh + + sed -i "s|^\(\"\$UE4_PROJECT_ROOT\/Longvinter\/Binaries\/Linux\/LongvinterServer-Linux-Shipping\" Longvinter \"\$@\"\)|LD_LIBRARY_PATH=/home/steam/steamcmd/linux64:\$LD_LIBRARY_PATH /usr/local/bin/box64 \1|" "./LongvinterServer-arm64.sh" + chmod +x ./LongvinterServer-arm64.sh + STARTCOMMAND=("./LongvinterServer-arm64.sh") +else + STARTCOMMAND=("./LongvinterServer.sh") fi -STARTCOMMAND=("./LongvinterServer.sh") -#Validate Installation +# Validate Installation if ! fileExists "${STARTCOMMAND[0]}"; then LogError "Server Not Installed Properly" exit 1 fi -chmod +x "${STARTCOMMAND[0]}" isReadable "${STARTCOMMAND[0]}" || exit isExecutable "${STARTCOMMAND[0]}" || exit @@ -62,10 +56,6 @@ if [ -n "${PORT}" ]; then STARTCOMMAND+=("-Port=${PORT}") fi -if [ -n "${QUERY_PORT}" ]; then - STARTCOMMAND+=("-QueryPort=${QUERY_PORT}") -fi - LogAction "Checking for available container updates" container_version_check @@ -73,7 +63,7 @@ LogAction "GENERATING CONFIG" if [ "${DISABLE_GENERATE_SETTINGS,,}" = true ]; then LogWarn "Env vars will not be applied due to DISABLE_GENERATE_SETTINGS being set to TRUE!" if [ ! -f "$CONFIG_FILE_FULL_PATH" ]; then - cp "$CONFIG_FILE_FULL_PATH".default "$CONFIG_FILE_FULL_PATH" + /home/steam/server/compile-settings.sh || exit fi else LogInfo "Using Env vars to create Game.ini" @@ -100,7 +90,7 @@ fi if [ "${AUTO_REBOOT_ENABLED,,}" = true ]; then LogInfo "AUTO_REBOOT_ENABLED=${AUTO_REBOOT_ENABLED,,}" LogInfo "Adding cronjob for auto rebooting" - echo "$AUTO_REBOOT_CRON_EXPRESSION bash /usr/local/bin/reboot" >> "/home/steam/server/crontab" + echo "$AUTO_REBOOT_CRON_EXPRESSION bash /home/steam/server/auto_reboot.sh" >> "/home/steam/server/crontab" supercronic -quiet -test "/home/steam/server/crontab" || exit fi @@ -112,7 +102,11 @@ else fi if [ "${ENABLE_PLAYER_LOGGING,,}" = true ] && [[ "${PLAYER_LOGGING_POLL_PERIOD}" =~ ^[0-9]+$ ]]; then - /home/steam/server/player_logging.sh & + if [[ "$(id -u)" -eq 0 ]]; then + su steam -c /home/steam/server/player_logging.sh & + else + /home/steam/server/player_logging.sh & + fi fi diff --git a/scripts/update.sh b/scripts/update.sh index 191b6bb..c460c9a 100644 --- a/scripts/update.sh +++ b/scripts/update.sh @@ -22,14 +22,13 @@ if [ "${UPDATE_ON_BOOT,,}" != true ]; then exit 1 fi -TARGET_COMMIT="${TARGET_COMMIT_ID:-$LATEST_COMMIT}" - countdown_message "${AUTO_UPDATE_WARN_MINUTES}" "${AUTO_UPDATE_WARN_MESSAGE}" "${AUTO_UPDATE_WARN_REMAINING_TIMES}" countdown_exit_code=$? case "${countdown_exit_code}" in 0 ) wait_save "Update" "Waiting for the server to be saved before update..." "warn" "$DISCORD_PRE_UPDATE_BOOT_MESSAGE_ENABLED" "$DISCORD_PRE_UPDATE_BOOT_MESSAGE_URL" - LogAction "Updating the server from ${CURRENT_COMMIT:0:7} to ${TARGET_COMMIT:0:7}" + LogAction "Updating the server from $CURRENT_MANIFEST to $TARGET_MANIFEST." + rm "$MANIFEST_PATH" backup shutdown_server ;; diff --git a/scripts/variables.sh b/scripts/variables.sh index 592d1ae..9b3365b 100644 --- a/scripts/variables.sh +++ b/scripts/variables.sh @@ -2,16 +2,14 @@ export HOME="/home/steam" export DATA_DIR="/data" -export GIT_REPO_NAME="longvinter-linux-server" -export GIT_REPO_BRANCH="main" -export GIT_REPO_URL="https://github.com/Uuvana-Studios/$GIT_REPO_NAME" -export GIT_REPO_PATH="$DATA_DIR" -export GIT_REPO_API="${GIT_REPO_URL/github\.com/api.github.com\/repos}" -export BACKUP_DIRECTORY_PATH="$GIT_REPO_PATH/Longvinter/Backup" -export SERVER_LOG_DIR="$GIT_REPO_PATH/Longvinter/Saved/Logs" +export BACKUP_DIR="$DATA_DIR/backups" +export SERVER_LOG_DIR="$DATA_DIR/Longvinter/Saved/Logs" export SERVER_LOG_PATH="$SERVER_LOG_DIR/Longvinter.log" export SERVER_CONFIG_PATH="/Longvinter/Saved/Config/LinuxServer/Game.ini" -export CONFIG_FILE_FULL_PATH="$GIT_REPO_PATH$SERVER_CONFIG_PATH" +export CONFIG_FILE_FULL_PATH="$DATA_DIR$SERVER_CONFIG_PATH" +export APPID=1639880 +export DEPOTID=1639882 +export MANIFEST_PATH="$DATA_DIR/steamapps/appmanifest_$APPID.acf" ARCHITECTURE=$(dpkg --print-architecture) PAGESIZE=$(getconf PAGESIZE) @@ -26,7 +24,7 @@ export CFG_SERVER_MOTD=${CFG_SERVER_MOTD:-"Welcome to Longvinter Island!"} export CFG_MAX_PLAYERS=${CFG_MAX_PLAYERS:-32} export CFG_PASSWORD=${CFG_PASSWORD} export CFG_COMMUNITY_WEBSITE=${CFG_COMMUNITY_WEBSITE:-"www.longvinter.com"} -export CFG_SERVER_TAG=${CFG_SERVER_TAG:-"none"} +export CFG_TAG=${CFG_TAG:-"none"} export CFG_COOP_PLAY=${CFG_COOP_PLAY:-false} export CFG_COOP_SPAWN=${CFG_COOP_SPAWN:-0} export CFG_CHECK_VPN=${CFG_CHECK_VPN:-true} @@ -35,10 +33,10 @@ export CFG_DISABLE_WANDERING_TRADERS=${CFG_DISABLE_WANDERING_TRADERS:-false} export CFG_SERVER_REGION=${CFG_SERVER_REGION} export CFG_ADMIN_STEAM_ID=${CFG_ADMIN_STEAM_ID} -export CFG_ENABLE_PVP=${CFG_ENABLE_PVP:-true} +export CFG_PVP=${CFG_PVP:-true} export CFG_TENT_DECAY=${CFG_TENT_DECAY:-true} export CFG_MAX_TENTS=${CFG_MAX_TENTS:-2} -export CFG_RESTART_TIME_24H=${CFG_RESTART_TIME_24H} +export CFG_RESTART_TIME_24H=${CFG_RESTART_TIME_24H:-"-1"} export CFG_SAVE_BACKUPS=${CFG_SAVE_BACKUPS:-false} export CFG_HARDCORE=${CFG_HARDCORE:-false} export CFG_MONEY_DROP_MULTIPLIER=${CFG_MONEY_DROP_MULTIPLIER:-"0.0"}