├── .github └── workflows │ ├── publish_image.yaml │ ├── publish_proton_image.yaml │ └── release_charts.yaml ├── LICENSE ├── README.md ├── container ├── compose.yaml ├── proton │ ├── Dockerfile │ ├── enshrouded_server_example.json │ └── entrypoint.sh └── wine │ ├── Dockerfile │ ├── enshrouded_server_example.json │ ├── entrypoint.sh │ └── winetricks.sh ├── helm ├── Chart.yaml ├── README.md ├── templates │ ├── _helpers.tpl │ ├── deployment.yaml │ ├── password-secret.yaml │ ├── pvc.yaml │ └── service.yaml └── values.yaml ├── kubernetes-manifests ├── README.md ├── enshrouded-ns-privs.yaml ├── enshrouded-server_configmap.yaml ├── service-cilium.yaml ├── service-nginx.yaml └── statefulset.yaml └── makefile /.github/workflows/publish_image.yaml: -------------------------------------------------------------------------------- 1 | name: Build and push Wine based image 2 | on: 3 | workflow_dispatch: 4 | 5 | jobs: 6 | build-push: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Set up Docker Buildx 10 | uses: docker/setup-buildx-action@v3 11 | - name: Login to Docker Hub 12 | uses: docker/login-action@v3 13 | with: 14 | username: ${{ secrets.DOCKERHUB_USERNAME }} 15 | password: ${{ secrets.DOCKERHUB_TOKEN }} 16 | - name: Build and push 17 | uses: docker/build-push-action@v6 18 | with: 19 | context: "{{defaultContext}}:/container/wine" 20 | file: Dockerfile 21 | push: true 22 | tags: | 23 | ${{ secrets.DOCKERHUB_USERNAME }}/enshrouded-dedicated-server:wine-latest 24 | -------------------------------------------------------------------------------- /.github/workflows/publish_proton_image.yaml: -------------------------------------------------------------------------------- 1 | name: Build and push GE-Proton based image 2 | on: 3 | release: 4 | types: [published] 5 | jobs: 6 | build-push: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Set up Docker Buildx 10 | uses: docker/setup-buildx-action@v3 11 | - name: Login to Docker Hub 12 | uses: docker/login-action@v3 13 | with: 14 | username: ${{ secrets.DOCKERHUB_USERNAME }} 15 | password: ${{ secrets.DOCKERHUB_TOKEN }} 16 | - name: Build and push 17 | uses: docker/build-push-action@v6 18 | with: 19 | context: "{{defaultContext}}:/container/proton" 20 | file: Dockerfile 21 | push: true 22 | tags: | 23 | ${{ secrets.DOCKERHUB_USERNAME }}/enshrouded-dedicated-server:latest 24 | ${{ secrets.DOCKERHUB_USERNAME }}/enshrouded-dedicated-server:proton-latest 25 | ${{ secrets.DOCKERHUB_USERNAME }}/enshrouded-dedicated-server:proton-${{ github.event.release.tag_name }} 26 | -------------------------------------------------------------------------------- /.github/workflows/release_charts.yaml: -------------------------------------------------------------------------------- 1 | name: Release to Charts Repo 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | commit-to-repo: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Checkout source repository 14 | uses: actions/checkout@v3 15 | 16 | - name: Commit and push changes to charts repo 17 | env: 18 | GITHUB_TOKEN: ${{ secrets.ACTIONS_GITHUB_TOKEN }} 19 | CHART_NAME: enshrouded-dedicated-server 20 | run: | 21 | git config --global user.name "github-actions[bot]" 22 | git config --global user.email "github-actions[bot]@users.noreply.github.com" 23 | git clone https://github.com/jsknnr/helm-charts.git 24 | cd helm-charts/charts 25 | [ ! -d "${{env.CHART_NAME}}" ] && mkdir "${{env.CHART_NAME}}" 26 | cp -r ../../helm/* ./"${{env.CHART_NAME}}"/ 27 | git remote set-url origin 'https://${{secrets.ACTIONS_GITHUB_TOKEN}}@github.com/jsknnr/helm-charts.git' 28 | git add . 29 | git commit -m "Automated commit from GitHub Actions for ${{env.CHART_NAME}}" 30 | git push origin main 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 John Skinner 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # enshrouded-server 2 | 3 | [![Static Badge](https://img.shields.io/badge/DockerHub-blue)](https://hub.docker.com/r/sknnr/enshrouded-dedicated-server) ![Docker Pulls](https://img.shields.io/docker/pulls/sknnr/enshrouded-dedicated-server) [![Static Badge](https://img.shields.io/badge/GitHub-green)](https://github.com/jsknnr/enshrouded-server) ![GitHub Repo stars](https://img.shields.io/github/stars/jsknnr/enshrouded-server) 4 | 5 | Run Enshrouded dedicated server in a container. Optionally includes helm chart for running in Kubernetes. 6 | 7 | **Disclaimer:** This is not an official image. No support, implied or otherwise is offered to any end user by the author or anyone else. Feel free to do what you please with the contents of this repo. 8 | 9 | ## Usage 10 | 11 | The processes within the container do **NOT** run as root. Everything runs as the user steam (gid:10000/uid:10000 by default). If you exec into the container, you will drop into `/home/steam` as the steam user. Enshrouded will be installed to `/home/steam/enshrouded`. Any persistent volumes should be mounted to `/home/steam/enshrouded/savegame` and be owned by 10000:10000. 12 | 13 | If you absolutely require to run the process in the container as a gid/uid other than 10000, you can build your own image based on my dockerfile. Instructions are covered [Here](https://github.com/jsknnr/enshrouded-server/issues/51) 14 | 15 | ### Proton and Wine based images 16 | 17 | The `latest` tag is now based on the Proton build instead of Wine. This should be seamless. Outside of `latest`, there is `wine-$realease_version` and `proton-$release_version` with `$release_version` being the version of the release from GitHub. I am no longer updating the Wine version of this image. 18 | 19 | ### Ports 20 | 21 | | Port | Protocol | Default | 22 | | ---------- | -------- | ------- | 23 | | Query Port | UDP | 15637 | 24 | 25 | ### Environment Variables 26 | 27 | | Name | Description | Default | Required | 28 | | --------------- | ----------------------------------------------------------------------- | ------------------------ | -------- | 29 | | SERVER_NAME | Name for the Server | Enshrouded Containerized | False | 30 | | SERVER_PASSWORD | Password for the server | None | False | 31 | | PORT | Port for steam query of server | 15637 | False | 32 | | SERVER_SLOTS | Number of slots for connections (Max 16) | 16 | False | 33 | | SERVER_IP | IP address for server to listen on | 0.0.0.0 | False | 34 | | EXTERNAL_CONFIG | If you would rather manually supply a config file, set this to true (1) | 0 | False | 35 | 36 | **Note:** SERVER_IP is ignored if using Helm because that isn't how Kubernetes works. 37 | 38 | ### Docker 39 | 40 | To run the container in Docker, run the following command: 41 | 42 | ```bash 43 | docker volume create enshrouded-persistent-data 44 | docker run \ 45 | --detach \ 46 | --name enshrouded-server \ 47 | --mount type=volume,source=enshrouded-persistent-data,target=/home/steam/enshrouded/savegame \ 48 | --publish 15637:15637/udp \ 49 | --env=SERVER_NAME='Enshrouded Containerized Server' \ 50 | --env=SERVER_SLOTS=16 \ 51 | --env=SERVER_PASSWORD='ChangeThisPlease' \ 52 | --env=PORT=15637 \ 53 | sknnr/enshrouded-dedicated-server:latest 54 | ``` 55 | 56 | ### Docker Compose 57 | 58 | To use Docker Compose, either clone this repo or copy the `compose.yaml` file out of the `container` directory to your local machine. Edit the compose file to change the environment variables to the values you desire and then save the changes. Once you have made your changes, from the same directory that contains the compose and the env files, simply run: 59 | 60 | ```bash 61 | docker-compose up -d 62 | ``` 63 | 64 | To bring the container down: 65 | 66 | ```bash 67 | docker-compose down 68 | ``` 69 | 70 | compose.yaml file: 71 | 72 | ```yaml 73 | version: "3" 74 | services: 75 | enshrouded: 76 | image: sknnr/enshrouded-dedicated-server:latest 77 | ports: 78 | - "15637:15637/udp" 79 | environment: 80 | - SERVER_NAME=Enshrouded Containerized 81 | - SERVER_PASSWORD=PleaseChangeMe 82 | - PORT=15637 83 | - SERVER_SLOTS=16 84 | - SERVER_IP=0.0.0.0 85 | volumes: 86 | - enshrouded-persistent-data:/home/steam/enshrouded/savegame 87 | 88 | volumes: 89 | enshrouded-persistent-data: 90 | ``` 91 | 92 | ### Podman 93 | 94 | To run the container in Podman, run the following command: 95 | 96 | ```bash 97 | podman volume create enshrouded-persistent-data 98 | podman run \ 99 | --detach \ 100 | --name enshrouded-server \ 101 | --mount type=volume,source=enshrouded-persistent-data,target=/home/steam/enshrouded/savegame \ 102 | --publish 15637:15637/udp \ 103 | --env=SERVER_NAME='Enshrouded Containerized Server' \ 104 | --env=SERVER_SLOTS=16 \ 105 | --env=SERVER_PASSWORD='ChangeThisPlease' \ 106 | --env=PORT=15637 \ 107 | docker.io/sknnr/enshrouded-dedicated-server:latest 108 | ``` 109 | 110 | ### Quadlet 111 | 112 | To run the container with Podman's new quadlet subsystem, make a file under (when running as root) /etc/containers/systemd/enshrouded.container containing: 113 | 114 | ```text 115 | [Unit] 116 | Description=Enshrouded Game Server 117 | 118 | [Container] 119 | Image=docker.io/sknnr/enshrouded-dedicated-server:latest 120 | Volume=enshrouded-persistent-data:/home/steam/enshrouded/savegame 121 | PublishPort=15637:15637/udp 122 | ContainerName=enshrouded-server 123 | Environment=SERVER_NAME="Enshrouded Containerized Server" 124 | Environment=SERVER_PASSWORD="ChangeThisPlease" 125 | Environment=PORT=15637 126 | Environment=SERVER_SLOTS=16 127 | 128 | [Service] 129 | # Restart service when sleep finishes 130 | Restart=always 131 | # Extend Timeout to allow time to pull the image 132 | TimeoutStartSec=900 133 | 134 | [Install] 135 | # Start by default on boot 136 | WantedBy=multi-user.target default.target 137 | ``` 138 | 139 | ### Kubernetes 140 | 141 | I've built a Helm chart and have included it in the `helm` directory within this repo. Modify the `values.yaml` file to your liking and install the chart into your cluster. Be sure to create and specify a namespace as I did not include a template for provisioning a namespace. 142 | 143 | The chart in this repo is also hosted in my helm-charts repository [here](https://jsknnr.github.io/helm-charts) 144 | 145 | To install this chart from my helm-charts repository: 146 | 147 | ```bash 148 | helm repo add jsknnr https://jsknnr.github.io/helm-charts 149 | helm repo update 150 | ``` 151 | 152 | To install the chart from the repo: 153 | 154 | ```bash 155 | helm install enshrouded jsknnr/enshrouded-dedicated-server --values myvalues.yaml 156 | # Where myvalues.yaml is your copy of the Values.yaml file with the settings that you want 157 | ``` 158 | 159 | ## Troubleshooting 160 | 161 | ### Connectivity 162 | 163 | If you are having issues connecting to the server once the container is deployed, I promise the issue is not with this image. You need to make sure that the ports 15636 and 15637 (or whichever ones you decide to use) are open on your router as well as the container host where this container image is running. You will also have to port-forward the game-port and query-port from your router to the private IP address of the container host where this image is running. After this has been done correctly and you are still experiencing issues, your internet service provider (ISP) may be blocking the ports and you should contact them to troubleshoot. 164 | 165 | For additional help, refer to this closed issue where some folks were able to debug their issues. It may be of help.
166 | https://github.com/jsknnr/enshrouded-server/issues/16 167 | 168 | ### Storage 169 | 170 | I recommend having Docker or Podman manage the volume that gets mounted into the container. However, if you absolutely must bind mount a directory into the container you need to make sure that on your container host the directory you are bind mounting is owned by 10000:10000 by default (`chown -R 10000:10000 /path/to/directory`). If the ownership of the directory is not correct the container will not start as the server will be unable to persist the savegame. 171 | -------------------------------------------------------------------------------- /container/compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | enshrouded: 4 | image: sknnr/enshrouded-dedicated-server:latest 5 | ports: 6 | - "15637:15637/udp" 7 | environment: 8 | - SERVER_NAME=Enshrouded Containerized 9 | - SERVER_PASSWORD=PleaseChangeMe 10 | - PORT=15637 11 | - SERVER_SLOTS=16 12 | - SERVER_IP=0.0.0.0 13 | volumes: 14 | - enshrouded-persistent-data:/home/steam/enshrouded/savegame 15 | 16 | volumes: 17 | enshrouded-persistent-data: 18 | -------------------------------------------------------------------------------- /container/proton/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:12-slim 2 | 3 | ARG CONTAINER_GID=10000 4 | ARG CONTAINER_UID=10000 5 | 6 | ENV DEBIAN_FRONTEND "noninteractive" 7 | ENV STEAM_APP_ID "2278520" 8 | ENV HOME "/home/steam" 9 | ENV ENSHROUDED_PATH "/home/steam/enshrouded" 10 | ENV ENSHROUDED_CONFIG "${ENSHROUDED_PATH}/enshrouded_server.json" 11 | ENV EXTERNAL_CONFIG 0 12 | ENV GE_PROTON_VERSION "9-25" 13 | ENV GE_PROTON_URL "https://github.com/GloriousEggroll/proton-ge-custom/releases/download/GE-Proton${GE_PROTON_VERSION}/GE-Proton${GE_PROTON_VERSION}.tar.gz" 14 | ENV STEAMCMD_PATH="/home/steam/steamcmd" 15 | ENV STEAM_SDK64_PATH="/home/steam/.steam/sdk64" 16 | ENV STEAM_SDK32_PATH="/home/steam/.steam/sdk32" 17 | ENV STEAM_COMPAT_CLIENT_INSTALL_PATH "$STEAMCMD_PATH" 18 | ENV STEAM_COMPAT_DATA_PATH "${STEAMCMD_PATH}/steamapps/compatdata/${STEAM_APP_ID}" 19 | ENV UMU_ID 0 20 | 21 | RUN groupadd -g $CONTAINER_GID steam \ 22 | && useradd -g $CONTAINER_GID -u $CONTAINER_UID -m steam \ 23 | && dpkg --add-architecture i386 \ 24 | && apt-get update \ 25 | && apt-get install --no-install-recommends -y \ 26 | procps \ 27 | ca-certificates \ 28 | winbind \ 29 | dbus \ 30 | libfreetype6 \ 31 | curl \ 32 | jq \ 33 | locales \ 34 | lib32gcc-s1 \ 35 | && echo 'LANG="en_US.UTF-8"' > /etc/default/locale \ 36 | && echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen \ 37 | && locale-gen \ 38 | && rm -f /etc/machine-id \ 39 | && dbus-uuidgen --ensure=/etc/machine-id \ 40 | && rm -rf /var/lib/apt/lists/* \ 41 | && apt-get clean \ 42 | && apt-get autoremove -y 43 | 44 | USER steam 45 | 46 | RUN mkdir "$ENSHROUDED_PATH" \ 47 | && mkdir -p "${ENSHROUDED_PATH}/savegame" \ 48 | && mkdir -p "${STEAMCMD_PATH}/compatibilitytools.d" \ 49 | && mkdir -p "${STEAMCMD_PATH}/steamapps/compatdata/${STEAM_APP_ID}" \ 50 | && curl -sqL https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz | tar zxvf - -C ${STEAMCMD_PATH} \ 51 | && chmod +x ${STEAMCMD_PATH}/steamcmd.sh \ 52 | && ${STEAMCMD_PATH}/steamcmd.sh +quit \ 53 | && mkdir -p /home/steam/.steam \ 54 | && ln -s ${STEAMCMD_PATH}/linux64 ${STEAM_SDK64_PATH} \ 55 | && ln -s ${STEAM_SDK64_PATH}/steamclient.so ${STEAM_SDK64_PATH}/steamservice.so \ 56 | && ln -s ${STEAMCMD_PATH}/linux32 ${STEAM_SDK32_PATH} \ 57 | && ln -s ${STEAM_SDK32_PATH}/steamclient.so ${STEAM_SDK32_PATH}/steamservice.so \ 58 | && curl -sqL "$GE_PROTON_URL" | tar zxvf - -C "${STEAMCMD_PATH}/compatibilitytools.d/" 59 | 60 | COPY entrypoint.sh /home/steam/entrypoint.sh 61 | COPY enshrouded_server_example.json /home/steam/enshrouded_server_example.json 62 | 63 | WORKDIR /home/steam 64 | 65 | CMD ["/home/steam/entrypoint.sh"] 66 | -------------------------------------------------------------------------------- /container/proton/enshrouded_server_example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Enshrouded Server", 3 | "saveDirectory": "./savegame", 4 | "logDirectory": "./logs", 5 | "ip": "0.0.0.0", 6 | "queryPort": 15637, 7 | "slotCount": 16, 8 | "gameSettingsPreset": "Default", 9 | "gameSettings": { 10 | "playerHealthFactor": 1, 11 | "playerManaFactor": 1, 12 | "playerStaminaFactor": 1, 13 | "playerBodyHeatFactor": 1, 14 | "enableDurability": true, 15 | "enableStarvingDebuff": false, 16 | "foodBuffDurationFactor": 1, 17 | "fromHungerToStarving": 600000000000, 18 | "shroudTimeFactor": 1, 19 | "tombstoneMode": "AddBackpackMaterials", 20 | "enableGliderTurbulences": true, 21 | "weatherFrequency": "Normal", 22 | "miningDamageFactor": 1, 23 | "plantGrowthSpeedFactor": 1, 24 | "resourceDropStackAmountFactor": 1, 25 | "factoryProductionSpeedFactor": 1, 26 | "perkUpgradeRecyclingFactor": 0.500000, 27 | "perkCostFactor": 1, 28 | "experienceCombatFactor": 1, 29 | "experienceMiningFactor": 1, 30 | "experienceExplorationQuestsFactor": 1, 31 | "randomSpawnerAmount": "Normal", 32 | "aggroPoolAmount": "Normal", 33 | "enemyDamageFactor": 1, 34 | "enemyHealthFactor": 1, 35 | "enemyStaminaFactor": 1, 36 | "enemyPerceptionRangeFactor": 1, 37 | "bossDamageFactor": 1, 38 | "bossHealthFactor": 1, 39 | "threatBonus": 1, 40 | "pacifyAllEnemies": false, 41 | "tamingStartleRepercussion": "LoseSomeProgress", 42 | "dayTimeDuration": 1800000000000, 43 | "nightTimeDuration": 720000000000 44 | }, 45 | "userGroups": [ 46 | { 47 | "name": "Default", 48 | "password": "", 49 | "canKickBan": false, 50 | "canAccessInventories": true, 51 | "canEditBase": true, 52 | "canExtendBase": true, 53 | "reservedSlots": 0 54 | } 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /container/proton/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Quick function to generate a timestamp 4 | timestamp () { 5 | date +"%Y-%m-%d %H:%M:%S,%3N" 6 | } 7 | 8 | shutdown () { 9 | echo "" 10 | echo "$(timestamp) INFO: Recieved SIGTERM, shutting down gracefully" 11 | kill -2 $enshrouded_pid 12 | } 13 | 14 | # Set our trap 15 | trap 'shutdown' TERM 16 | 17 | # Validate arguments 18 | if [ -z "$SERVER_NAME" ]; then 19 | SERVER_NAME='Enshrouded Containerized' 20 | echo "$(timestamp) WARN: SERVER_NAME not set, using default: Enshrouded Containerized" 21 | fi 22 | 23 | if [ -z "$SERVER_PASSWORD" ]; then 24 | echo "$(timestamp) WARN: SERVER_PASSWORD not set, server will be open to the public" 25 | fi 26 | 27 | if [ -z "$PORT" ]; then 28 | PORT='15637' 29 | echo "$(timestamp) WARN: PORT not set, using default: 15637" 30 | fi 31 | 32 | if [ -z "$SERVER_SLOTS" ]; then 33 | SERVER_SLOTS='16' 34 | echo "$(timestamp) WARN: SERVER_SLOTS not set, using default: 16" 35 | fi 36 | 37 | if [ -z "$SERVER_IP" ]; then 38 | SERVER_IP='0.0.0.0' 39 | echo "$(timestamp) WARN: SERVER_IP not set, using default: 0.0.0.0" 40 | fi 41 | 42 | # Install/Update Enshrouded 43 | echo "$(timestamp) INFO: Updating Enshrouded Dedicated Server" 44 | ${STEAMCMD_PATH}/steamcmd.sh +@sSteamCmdForcePlatformType windows +force_install_dir "$ENSHROUDED_PATH" +login anonymous +app_update ${STEAM_APP_ID} validate +quit 45 | 46 | # Check that steamcmd was successful 47 | if [ $? != 0 ]; then 48 | echo "$(timestamp) ERROR: steamcmd was unable to successfully initialize and update Enshrouded" 49 | exit 1 50 | fi 51 | 52 | # Copy example server config if not already present 53 | if [ $EXTERNAL_CONFIG -eq 0 ]; then 54 | if ! [ -f "${ENSHROUDED_PATH}/enshrouded_server.json" ]; then 55 | echo "$(timestamp) INFO: Enshrouded server config not present, copying example" 56 | cp /home/steam/enshrouded_server_example.json ${ENSHROUDED_PATH}/enshrouded_server.json 57 | fi 58 | fi 59 | 60 | # Check that savegame directory exists, if not create 61 | if ! [ -d "${ENSHROUDED_PATH}/savegame" ]; then 62 | mkdir -p "${ENSHROUDED_PATH}/savegame" 63 | fi 64 | 65 | # Check for proper save permissions 66 | if ! touch "${ENSHROUDED_PATH}/savegame/test"; then 67 | echo "" 68 | echo "$(timestamp) ERROR: The ownership of /home/steam/enshrouded/savegame is not correct and the server will not be able to save..." 69 | echo "the directory that you are mounting into the container needs to be owned by 10000:10000" 70 | echo "from your container host attempt the following command 'chown -R 10000:10000 /your/enshrouded/folder'" 71 | echo "" 72 | exit 1 73 | fi 74 | 75 | rm "${ENSHROUDED_PATH}/savegame/test" 76 | 77 | # Modify server config to match our arguments 78 | if [ $EXTERNAL_CONFIG -eq 0 ]; then 79 | echo "$(timestamp) INFO: Updating Enshrouded Server configuration" 80 | tmpfile=$(mktemp) 81 | jq --arg n "$SERVER_NAME" '.name = $n' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG 82 | if [ -n "$SERVER_PASSWORD" ]; then 83 | jq --arg p "$SERVER_PASSWORD" '.userGroups[].password = $p' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG 84 | fi 85 | jq --arg q "$PORT" '.queryPort = ($q | tonumber)' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG 86 | jq --arg s "$SERVER_SLOTS" '.slotCount = ($s | tonumber)' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG 87 | jq --arg i "$SERVER_IP" '.ip = $i' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG 88 | else 89 | echo "$(timestamp) INFO: EXTERNAL_CONFIG set to true, not updating Enshrouded Server configuration" 90 | fi 91 | 92 | # Wine talks too much and it's annoying 93 | export WINEDEBUG=-all 94 | 95 | # Check that log directory exists, if not create 96 | if ! [ -d "${ENSHROUDED_PATH}/logs" ]; then 97 | mkdir -p "${ENSHROUDED_PATH}/logs" 98 | fi 99 | 100 | # Check that log file exists, if not create 101 | if ! [ -f "${ENSHROUDED_PATH}/logs/enshrouded_server.log" ]; then 102 | touch "${ENSHROUDED_PATH}/logs/enshrouded_server.log" 103 | fi 104 | 105 | # Link logfile to stdout of pid 1 so we can see logs 106 | ln -sf /proc/1/fd/1 "${ENSHROUDED_PATH}/logs/enshrouded_server.log" 107 | 108 | # Launch Enshrouded 109 | echo "$(timestamp) INFO: Starting Enshrouded Dedicated Server" 110 | 111 | ${STEAMCMD_PATH}/compatibilitytools.d/GE-Proton${GE_PROTON_VERSION}/proton run ${ENSHROUDED_PATH}/enshrouded_server.exe & 112 | 113 | # Find pid for enshrouded_server.exe 114 | timeout=0 115 | while [ $timeout -lt 11 ]; do 116 | if ps -e | grep "enshrouded_serv"; then 117 | enshrouded_pid=$(ps -e | grep "enshrouded_serv" | awk '{print $1}') 118 | break 119 | elif [ $timeout -eq 10 ]; then 120 | echo "$(timestamp) ERROR: Timed out waiting for enshrouded_server.exe to be running" 121 | exit 1 122 | fi 123 | sleep 6 124 | ((timeout++)) 125 | echo "$(timestamp) INFO: Waiting for enshrouded_server.exe to be running" 126 | done 127 | 128 | # Hold us open until we recieve a SIGTERM by opening a job waiting for the process to finish then calling `wait` 129 | tail --pid=$enshrouded_pid -f /dev/null & 130 | wait 131 | 132 | # Handle post SIGTERM from here (SIGTERM will cancel the `wait` immediately even though the job is not done yet) 133 | # Check if the enshrouded_server.exe process is still running, and if so, wait for it to close, indicating full shutdown, then go home 134 | if ps -e | grep "enshrouded_serv"; then 135 | tail --pid=$enshrouded_pid -f /dev/null 136 | fi 137 | 138 | # o7 139 | echo "$(timestamp) INFO: Shutdown complete." 140 | exit 0 141 | -------------------------------------------------------------------------------- /container/wine/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:12-slim 2 | 3 | ARG CONTAINER_GID=10000 4 | ARG CONTAINER_UID=10000 5 | 6 | ENV DEBIAN_FRONTEND "noninteractive" 7 | ENV ENSHROUDED_PATH "/home/steam/enshrouded" 8 | ENV ENSHROUDED_CONFIG "${ENSHROUDED_PATH}/enshrouded_server.json" 9 | ENV WINEPREFIX "/home/steam/.enshrouded_prefix" 10 | ENV WINEARCH "win64" 11 | 12 | RUN groupadd -g $CONTAINER_GID steam \ 13 | && useradd -g $CONTAINER_GID -u $CONTAINER_UID -m steam \ 14 | && dpkg --add-architecture i386 \ 15 | && apt-get update \ 16 | && apt-get install --no-install-recommends -y \ 17 | procps \ 18 | ca-certificates \ 19 | curl \ 20 | wget \ 21 | jq \ 22 | lib32gcc-s1 \ 23 | cabextract \ 24 | winbind \ 25 | xvfb \ 26 | && mkdir -pm755 /etc/apt/keyrings \ 27 | && wget -O /etc/apt/keyrings/winehq-archive.key https://dl.winehq.org/wine-builds/winehq.key \ 28 | && wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/debian/dists/bookworm/winehq-bookworm.sources \ 29 | && apt-get update \ 30 | && apt-get install -y --install-recommends winehq-stable \ 31 | && wget -O /usr/local/bin/winetricks https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks \ 32 | && chmod +x /usr/local/bin/winetricks \ 33 | && rm -rf /var/lib/apt/lists/* \ 34 | && apt-get clean \ 35 | && apt-get autoremove -y 36 | 37 | 38 | USER steam 39 | 40 | COPY entrypoint.sh /home/steam/entrypoint.sh 41 | COPY winetricks.sh /home/steam/winetricks.sh 42 | COPY enshrouded_server_example.json /home/steam/enshrouded_server_example.json 43 | 44 | RUN mkdir "$ENSHROUDED_PATH" \ 45 | && mkdir "$ENSHROUDED_PATH"/savegame \ 46 | && mkdir "$WINEPREFIX" \ 47 | && mkdir /home/steam/steamcmd \ 48 | && curl -sqL https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz | tar zxvf - -C /home/steam/steamcmd \ 49 | && chmod +x /home/steam/steamcmd/steamcmd.sh \ 50 | && /home/steam/winetricks.sh 51 | 52 | WORKDIR /home/steam 53 | 54 | CMD ["/home/steam/entrypoint.sh"] 55 | -------------------------------------------------------------------------------- /container/wine/enshrouded_server_example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Enshrouded Server", 3 | "saveDirectory": "./savegame", 4 | "logDirectory": "./logs", 5 | "ip": "0.0.0.0", 6 | "queryPort": 15637, 7 | "slotCount": 16, 8 | "gameSettingsPreset": "Default", 9 | "gameSettings": { 10 | "playerHealthFactor": 1, 11 | "playerManaFactor": 1, 12 | "playerStaminaFactor": 1, 13 | "playerBodyHeatFactor": 1, 14 | "enableDurability": true, 15 | "enableStarvingDebuff": false, 16 | "foodBuffDurationFactor": 1, 17 | "fromHungerToStarving": 600000000000, 18 | "shroudTimeFactor": 1, 19 | "tombstoneMode": "AddBackpackMaterials", 20 | "enableGliderTurbulences": true, 21 | "weatherFrequency": "Normal", 22 | "miningDamageFactor": 1, 23 | "plantGrowthSpeedFactor": 1, 24 | "resourceDropStackAmountFactor": 1, 25 | "factoryProductionSpeedFactor": 1, 26 | "perkUpgradeRecyclingFactor": 0.500000, 27 | "perkCostFactor": 1, 28 | "experienceCombatFactor": 1, 29 | "experienceMiningFactor": 1, 30 | "experienceExplorationQuestsFactor": 1, 31 | "randomSpawnerAmount": "Normal", 32 | "aggroPoolAmount": "Normal", 33 | "enemyDamageFactor": 1, 34 | "enemyHealthFactor": 1, 35 | "enemyStaminaFactor": 1, 36 | "enemyPerceptionRangeFactor": 1, 37 | "bossDamageFactor": 1, 38 | "bossHealthFactor": 1, 39 | "threatBonus": 1, 40 | "pacifyAllEnemies": false, 41 | "tamingStartleRepercussion": "LoseSomeProgress", 42 | "dayTimeDuration": 1800000000000, 43 | "nightTimeDuration": 720000000000 44 | }, 45 | "userGroups": [ 46 | { 47 | "name": "Default", 48 | "password": "", 49 | "canKickBan": false, 50 | "canAccessInventories": true, 51 | "canEditBase": true, 52 | "canExtendBase": true, 53 | "reservedSlots": 0 54 | } 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /container/wine/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Quick function to generate a timestamp 4 | timestamp () { 5 | date +"%Y-%m-%d %H:%M:%S,%3N" 6 | } 7 | 8 | shutdown () { 9 | echo "" 10 | echo "$(timestamp) INFO: Recieved SIGTERM, shutting down gracefully" 11 | kill -2 $enshrouded_pid 12 | } 13 | 14 | # Set our trap 15 | trap 'shutdown' TERM 16 | 17 | # Validate arguments 18 | if [ -z "$SERVER_NAME" ]; then 19 | SERVER_NAME='Enshrouded Containerized' 20 | echo "$(timestamp) WARN: SERVER_NAME not set, using default: Enshrouded Containerized" 21 | fi 22 | 23 | if [ -z "$SERVER_PASSWORD" ]; then 24 | echo "$(timestamp) WARN: SERVER_PASSWORD not set, server will be open to the public" 25 | fi 26 | 27 | if [ -z "$PORT" ]; then 28 | PORT='15637' 29 | echo "$(timestamp) WARN: PORT not set, using default: 15637" 30 | fi 31 | 32 | if [ -z "$SERVER_SLOTS" ]; then 33 | SERVER_SLOTS='16' 34 | echo "$(timestamp) WARN: SERVER_SLOTS not set, using default: 16" 35 | fi 36 | 37 | if [ -z "$SERVER_IP" ]; then 38 | SERVER_IP='0.0.0.0' 39 | echo "$(timestamp) WARN: SERVER_IP not set, using default: 0.0.0.0" 40 | fi 41 | 42 | # Install/Update Enshrouded 43 | echo "$(timestamp) INFO: Updating Enshrouded Dedicated Server" 44 | /home/steam/steamcmd/steamcmd.sh +@sSteamCmdForcePlatformType windows +force_install_dir "$ENSHROUDED_PATH" +login anonymous +app_update 2278520 validate +quit 45 | 46 | # Check that steamcmd was successful 47 | if [ $? != 0 ]; then 48 | echo "ERROR: steamcmd was unable to successfully initialize and update Enshrouded..." 49 | exit 1 50 | fi 51 | 52 | # Copy example server config if not already present 53 | if ! [ -f "${ENSHROUDED_PATH}/enshrouded_server.json" ]; then 54 | echo "$(timestamp) INFO: Enshrouded server config not present, copying example" 55 | cp /home/steam/enshrouded_server_example.json ${ENSHROUDED_PATH}/enshrouded_server.json 56 | fi 57 | 58 | # Check for proper save permissions 59 | if ! touch "${ENSHROUDED_PATH}/savegame/test"; then 60 | echo "" 61 | echo "$(timestamp) ERROR: The ownership of /home/steam/enshrouded/savegame is not correct and the server will not be able to save..." 62 | echo "the directory that you are mounting into the container needs to be owned by 10000:10000" 63 | echo "from your container host attempt the following command 'chown -R 10000:10000 /your/enshrouded/folder'" 64 | echo "" 65 | exit 1 66 | fi 67 | 68 | rm "${ENSHROUDED_PATH}/savegame/test" 69 | 70 | # Modify server config to match our arguments 71 | echo "$(timestamp) INFO: Updating Enshrouded Server configuration" 72 | tmpfile=$(mktemp) 73 | jq --arg n "$SERVER_NAME" '.name = $n' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG 74 | if [ -n "$SERVER_PASSWORD" ]; then 75 | jq --arg p "$SERVER_PASSWORD" '.userGroups[].password = $p' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG 76 | fi 77 | jq --arg q "$PORT" '.queryPort = ($q | tonumber)' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG 78 | jq --arg s "$SERVER_SLOTS" '.slotCount = ($s | tonumber)' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG 79 | jq --arg i "$SERVER_IP" '.ip = $i' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG 80 | 81 | # Wine talks too much and it's annoying 82 | export WINEDEBUG=-all 83 | 84 | # Launch Enshrouded 85 | echo "$(timestamp) INFO: Starting Enshrouded Dedicated Server" 86 | wine ${ENSHROUDED_PATH}/enshrouded_server.exe & 87 | 88 | # Find pid for enshrouded_server.exe 89 | timeout=0 90 | while [ $timeout -lt 11 ]; do 91 | if ps -e | grep "enshrouded_serv"; then 92 | enshrouded_pid=$(ps -e | grep "enshrouded_serv" | awk '{print $1}') 93 | break 94 | elif [ $timeout -eq 10 ]; then 95 | echo "$(timestamp) ERROR: Timed out waiting for enshrouded_server.exe to be running" 96 | exit 1 97 | fi 98 | sleep 6 99 | ((timeout++)) 100 | echo "$(timestamp) INFO: Waiting for enshrouded_server.exe to be running" 101 | done 102 | 103 | # Hold us open until we recieve a SIGTERM 104 | wait 105 | 106 | # Handle post SIGTERM from here 107 | # Hold us open until WSServer-Linux pid closes, indicating full shutdown, then go home 108 | tail --pid=$enshrouded_pid -f /dev/null 109 | 110 | # o7 111 | echo "$(timestamp) INFO: Shutdown complete." 112 | exit 0 113 | -------------------------------------------------------------------------------- /container/wine/winetricks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export DISPLAY=:1.0 3 | 4 | Xvfb :1 -screen 0 1024x768x16 & 5 | env WINEDLLOVERRIDES="mscoree=d" wineboot --init /nogui 6 | winetricks corefonts 7 | winetricks sound=disabled 8 | winetricks -q --force vcrun2022 9 | wine winecfg -v win10 10 | rm -rf /home/steam/.cache 11 | -------------------------------------------------------------------------------- /helm/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | name: enshrouded-dedicated-server 3 | version: 1.0.0 4 | description: Enshrouded dedicated server. 5 | keywords: 6 | - game 7 | - server 8 | - enshrouded 9 | home: https://github.com/jsknnr/enshrouded-server 10 | -------------------------------------------------------------------------------- /helm/README.md: -------------------------------------------------------------------------------- 1 | # enshrouded-dedicated-server 2 | 3 | ![Version: 1.0.0](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square) 4 | 5 | Enshrouded dedicated server. 6 | 7 | **Homepage:** 8 | 9 | ## Values 10 | 11 | | Key | Type | Default | Description | 12 | |-----|------|---------|-------------| 13 | | config.queryPort | int | `15637` | The port used by the game server | 14 | | config.serverName | string | `"Enshrouded Server"` | Server name | 15 | | config.serverPassword | string | `""` | Server password. If not set, password will be generated randomly. | 16 | | config.serverPasswordExistingSecretName | string | `""` | Existing secret name for server password. Must contain key named "password". If set `serverPassword` will be ignored. | 17 | | config.serverSlots | int | `16` | Number of server slots | 18 | | image.repository | string | `"sknnr/enshrouded-dedicated-server"` | | 19 | | image.tag | string | `"v2.0.5"` | | 20 | | resources.requests.cpu | float | `4` | | 21 | | resources.requests.memory | string | `"12G"` | | 22 | | service.annotations | object | `{}` | | 23 | | service.externalIPs | list | `[]` | | 24 | | service.type | string | `"LoadBalancer"` | | 25 | | volumes.dataPVC.size | string | `"50Gi"` | Size of the persistent volume | 26 | | volumes.storageClassName | string | `""` | | 27 | 28 | ---------------------------------------------- 29 | Autogenerated from chart metadata using [helm-docs v1.11.3](https://github.com/norwoodj/helm-docs/releases/v1.11.3) 30 | -------------------------------------------------------------------------------- /helm/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{- define "enshrouded.passwordSecretName" -}} 2 | {{- if .Values.config.serverPasswordExistingSecretName -}} 3 | {{ .Values.config.serverPasswordExistingSecretName -}} 4 | {{- else -}} 5 | {{ .Release.Name }}-password 6 | {{- end -}} 7 | {{- end -}} 8 | -------------------------------------------------------------------------------- /helm/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: "{{ .Chart.Name }}" 5 | labels: 6 | app: "{{ .Chart.Name }}" 7 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 8 | release: "{{ .Release.Name }}" 9 | heritage: "{{ .Release.Service }}" 10 | spec: 11 | strategy: 12 | type: Recreate 13 | replicas: 1 14 | selector: 15 | matchLabels: 16 | app: "{{ .Chart.Name }}" 17 | release: "{{ .Release.Name }}" 18 | template: 19 | metadata: 20 | labels: 21 | app: "{{ .Chart.Name }}" 22 | release: "{{ .Release.Name }}" 23 | spec: 24 | securityContext: 25 | runAsUser: 10000 26 | runAsGroup: 10000 27 | fsGroup: 10000 28 | containers: 29 | - name: "{{ .Chart.Name }}" 30 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" 31 | imagePullPolicy: Always 32 | resources: 33 | {{ toYaml .Values.resources | indent 10 }} 34 | env: 35 | - name: SERVER_NAME 36 | value: {{ .Values.config.serverName | squote }} 37 | - name: SERVER_PASSWORD 38 | valueFrom: 39 | secretKeyRef: 40 | name: {{ include "enshrouded.passwordSecretName" . }} 41 | key: serverPassword 42 | - name: PORT 43 | value: {{ .Values.config.port | squote }} 44 | - name: SERVER_SLOTS 45 | value: {{ .Values.config.serverSlots | squote }} 46 | - name: EXTERNAL_CONFIG 47 | value: {{ .Values.config.externalConfig | squote }} 48 | ports: 49 | - name: port 50 | containerPort: {{ .Values.config.port | int }} 51 | protocol: UDP 52 | volumeMounts: 53 | - name: data 54 | mountPath: /home/steam/enshrouded/savegame 55 | securityContext: 56 | allowPrivilegeEscalation: false 57 | 58 | volumes: 59 | - name: data 60 | persistentVolumeClaim: 61 | claimName: "{{ .Chart.Name }}-data" 62 | -------------------------------------------------------------------------------- /helm/templates/password-secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if not .Values.config.serverPasswordExistingSecretName }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ include "enshrouded.passwordSecretName" .}} 6 | labels: 7 | app: "{{ .Chart.Name }}" 8 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 9 | release: "{{ .Release.Name }}" 10 | heritage: "{{ .Release.Service }}" 11 | type: Opaque 12 | stringData: 13 | serverPassword: {{ .Values.config.serverPassword | default (randAlphaNum 10) | quote }} 14 | {{- end }} 15 | -------------------------------------------------------------------------------- /helm/templates/pvc.yaml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: "{{ .Chart.Name }}-data" 5 | labels: 6 | app: "{{ .Chart.Name }}" 7 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 8 | release: "{{ .Release.Name }}" 9 | heritage: "{{ .Release.Service }}" 10 | spec: 11 | accessModes: 12 | - ReadWriteOnce 13 | resources: 14 | requests: 15 | storage: {{ .Values.volumes.dataPVC.size }} 16 | {{- if ne .Values.volumes.storageClassName "" }} 17 | storageClassName: {{ .Values.volumes.storageClassName }} 18 | {{- end }} 19 | -------------------------------------------------------------------------------- /helm/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: "{{ .Chart.Name }}-service" 5 | labels: 6 | app: "{{ .Chart.Name }}" 7 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 8 | release: "{{ .Release.Name }}" 9 | heritage: "{{ .Release.Service }}" 10 | {{- with .Values.service.annotations }} 11 | annotations: {{- toYaml . | nindent 4 }} 12 | {{- end }} 13 | spec: 14 | type: {{ .Values.service.type }} 15 | {{- with .Values.service.externalIPs }} 16 | externalIPs: {{ . | toYaml | nindent 4 }} 17 | {{- end }} 18 | ports: 19 | - name: port 20 | port: {{ .Values.config.port | int }} 21 | targetPort: port 22 | protocol: UDP 23 | {{- if eq .Values.service.type "NodePort" }} 24 | nodePort: {{ .Values.config.port| int }} 25 | {{- end }} 26 | selector: 27 | app: "{{ .Chart.Name }}" 28 | -------------------------------------------------------------------------------- /helm/values.yaml: -------------------------------------------------------------------------------- 1 | image: 2 | repository: sknnr/enshrouded-dedicated-server 3 | tag: latest 4 | 5 | service: 6 | type: LoadBalancer 7 | externalIPs: [] 8 | annotations: {} 9 | 10 | resources: 11 | requests: 12 | memory: 12G 13 | cpu: 4.0 14 | 15 | volumes: 16 | dataPVC: 17 | # -- Size of the persistent volume 18 | size: 50Gi 19 | storageClassName: "" 20 | 21 | config: 22 | # -- Server name 23 | serverName: "Enshrouded Server" 24 | # -- Server password. If not set, password will be generated randomly. 25 | serverPassword: "" 26 | # -- Existing secret name for server password. Must contain key named "password". If set `serverPassword` will be ignored. 27 | serverPasswordExistingSecretName: "" 28 | port: 15637 29 | # -- Number of server slots 30 | serverSlots: 16 31 | externalConfig: 0 32 | -------------------------------------------------------------------------------- /kubernetes-manifests/README.md: -------------------------------------------------------------------------------- 1 | # Enshrouded server statefulSet on Kubernetes 2 | 3 | Review the manifests and make changes for your cluster. Each file should be reviewed and possibly edited. 4 | 5 | Apply in this order: 6 | - enshrouded-ns-privs.yaml 7 | - enshrouded-server_configmap.yaml 8 | - statefulset.yaml 9 | - service.yaml 10 | 11 | ## Configure server 12 | 13 | Either edit the configMap before applying, or use:\ 14 | `kubectl edit configmaps enshrouded-config` 15 | 16 | References for server config: 17 | https://nodecraft.com/support/games/enshrouded/changing-settings-for-an-enshrouded-server#h-key-server-settings-breakdown-e9f41b9a22 \ 18 | https://guides.gamehostbros.com/games/enshrouded/custom-difficulty-settings/ \ 19 | 20 | Units involving time are in nanoseconds (1/1,000,000,000 of a second), in-game they are displayed as minutes, you can calculate your desired value using this calculator:\ 21 | https://www.unitconverters.net/time/minute-to-nanosecond.htm 22 | 23 | ## Official Server Readme 24 | ``` 25 | _ _ _ 26 | ( ) ( ) ( ) 27 | __ ___ ___ | |__ _ __ _ _ _ _| | __ _| | 28 | /'__`\/' _ `\/',__)| _ `\( '__)/'_`\ ( ) ( ) /'_` | /'__`\ /'_` | 29 | ( ___/| ( ) |\__, \| | | || | ( (_) )| (_) |( (_| |( ___/( (_| | 30 | `\____)(_) (_)(____/(_) (_)(_) `\___/'`\___/'`\__,_)`\____)`\__,_) 31 | ___ __ _ __ _ _ __ _ __ 32 | /',__) /'__`\( '__)( ) ( ) /'__`\( '__) 33 | \__, \( ___/| | | \_/ |( ___/| | _ 34 | (____/`\____)(_) `\___/'`\____)(_) (_) 35 | ______ 36 | (______) 37 | _ ___ 38 | _ (_) /'___) 39 | (_) ___ _ ___ | | ___ | (__ _ 40 | | |/',__) /'_`\ /' _ `\ | |/' _ `\| ,__)/'_`\ 41 | | |\__, \( (_) )| ( ) | | || ( ) || | ( (_) ) 42 | _ | |(____/`\___/'(_) (_) (_)(_) (_)(_) `\___/' 43 | ( )_| | 44 | `\___/' 45 | 46 | Version: 0.7.4.0 47 | ``` 48 | 49 | The following paragraphs describe options and valid values that hosts of dedicated servers can configure by editing the file enshrouded_server.json, located in the same folder as the enshrouded_server.exe. 50 | 51 | ### PERMISSION SETTINGS 52 | 53 | Enshrouded allows hosts to define permissions for groups of players. This document leads through the new functions and also highlights areas that hosts need to be aware of. 54 | 55 | #### Dedicated server hosting - Using the pre-update 2 settings 56 | 57 | In Update 2 of Enshrouded the structure of the `enshrouded_server.json` had to be adapted to support multiple passwords. The password for a server was previously defined in line 3 of the file `enshrouded_server.json` via “password”: “”. This line is no longer used to setup the password for dedicated servers! However, if the game detects a password defined in line 3, it will set up a new “userGroup” called “default” which uses the password and automatically grants the same permission level as what players were accustomed to up until Update 2. This means if the host of a dedicated server chooses to not change anything, the dedicated server will still be protected by the same password and the permissions of joining players will stay the same. 58 | 59 | #### Dedicated server hosting - Setting up user groups 60 | 61 | Player permissions for playing on servers are handled via user groups. Each group can be set up in the `enshrouded_server.json` with a unique configuration of permissions and an accompanying password that grants the permissions to the logged-in player. By default, the `enshrouded_server.json` starts with 3 user groups which may serve as a base for hosts. The presets are: 62 | 63 | `Admin:` 64 | - Changes to the player bases are allowed. 65 | - Using chests and other containers are allowed. 66 | - Kicking and banning other players is allowed. 67 | 68 | `Friend:` 69 | - Changes to the player bases are allowed. 70 | - Using chests and other containers are allowed. 71 | 72 | `Guest:` 73 | - Changes to the player bases are not allowed. 74 | - Using chests and other containers are not allowed. 75 | 76 | **Please note: all user groups have full access to the game world outside the player bases and can engage in combat, collect materials, dig for resources, solve quests etc.** 77 | 78 | **Please also note: the presets mentioned above are only generated when the `enshrouded_server.json` is freshly created after updating Enshrouded with update 2. When the game detects an already defined password, only the “default” user group is created with the permission configuration identical to “Friend” from the presets above. By default, when a fresh `enshrouded_server.json` is created, randomized passwords are set to prevent unwanted players from joining the server.** 79 | 80 | #### Custom player permission groups 81 | 82 | The `enshrouded_server.json` also allows setting up new and unique user groups. Simply add a new user group section with a new name, define a password and select the permissions needed for the player group. For example, it could be interesting to allow a user group to access the content of chests, other containers or workstations but not to allow adding/deleting props and voxels in the player bases. 83 | 84 | Another setting that can be configured for each user group is a number of reserved slots for that particular user group. This is set by adding this line to the user group: 85 | 86 | `"reservedSlots": 1` 87 | 88 | When 1 or more reserved slots are set, the lobby will be marked as “full” for players who try to log into the server under a different user group and would fill up all session slots. This allows for example Admins or Friends to join even if there is a high demand for slots by “Guests”. 89 | 90 | ### DIFFICULTY- AND GAMEPLAY SETTINGS 91 | 92 | Update 0.7.3.0 introduced a number of difficulty- and gameplay settings that can be configured for the dedicated server via the `enshrouded_server.json` - file. 93 | 94 | **Note:** when no `enshrouded_server.json` config file is found, then a fresh file is created with the start of the enshrouded_server exe. 95 | 96 | #### Difficulty setting presets 97 | 98 | `"gameSettingsPreset":` 99 | 100 | The options are: 101 | - **"Default”** - The “Default” difficulty setting configures all values to default. It is the direct continuation of how Enshrouded was configured up until update 0.7.3.0 and is the recommended setting for first-time players. 102 | - **“Relaxed”** - The “Relaxed” preset reduces the amount of enemies and provides players with more resources and loot. This mode targets players who are most interested in base-building and light-hearted adventuring. 103 | - **“Hard”** - The “Hard” preset increases the amount of enemies and makes them more aggressive to give players a tougher combat experience. 104 | - **“Survival”** - The “Survival” preset is for those who seek some punishment with additional survival mechanics on top of more aggressive enemies. 105 | - **“Custom”** - When “Custom” is selected, a long list of individual settings can be tweaked. 106 | 107 | #### Individual Custom Settings including default values 108 | 109 | ```json 110 | Player Health 111 | "gameSettings": { 112 | "playerHealthFactor": 1, 113 | } 114 | Scales the max health for players by a factor. Ingame, the factor is represented by a percentage. 115 | Min value: 0.25 116 | Max value: 4 117 | ``` 118 | 119 | ```json 120 | Player Mana 121 | "gameSettings": { 122 | "playerManaFactor": 1, 123 | } 124 | Scales the max mana for players by a factor. Ingame, the factor is represented by a percentage. 125 | Min value: 0.25 126 | Max value: 4 127 | ``` 128 | 129 | ```json 130 | Player Stamina 131 | "gameSettings": { 132 | "playerStaminaFactor": 1, 133 | } 134 | Scales the max stamina for players by a factor. Ingame, the factor is represented by a percentage. 135 | Min value: 0.25 136 | Max value: 4 137 | ``` 138 | 139 | ```json 140 | Weapon Durability 141 | "gameSettings": { 142 | "enableDurability": true, 143 | } 144 | If this setting is set to “false”, weapons don't break anymore. 145 | Options: true / false 146 | ``` 147 | 148 | ```json 149 | Hunger and Starvation 150 | "gameSettings": { 151 | "enableStarvingDebuff": false, 152 | } 153 | Enables hunger and starvation. During starvation, the player loses health periodically until death if no food or drink is consumed. 154 | Options: true / false 155 | ``` 156 | 157 | ```json 158 | Food Buff Duration 159 | "gameSettings": { 160 | "foodBuffDurationFactor": 1, 161 | } 162 | Scales food buff durations. Ingame, the factor is represented by a percentage. 163 | Min value: 0.5 164 | Max value: 2 165 | ``` 166 | 167 | ```json 168 | Hungry State Duration 169 | "gameSettings": { 170 | "fromHungerToStarving": 600000000000, 171 | } 172 | This setting controls the length of the hungry state before the starving sets in. The unit in this setting is nanoseconds. Ingame the time is displayed in minutes. 173 | Min value: 5 minutes 174 | Max value: 20 minutes 175 | ``` 176 | 177 | ```json 178 | Shroud time duration modifier 179 | "gameSettings": { 180 | "shroudTimeFactor": 1, 181 | } 182 | Scales how long player characters can remain within the Shroud. Ingame, the factor is represented by a percentage. 183 | Min value: 0.5 184 | Max value: 2 185 | ``` 186 | 187 | ```json 188 | Enemy Amount 189 | "gameSettings": { 190 | "randomSpawnerAmount": "Normal" 191 | } 192 | This setting controls the amount of enemies in the world. 193 | Options: Few / Normal / Many / Extreme 194 | ``` 195 | 196 | ```json 197 | Mining Effectiveness 198 | "gameSettings": { 199 | "miningDamageFactor": 1, 200 | } 201 | This scales the mining damage. A higher mining damage leads to increased terraforming and more yield of resources per hit. Ingame, the factor is represented by a percentage. 202 | Min value: 0.5 203 | Max value: 2 204 | ``` 205 | 206 | ```json 207 | Plant Growth Speed 208 | "gameSettings": { 209 | "plantGrowthSpeedFactor": 1, 210 | } 211 | Scales the value of the plant growth speed. Ingame, the factor is represented by a percentage. 212 | Min value: 0.25 213 | Max value: 2 214 | ``` 215 | 216 | ```json 217 | Resources Gain Modifier 218 | "gameSettings": { 219 | "resourceDropStackAmountFactor": 1, 220 | } 221 | Scales the amount of materials per loot stack in chests, defeated enemies etc. Ingame, the factor is represented by a percentage. 222 | Min value: 0.25 223 | Max value: 2 224 | ``` 225 | 226 | ```json 227 | Workstation Effectiveness 228 | "gameSettings": { 229 | "factoryProductionSpeedFactor": 1, 230 | } 231 | Scales the length of production times for workshop items. Ingame, the factor is represented by a percentage. 232 | Min value: 0.25 233 | Max value: 2 234 | ``` 235 | 236 | ```json 237 | Weapon Recycling Yield Modifier 238 | "gameSettings": { 239 | "perkUpgradeRecyclingFactor": 0.100000, 240 | } 241 | Scales the amount of Runes that are returned to you when salvaging upgraded weapons. Ingame, the factor is represented by a percentage. 242 | Min value: 0 243 | Max value: 1 244 | ``` 245 | 246 | ```json 247 | Weapon Upgrading Costs 248 | "gameSettings": { 249 | "perkCostFactor": 1, 250 | } 251 | Scales the amount of Runes required for upgrading weapons. Ingame, the factor is represented by a percentage. 252 | Min value: 0.25 253 | Max value: 2 254 | ``` 255 | 256 | ```json 257 | Combat Experience Modifier 258 | "gameSettings": { 259 | "experienceCombatFactor": 1, 260 | } 261 | Scales the amount of XP received through combat. Ingame, the factor is represented by a percentage. 262 | Min value: 0.25 263 | Max value: 2 264 | ``` 265 | 266 | ```json 267 | Mining Experience Modifier 268 | "gameSettings": { 269 | "experienceMiningFactor": 1, 270 | } 271 | Scales the amount of XP received by mining resources. Ingame, the factor is represented by a percentage. 272 | Min value: 0 273 | Max value: 2 274 | ``` 275 | 276 | ```json 277 | Exploration Experience Modifier 278 | "gameSettings": { 279 | "experienceExplorationQuestsFactor": 1, 280 | } 281 | Scales the amount of XP received by exploring and completing quests. Ingame, the factor is represented by a percentage. 282 | Min value: 0.25 283 | Max value: 2 284 | ``` 285 | 286 | ```json 287 | Modifier for simultaneous Enemy Attacks 288 | "gameSettings": { 289 | "aggroPoolAmount": "Normal" 290 | } 291 | This setting controls how many enemies are allowed to attack at the same time. Ingame, the factor is represented by a percentage. 292 | Options: Few / Normal / Many / Extreme 293 | ``` 294 | 295 | ```json 296 | Enemy Damage 297 | "gameSettings": { 298 | "enemyDamageFactor": 1, 299 | } 300 | Scales all enemy damage by this value - except for bosses. Ingame, the factor is represented by a percentage. 301 | Min value: 0.25 302 | Max value: 5 303 | ``` 304 | 305 | ```json 306 | Enemy Health 307 | "gameSettings": { 308 | "enemyHealthFactor": 1, 309 | } 310 | Scales all enemy health by this value - except for bosses. Ingame, the factor is represented by a percentage. 311 | Min value: 0.25 312 | Max value: 4 313 | ``` 314 | 315 | ```json 316 | Enemy Stun Modifier 317 | "gameSettings": { 318 | "enemyStaminaFactor": 1, 319 | } 320 | Scales all enemy stamina by this value. It will take longer to stun enemies with a higher enemy stamina. This excludes bosses. Ingame, the factor is represented by a percentage. 321 | Min value: 0.5 322 | Max value: 2 323 | ``` 324 | 325 | ```json 326 | Enemy Perception Modifier 327 | "gameSettings": { 328 | "enemyPerceptionRangeFactor": 1, 329 | } 330 | Scales how far enemies can see and hear the player. This excludes bosses. Ingame, the factor is represented by a percentage. 331 | Min value: 0.5 332 | Max value: 2 333 | ``` 334 | 335 | ```json 336 | Boss Damage Modifier 337 | "gameSettings": { 338 | "bossDamageFactor": 1, 339 | } 340 | This setting scales the damage of boss attacks. Ingame, the factor is represented by a percentage. 341 | Min value: 0.2 342 | Max value: 5 343 | ``` 344 | 345 | ```json 346 | Boss Health Modifier 347 | "gameSettings": { 348 | "bossHealthFactor": 1, 349 | } 350 | Scales all health of bosses by this value. Ingame, the factor is represented by a percentage. 351 | Min value: 0.2 352 | Max value: 5 353 | ``` 354 | 355 | ```json 356 | Enemy Attacks Modifier 357 | "gameSettings": { 358 | "threatBonus": 1, 359 | } 360 | Scales the frequency of enemy attacks. This excludes bosses. Ingame, the factor is represented by a percentage. 361 | Min value: 0.25 362 | Max value: 4 363 | ``` 364 | 365 | ```json 366 | Pacified Enemies 367 | "gameSettings": { 368 | "pacifyAllEnemies": false, 369 | } 370 | If turned on, enemies won't attack the players until they are attacked. This excludes bosses. 371 | Options: true / false 372 | ``` 373 | 374 | ```json 375 | Daytime 376 | "gameSettings": { 377 | "dayTimeDuration": 1800000000000 378 | } 379 | Scales the length of daytime. A smaller value equals shorter daytime. The unit is nanoseconds. Ingame, the time is displayed in minutes. 380 | Min value: 2 minutes 381 | Max value: 60 minutes 382 | ``` 383 | 384 | ```json 385 | Nighttime 386 | "gameSettings": { 387 | "nightTimeDuration": 720000000000 388 | } 389 | Scales the length of daytime. A smaller value equals a shorter nighttime. The unit is nanoseconds. Ingame, the time is displayed in minutes. 390 | Min value: 2 minutes 391 | Max value: 60 minutes 392 | ``` 393 | 394 | ```json 395 | Tombstone Mode 396 | "gameSettings": { 397 | "tombstoneMode": "AddBackpackMaterials" 398 | } 399 | The players can either keep or lose all items from their backpack when dying. In the default setting, they only lose materials. Lost items are stored in a tombstone and can be recovered there. 400 | Options: AddBackpackMaterials / Everything / NoTombstone 401 | ``` 402 | 403 | #### Update 0.7.4.0 introduced a few new user settings 404 | 405 | ```json 406 | Player body heat against cold weather 407 | "gameSettings": { 408 | "playerBodyHeatFactor": 1, 409 | } 410 | Scales the max amount of available body heat in the player. The higher the factor the longer the player can stay in very cold areas before hypothermia sets in. 411 | Min value: 0.5 412 | Max value: 2 413 | ``` 414 | 415 | ```json 416 | Weather phenomena frequency 417 | "gameSettings": { 418 | "weatherFrequency": "Normal", 419 | } 420 | This setting allows defining how often new weather phenomena appear in the game world. 421 | Options: Disabled / Rare / Normal / Often 422 | ``` 423 | 424 | ```json 425 | Taming failure repercussions 426 | "gameSettings": { 427 | "tamingStartleRepercussion": "LoseSomeProgress", 428 | } 429 | This setting allows defining how the game reacts when the player startles the wildlife during taming. Progress is visualized by hearts in the game. 430 | Options: KeepProgress / LoseSomeProgress / LoseAllProgress 431 | ``` 432 | 433 | ```json 434 | Air turbulences while gliding 435 | "gameSettings": { 436 | "enableGliderTurbulences": true, 437 | } 438 | If turned off, the glider will not be affected by air turbulences, just as in previous versions of the game. 439 | Options: true / false 440 | ``` 441 | 442 | ### DEFAULT `enshrouded_server.json` / VERSION 0.7.4.0 443 | 444 | ```json 445 | { 446 | "name": "Enshrouded Server", 447 | "saveDirectory": "./savegame", 448 | "logDirectory": "./logs", 449 | "ip": "0.0.0.0", 450 | "queryPort": 15637, 451 | "slotCount": 16, 452 | "gameSettingsPreset": "Default", 453 | "gameSettings": { 454 | "playerHealthFactor": 1, 455 | "playerManaFactor": 1, 456 | "playerStaminaFactor": 1, 457 | "playerBodyHeatFactor": 1, 458 | "enableDurability": true, 459 | "enableStarvingDebuff": false, 460 | "foodBuffDurationFactor": 1, 461 | "fromHungerToStarving": 600000000000, 462 | "shroudTimeFactor": 1, 463 | "tombstoneMode": "AddBackpackMaterials", 464 | "enableGliderTurbulences": true, 465 | "weatherFrequency": "Normal", 466 | "miningDamageFactor": 1, 467 | "plantGrowthSpeedFactor": 1, 468 | "resourceDropStackAmountFactor": 1, 469 | "factoryProductionSpeedFactor": 1, 470 | "perkUpgradeRecyclingFactor": 0.500000, 471 | "perkCostFactor": 1, 472 | "experienceCombatFactor": 1, 473 | "experienceMiningFactor": 1, 474 | "experienceExplorationQuestsFactor": 1, 475 | "randomSpawnerAmount": "Normal", 476 | "aggroPoolAmount": "Normal", 477 | "enemyDamageFactor": 1, 478 | "enemyHealthFactor": 1, 479 | "enemyStaminaFactor": 1, 480 | "enemyPerceptionRangeFactor": 1, 481 | "bossDamageFactor": 1, 482 | "bossHealthFactor": 1, 483 | "threatBonus": 1, 484 | "pacifyAllEnemies": false, 485 | "tamingStartleRepercussion": "LoseSomeProgress", 486 | "dayTimeDuration": 1800000000000, 487 | "nightTimeDuration": 720000000000 488 | }, 489 | "userGroups": [ 490 | { 491 | "name": "Admin", 492 | "password": "AdminXXXXXXXX", 493 | "canKickBan": true, 494 | "canAccessInventories": true, 495 | "canEditBase": true, 496 | "canExtendBase": true, 497 | "reservedSlots": 0 498 | }, 499 | { 500 | "name": "Friend", 501 | "password": "FriendXXXXXXXX", 502 | "canKickBan": false, 503 | "canAccessInventories": true, 504 | "canEditBase": true, 505 | "canExtendBase": false, 506 | "reservedSlots": 0 507 | }, 508 | { 509 | "name": "Guest", 510 | "password": "GuestXXXXXXXX", 511 | "canKickBan": false, 512 | "canAccessInventories": false, 513 | "canEditBase": false, 514 | "canExtendBase": false, 515 | "reservedSlots": 0 516 | } 517 | ] 518 | } 519 | ``` 520 | -------------------------------------------------------------------------------- /kubernetes-manifests/enshrouded-ns-privs.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: enshrouded 6 | ## Uncomment if default is restricted (ie, Talos) 7 | # labels: 8 | # pod-security.kubernetes.io/enforce: privileged 9 | # pod-security.kubernetes.io/audit: privileged 10 | # pod-security.kubernetes.io/warn: privileged 11 | -------------------------------------------------------------------------------- /kubernetes-manifests/enshrouded-server_configmap.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: enshrouded-config 6 | data: 7 | enshrouded_server.json: | 8 | { 9 | "name": "Enshrouded Server", 10 | "saveDirectory": "./savegame", 11 | "logDirectory": "./logs", 12 | "ip": "0.0.0.0", 13 | "queryPort": 15637, 14 | "slotCount": 16, 15 | "gameSettingsPreset": "Default", 16 | "gameSettings": { 17 | "playerHealthFactor": 1, 18 | "playerManaFactor": 1, 19 | "playerStaminaFactor": 1, 20 | "playerBodyHeatFactor": 1, 21 | "enableDurability": true, 22 | "enableStarvingDebuff": false, 23 | "foodBuffDurationFactor": 1, 24 | "fromHungerToStarving": 600000000000, 25 | "shroudTimeFactor": 1, 26 | "tombstoneMode": "AddBackpackMaterials", 27 | "enableGliderTurbulences": true, 28 | "weatherFrequency": "Normal", 29 | "miningDamageFactor": 1, 30 | "plantGrowthSpeedFactor": 1, 31 | "resourceDropStackAmountFactor": 1, 32 | "factoryProductionSpeedFactor": 1, 33 | "perkUpgradeRecyclingFactor": 0.500000, 34 | "perkCostFactor": 1, 35 | "experienceCombatFactor": 1, 36 | "experienceMiningFactor": 1, 37 | "experienceExplorationQuestsFactor": 1, 38 | "randomSpawnerAmount": "Normal", 39 | "aggroPoolAmount": "Normal", 40 | "enemyDamageFactor": 1, 41 | "enemyHealthFactor": 1, 42 | "enemyStaminaFactor": 1, 43 | "enemyPerceptionRangeFactor": 1, 44 | "bossDamageFactor": 1, 45 | "bossHealthFactor": 1, 46 | "threatBonus": 1, 47 | "pacifyAllEnemies": false, 48 | "tamingStartleRepercussion": "LoseSomeProgress", 49 | "dayTimeDuration": 1800000000000, 50 | "nightTimeDuration": 720000000000 51 | }, 52 | "userGroups": [ 53 | { 54 | "name": "Admin", 55 | "password": "AdminXXXXXXXX", 56 | "canKickBan": true, 57 | "canAccessInventories": true, 58 | "canEditBase": true, 59 | "canExtendBase": true, 60 | "reservedSlots": 0 61 | }, 62 | { 63 | "name": "Friend", 64 | "password": "FriendXXXXXXXX", 65 | "canKickBan": false, 66 | "canAccessInventories": true, 67 | "canEditBase": true, 68 | "canExtendBase": false, 69 | "reservedSlots": 0 70 | }, 71 | { 72 | "name": "Guest", 73 | "password": "GuestXXXXXXXX", 74 | "canKickBan": false, 75 | "canAccessInventories": false, 76 | "canEditBase": false, 77 | "canExtendBase": false, 78 | "reservedSlots": 0 79 | } 80 | ] 81 | } -------------------------------------------------------------------------------- /kubernetes-manifests/service-cilium.yaml: -------------------------------------------------------------------------------- 1 | # Example for Cilium with LoadBalancer dedicated Loadbalancer address 2 | --- 3 | apiVersion: v1 4 | kind: Service 5 | metadata: 6 | name: enshrouded 7 | namespace: enshrouded 8 | annotations: 9 | io.cilium/lb-ipam-ips: "10.26.14.82" 10 | kubernetes.io/ingress.class: "cilium" 11 | ingress.cilium.io/loadbalancer-mode: "dedicated" 12 | labels: 13 | app: enshrouded 14 | spec: 15 | type: LoadBalancer 16 | ports: 17 | - port: 15637 18 | protocol: UDP 19 | name: "query-port-udp" 20 | targetPort: 15637 21 | selector: 22 | app: enshrouded 23 | -------------------------------------------------------------------------------- /kubernetes-manifests/service-nginx.yaml: -------------------------------------------------------------------------------- 1 | ## Example for Nginx 2 | --- 3 | apiVersion: v1 4 | kind: Service 5 | metadata: 6 | name: enshrouded 7 | namespace: enshrouded 8 | labels: 9 | app: enshrouded 10 | spec: 11 | type: ClusterIP 12 | ports: 13 | - port: 15637 14 | protocol: UDP 15 | name: "query-port-udp" 16 | targetPort: 15637 17 | selector: 18 | app: enshrouded -------------------------------------------------------------------------------- /kubernetes-manifests/statefulset.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: StatefulSet 4 | metadata: 5 | name: enshrouded 6 | namespace: enshrouded 7 | labels: 8 | app: enshrouded 9 | spec: 10 | selector: 11 | matchLabels: 12 | app: enshrouded 13 | serviceName: "enshrouded" 14 | replicas: 1 15 | template: 16 | metadata: 17 | labels: 18 | app: enshrouded 19 | spec: 20 | securityContext: 21 | runAsUser: 10000 22 | runAsGroup: 10000 23 | fsGroup: 10000 24 | containers: 25 | - name: enshrouded 26 | image: sknnr/enshrouded-dedicated-server:latest 27 | imagePullPolicy: Always 28 | ports: 29 | - containerPort: 15637 30 | name: "query-port-udp" 31 | protocol: UDP 32 | volumeMounts: 33 | - name: enshrouded-data 34 | mountPath: /home/steam/enshrouded/savegame 35 | - name: config-volume 36 | mountPath: /home/steam/enshrouded/enshrouded_server.json 37 | subPath: enshrouded_server.json 38 | resources: 39 | requests: 40 | cpu: 500m 41 | memory: 500Mi 42 | limits: 43 | cpu: 4 44 | memory: 6Gi 45 | volumes: 46 | - name: config-volume 47 | configMap: 48 | name: enshrouded-config 49 | - name: enshrouded-data 50 | persistentVolumeClaim: 51 | claimName: enshrouded-data 52 | ## If you manually create a persistent volume and volume claim, comment out the section below. 53 | volumeClaimTemplates: 54 | - metadata: 55 | name: enshrouded-data 56 | spec: 57 | accessModes: [ "ReadWriteOnce" ] 58 | resources: 59 | requests: 60 | storage: 10Gi -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | # I would prefer Podman but for some reason the Proton container just doesn't run right in Podman. 2 | # Not sure if this is a me problem or a Podman problem. So Proton builds and runs with Docker instead. 3 | # 4 | # Image Values 5 | REGISTRY := localhost 6 | IMAGE := enshrouded-test 7 | PROTON_IMAGE := enshrouded-proton-test 8 | IMAGE_REF := $(REGISTRY)/$(IMAGE) 9 | PROTON_IMAGE_REF := $(REGISTRY)/$(PROTON_IMAGE) 10 | 11 | # Git commit hash 12 | HASH := $(shell git rev-parse --short HEAD) 13 | 14 | # Buildah/Podman/Docker Options 15 | CONTAINER_NAME := enshrouded-test 16 | VOLUME_NAME := enshrouded-data 17 | BUILDAH_BUILD_OPTS := --format docker -f ./container/wine/Dockerfile 18 | PODMAN_RUN_OPTS := --name $(CONTAINER_NAME) -d --mount type=volume,source=$(VOLUME_NAME),target=/home/steam/enshrouded/savegame -p 15636:15636/udp -p 15637:15637/udp --env=SERVER_NAME='Enshrouded Containerized Server' --env=SERVER_SLOTS=16 --env=SERVER_PASSWORD='ChangeThisPlease' --env=PORT=15637 19 | PROTON_CONTAINER_NAME := enshrouded-proton-test 20 | PROTON_VOLUME_NAME := enshrouded-proton-data 21 | PROTON_DOCKER_BUILD_OPTS := -f ./container/proton/Dockerfile 22 | PROTON_DOCKER_RUN_OPTS := --name $(PROTON_CONTAINER_NAME) -d --mount type=volume,source=$(PROTON_VOLUME_NAME),target=/home/steam/enshrouded/savegame -p 15636:15636/udp -p 15637:15637/udp --env=SERVER_NAME='Enshrouded Containerized Server' --env=SERVER_SLOTS=16 --env=SERVER_PASSWORD='ChangeThisPlease' --env=PORT=15637 23 | 24 | # Makefile targets 25 | .PHONY: build run cleanup build-proton run-proton cleanup-proton 26 | 27 | build: 28 | buildah build $(BUILDAH_BUILD_OPTS) -t $(IMAGE_REF):$(HASH) ./container/wine 29 | 30 | run: 31 | podman volume create $(VOLUME_NAME) 32 | podman run $(PODMAN_RUN_OPTS) $(IMAGE_REF):$(HASH) 33 | 34 | cleanup: 35 | podman rm -f $(CONTAINER_NAME) 36 | podman rmi -f $(IMAGE_REF):$(HASH) 37 | podman volume rm $(VOLUME_NAME) 38 | 39 | build-proton: 40 | docker build $(PROTON_DOCKER_BUILD_OPTS) -t $(PROTON_IMAGE_REF):$(HASH) ./container/proton 41 | 42 | run-proton: 43 | docker volume create $(PROTON_VOLUME_NAME) 44 | docker run $(PROTON_DOCKER_RUN_OPTS) $(PROTON_IMAGE_REF):$(HASH) 45 | 46 | cleanup-proton: 47 | docker rm -f $(PROTON_CONTAINER_NAME) 48 | docker rmi -f $(PROTON_IMAGE_REF):$(HASH) 49 | docker volume rm $(PROTON_VOLUME_NAME) 50 | --------------------------------------------------------------------------------