├── .circleci └── config.yml ├── .github ├── CODEOWNERS └── workflows │ └── publish.yml ├── .gitignore ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── common.cfg.tmpl ├── config-game-template ├── 7DaysToDie │ └── serverconfig.xml.tmpl ├── Factorio │ └── server-settings.json.tmpl ├── GarrysMod │ └── server.cfg.tmpl ├── Minecraft │ └── server.properties.tmpl └── README.md ├── docker-compose.citest.yml ├── docker-compose.gmod.yml ├── docker-compose.yml ├── docker-runner.sh ├── docker-stack.yml ├── examples ├── docker-compose.7dtd.yml ├── docker-compose.ark.yml ├── docker-compose.arma3.yml ├── docker-compose.csgo.yml ├── docker-compose.css.yml ├── docker-compose.factorio.yml ├── docker-compose.gmod.yml ├── docker-compose.inss.yml ├── docker-compose.minecraft.yml ├── docker-compose.mohaa.yml ├── docker-compose.pstbs.yml ├── docker-compose.valheim.yml ├── docker-compose.wet.yml └── docker-compose.wurm.yml ├── renovate.json ├── scripts └── test-gomplate.sh └── src ├── cmd └── monitor │ └── monitor.go └── version └── version.go /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | defaults: &defaults 2 | working_directory: ~/build 3 | docker: 4 | - image: joshhsoj1902/circleci-build-image:2.1.0 5 | swarm_test: &swarm_test 6 | name: Start container & run tests 7 | command: | 8 | docker swarm init 9 | docker stack deploy --compose-file ./docker-stack.yml game 10 | sleep 30 11 | retry -v -s 5 -t 12 'docker exec $(docker ps -q) curl -f http://localhost:28080/live || exit 1' 12 | retry -v -s 5 -t 60 'docker exec $(docker ps -q) curl -f http://localhost:28080/ready || exit 1' 13 | version: 2.1 14 | 15 | orbs: 16 | docker: joshhsoj1902/docker@0.20.0 17 | 18 | jobs: 19 | setup: 20 | <<: *defaults 21 | steps: 22 | - checkout 23 | - run: 24 | name: setup workspace 25 | command: | 26 | cp -rp docker-compose.citest.yml docker-stack.yml Makefile scripts examples /tmp/workspace 27 | ls -ltr /tmp/workspace 28 | ls -ltr /tmp/workspace/examples 29 | - persist_to_workspace: 30 | root: /tmp/workspace 31 | paths: 32 | - docker-compose.citest.yml 33 | - docker-stack.yml 34 | - examples 35 | - Makefile 36 | - scripts 37 | 38 | swarm: 39 | <<: *defaults 40 | steps: 41 | - setup_remote_docker: 42 | version: 19.03.8 43 | - attach_workspace: 44 | at: /tmp/workspace 45 | - run: docker load -i /tmp/workspace/images.tar 46 | - run: cp /tmp/workspace/docker-stack.yml ./docker-stack.yml 47 | - run: docker tag joshhsoj1902/linuxgsm-docker:latest joshhsoj1902/linuxgsm-docker:local 48 | - run: 49 | <<: *swarm_test 50 | workflows: 51 | version: 2 52 | build_and_test: 53 | jobs: 54 | - setup 55 | - docker/build: 56 | context: org-global 57 | tag: latest 58 | requires: 59 | - setup 60 | # - docker/test: 61 | # name: gomplate tests 62 | # requires: 63 | # - docker/build 64 | - swarm: 65 | name: swarm-test 66 | requires: 67 | - docker/build 68 | - docker/container-health: 69 | name: compose-test 70 | composeFile: docker-compose.citest.yml 71 | command: docker-compose -p citest -f /tmp/workspace/docker-compose.citest.yml up 72 | service: css 73 | after_test: 74 | - docker/compose-exec-retry: 75 | composeFilePath: /tmp/workspace/docker-compose.citest.yml -p citest 76 | service: css 77 | command: curl -f http://localhost:28080/ready 78 | sleep: 15 79 | tries: 60 80 | requires: 81 | - docker/build 82 | ### 7dtd ### 83 | - docker/container-health: 84 | name: 7dtd-compose 85 | composeFile: examples/docker-compose.7dtd.yml 86 | command: docker-compose -p 7dtd -f /tmp/workspace/examples/docker-compose.7dtd.yml up 87 | service: 7dtd 88 | after_test: 89 | - docker/compose-exec-retry: 90 | composeFilePath: /tmp/workspace/examples/docker-compose.7dtd.yml -p 7dtd 91 | service: 7dtd 92 | command: curl -f http://localhost:28080/ready 93 | sleep: 30 94 | tries: 30 95 | requires: 96 | - swarm-test 97 | - compose-test 98 | ### ARK ### 99 | - docker/container-health: 100 | name: ark-compose 101 | composeFile: examples/docker-compose.ark.yml 102 | command: docker-compose -p ark -f /tmp/workspace/examples/docker-compose.ark.yml up 103 | service: ark 104 | after_test: 105 | - docker/compose-exec-retry: 106 | composeFilePath: /tmp/workspace/examples/docker-compose.ark.yml -p ark 107 | service: ark 108 | command: curl -f http://localhost:28080/ready 109 | sleep: 30 110 | tries: 60 111 | requires: 112 | - swarm-test 113 | - compose-test 114 | ### CSGO ### 115 | - docker/container-health: 116 | name: csgo-compose 117 | composeFile: examples/docker-compose.csgo.yml 118 | command: docker-compose -p csgo -f /tmp/workspace/examples/docker-compose.csgo.yml up 119 | service: csgo 120 | after_test: 121 | - docker/compose-exec-retry: 122 | composeFilePath: /tmp/workspace/examples/docker-compose.csgo.yml -p csgo 123 | service: csgo 124 | command: curl -f http://localhost:28080/ready 125 | sleep: 30 126 | tries: 60 127 | requires: 128 | - swarm-test 129 | - compose-test 130 | ### CSS ### 131 | - docker/container-health: 132 | name: css-compose 133 | composeFile: examples/docker-compose.css.yml 134 | command: docker-compose -p css -f /tmp/workspace/examples/docker-compose.css.yml up 135 | service: css 136 | after_test: 137 | - docker/compose-exec-retry: 138 | composeFilePath: /tmp/workspace/examples/docker-compose.css.yml -p css 139 | service: css 140 | command: curl -f http://localhost:28080/ready 141 | sleep: 5 142 | tries: 60 143 | requires: 144 | - swarm-test 145 | - compose-test 146 | ### GMOD ### 147 | - docker/container-health: 148 | name: gmod-compose 149 | composeFile: examples/docker-compose.gmod.yml 150 | command: docker-compose -p gmod -f /tmp/workspace/examples/docker-compose.gmod.yml up 151 | service: gmod 152 | after_test: 153 | - docker/compose-exec-retry: 154 | composeFilePath: /tmp/workspace/examples/docker-compose.gmod.yml -p gmod 155 | service: gmod 156 | command: curl -f http://localhost:28080/ready 157 | sleep: 15 158 | tries: 60 159 | requires: 160 | - swarm-test 161 | - compose-test 162 | ### INSS ### 163 | # - docker/container-health: 164 | # name: inss-compose 165 | # composeFile: examples/docker-compose.inss.yml 166 | # command: docker-compose -p inss -f /tmp/workspace/examples/docker-compose.inss.yml up 167 | # service: inss 168 | # after_test: 169 | # - docker/compose-exec-retry: 170 | # composeFilePath: /tmp/workspace/examples/docker-compose.inss.yml -p inss 171 | # service: inss 172 | # command: curl -f http://localhost:28080/ready 173 | # sleep: 30 174 | # tries: 60 175 | # requires: 176 | # - swarm-test 177 | # - compose-test 178 | ### Minecraft ### 179 | - docker/container-health: 180 | name: minecraft-compose 181 | composeFile: examples/docker-compose.minecraft.yml 182 | command: docker-compose -p minecraft -f /tmp/workspace/examples/docker-compose.minecraft.yml up 183 | service: minecraft 184 | after_test: 185 | - docker/compose-exec-retry: 186 | composeFilePath: /tmp/workspace/examples/docker-compose.minecraft.yml -p minecraft 187 | service: minecraft 188 | command: curl -f http://localhost:28080/ready 189 | sleep: 5 190 | tries: 60 191 | requires: 192 | - swarm-test 193 | - compose-test 194 | ### Medal of Honor: Allied Assault ### 195 | - docker/container-health: 196 | name: mohaa-compose 197 | composeFile: examples/docker-compose.mohaa.yml 198 | command: docker-compose -p mohaa -f /tmp/workspace/examples/docker-compose.mohaa.yml up 199 | service: mohaa 200 | after_test: 201 | - docker/compose-exec-retry: 202 | composeFilePath: /tmp/workspace/examples/docker-compose.mohaa.yml -p mohaa 203 | service: mohaa 204 | command: curl -f http://localhost:28080/ready 205 | sleep: 30 206 | tries: 60 207 | requires: 208 | - swarm-test 209 | - compose-test 210 | ### Pstbs ### 211 | # - docker/container-health: 212 | # name: pstbs-compose 213 | # composeFile: examples/docker-compose.pstbs.yml 214 | # command: docker-compose -p pstbs -f /tmp/workspace/examples/docker-compose.pstbs.yml up 215 | # service: pstbs 216 | # after_test: 217 | # - docker/compose-exec-retry: 218 | # composeFilePath: /tmp/workspace/examples/docker-compose.pstbs.yml -p pstbs 219 | # service: pstbs 220 | # command: curl -f http://localhost:28080/ready 221 | # sleep: 5 222 | # tries: 60 223 | # requires: 224 | # - swarm-test 225 | # - compose-test 226 | 227 | 228 | ### Wet ### 229 | - docker/container-health: 230 | name: wet-compose 231 | composeFile: examples/docker-compose.wet.yml 232 | command: docker-compose -p wet -f /tmp/workspace/examples/docker-compose.wet.yml up 233 | service: wet 234 | after_test: 235 | - docker/compose-exec-retry: 236 | composeFilePath: /tmp/workspace/examples/docker-compose.wet.yml -p wet 237 | service: wet 238 | command: curl -f http://localhost:28080/ready 239 | sleep: 5 240 | tries: 60 241 | requires: 242 | - swarm-test 243 | - compose-test 244 | ### VALHEIM ### 245 | - docker/container-health: 246 | name: valheim-compose 247 | composeFile: examples/docker-compose.valheim.yml 248 | command: docker-compose -p valheim -f /tmp/workspace/examples/docker-compose.valheim.yml up 249 | service: valheim 250 | after_test: 251 | - docker/compose-exec-retry: 252 | composeFilePath: /tmp/workspace/examples/docker-compose.valheim.yml -p valheim 253 | service: valheim 254 | command: curl -f http://localhost:28080/ready 255 | sleep: 5 256 | tries: 60 257 | requires: 258 | - swarm-test 259 | - compose-test 260 | ### Wurm ### 261 | # - docker/container-health: 262 | # name: wurm-compose 263 | # composeFile: examples/docker-compose.wurm.yml 264 | # command: docker-compose -p wurm -f /tmp/workspace/examples/docker-compose.wurm.yml up 265 | # service: wurm 266 | # after_test: 267 | # - docker/compose-exec-retry: 268 | # composeFilePath: /tmp/workspace/examples/docker-compose.wurm.yml -p wurm 269 | # service: wurm 270 | # command: curl -f http://localhost:28080/ready 271 | # sleep: 5 272 | # tries: 60 273 | # requires: 274 | # - swarm-test 275 | # - compose-test 276 | 277 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Lines starting with '#' are comments. 2 | # Each line is a file pattern followed by one or more owners. 3 | 4 | # These owners will be the default owners for everything in the repo. 5 | * @joshhsoj1902 6 | 7 | # Order is important. The last matching pattern has the most precedence. 8 | # So if a pull request only touches javascript files, only these owners 9 | # will be requested to review. 10 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | 6 | name: Publish Docker image 7 | 8 | on: 9 | release: 10 | types: [published] 11 | 12 | jobs: 13 | push_to_registry: 14 | name: Push Docker image to Docker Hub 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Check out the repo 18 | uses: actions/checkout@v2 19 | 20 | - name: Log in to Docker Hub 21 | uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 22 | with: 23 | username: ${{ secrets.DOCKER_USERNAME }} 24 | password: ${{ secrets.DOCKER_PASSWORD }} 25 | 26 | - name: Extract metadata (tags, labels) for Docker 27 | id: meta 28 | uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 29 | with: 30 | images: joshhsoj1902/linuxgsm-docker 31 | 32 | - name: Build and push Docker image 33 | uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc 34 | with: 35 | context: . 36 | push: true 37 | tags: ${{ steps.meta.outputs.tags }} 38 | labels: ${{ steps.meta.outputs.labels }} 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /monitor 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Operator 2 | FROM golang:1.16.0 AS builder 3 | RUN mkdir -p /src 4 | ADD Makefile / 5 | 6 | COPY src/ /src/ 7 | WORKDIR / 8 | 9 | RUN make build-monitor 10 | 11 | FROM ubuntu:18.04 12 | 13 | WORKDIR /home/linuxgsm/linuxgsm 14 | 15 | # Stop apt-get asking to get Dialog frontend 16 | ENV DEBIAN_FRONTEND noninteractive 17 | ENV TERM xterm 18 | 19 | ENV LGSM_CONSOLE_STDOUT=true 20 | ENV LGSM_SCRIPT_STDOUT=true 21 | ENV LGSM_ALERT_STDOUT=true 22 | ENV LGSM_GAME_STDOUT=true 23 | 24 | ENV LGSM_STOP_ON_FAILURE=true 25 | 26 | RUN apt-get update && \ 27 | apt-get install -y \ 28 | curl 29 | 30 | # https://adoptium.net/releases.html?variant=openjdk16&jvmVariant=hotspot 31 | RUN mkdir -p /bin/java && \ 32 | curl -sL 'https://github.com/adoptium/temurin16-binaries/releases/download/jdk-16.0.2%2B7/OpenJDK16U-jdk_x64_linux_hotspot_16.0.2_7.tar.gz' | tar zxvf - -C /bin/java 33 | 34 | ENV PATH="/bin/java/jdk-16.0.2+7/bin:${PATH}" 35 | 36 | # Install dependencies and clean 37 | # RUN echo steam steam/question select "I AGREE" | debconf-set-selections && \ 38 | RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - && \ 39 | apt-get update && \ 40 | apt-get install -y software-properties-common && \ 41 | add-apt-repository multiverse && \ 42 | dpkg --add-architecture i386 && \ 43 | apt-get update && \ 44 | apt-get install -y \ 45 | bc \ 46 | binutils \ 47 | bsdmainutils \ 48 | bzip2 \ 49 | # This default-jre isn't used, The above jdk is used instead. linuxGSM still looks for this to be installed 50 | default-jre \ 51 | expect \ 52 | file \ 53 | git \ 54 | gzip \ 55 | iproute2 \ 56 | jq \ 57 | lib32gcc1 \ 58 | lib32z1 \ 59 | libc6 \ 60 | libstdc++6 \ 61 | libstdc++6:i386 \ 62 | lib32stdc++6 \ 63 | libtinfo5:i386 \ 64 | libsdl2-2.0-0:i386 \ 65 | libstdc++5:i386 \ 66 | libgconf-2-4 \ 67 | mailutils \ 68 | net-tools \ 69 | netcat \ 70 | postfix \ 71 | python \ 72 | # steamcmd \ 73 | tmux \ 74 | telnet \ 75 | util-linux \ 76 | unzip \ 77 | wget \ 78 | xvfb \ 79 | # Cleanup 80 | && apt-get -y autoremove \ 81 | && apt-get -y clean \ 82 | && rm -rf /var/lib/apt/lists/* \ 83 | && rm -rf /tmp/* \ 84 | && rm -rf /var/tmp/* 85 | 86 | # Install steamcmd 87 | SHELL ["/bin/bash", "-o", "pipefail", "-c"] 88 | RUN echo steam steam/question select "I AGREE" | debconf-set-selections \ 89 | && echo steam steam/license note '' | debconf-set-selections \ 90 | && dpkg --add-architecture i386 \ 91 | && apt-get update -y \ 92 | && apt-get install -y --no-install-recommends ca-certificates locales steamcmd \ 93 | # Cleanup 94 | && apt-get -y autoremove \ 95 | && apt-get -y clean \ 96 | && rm -rf /var/lib/apt/lists/* \ 97 | && rm -rf /tmp/* \ 98 | && rm -rf /var/tmp/* \ 99 | # Final setup 100 | && ln -s /usr/games/steamcmd /usr/bin/steamcmd \ 101 | && steamcmd +quit 102 | 103 | # Install Gamedig https://docs.linuxgsm.com/requirements/gamedig 104 | RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - \ 105 | && apt-get update && apt-get install -y nodejs \ 106 | && npm install -g gamedig \ 107 | # Cleanup 108 | && apt-get -y autoremove \ 109 | && apt-get -y clean \ 110 | && rm -rf /var/lib/apt/lists/* \ 111 | && rm -rf /tmp/* \ 112 | && rm -rf /var/tmp/* 113 | 114 | COPY --from=joshhsoj1902/parse-env:1.0.3 /go/src/github.com/joshhsoj1902/parse-env/main /usr/bin/parse-env 115 | COPY --from=hairyhenderson/gomplate:v3.9.0-alpine /bin/gomplate /usr/bin/gomplate 116 | 117 | # Add the linuxgsm user 118 | RUN adduser \ 119 | --disabled-login \ 120 | --disabled-password \ 121 | --shell /bin/bash \ 122 | --gecos "" \ 123 | linuxgsm \ 124 | && usermod -G tty linuxgsm \ 125 | && chown -R linuxgsm:linuxgsm /home/linuxgsm 126 | 127 | # Switch to the user linuxgsm 128 | USER linuxgsm 129 | 130 | # Install LinuxGSM 131 | RUN git clone "https://github.com/GameServerManagers/LinuxGSM.git" /home/linuxgsm/linuxgsm \ 132 | && git checkout tags/v21.2.5 \ 133 | && rm -rf /home/linuxgsm/linuxgsm/.git \ 134 | # Install GameConfigs 135 | && git clone "https://github.com/GameServerManagers/Game-Server-Configs.git" /home/linuxgsm/linuxgsm/lgsm/config-default/config-game/ \ 136 | && rm -rf /home/linuxgsm/linuxgsm-config/.git 137 | 138 | # Install LinuxGSM 139 | # RUN git clone "https://github.com/joshhsoj1902/LinuxGSM.git" /home/linuxgsm/linuxgsm \ 140 | # && git checkout joshhsoj1902-changes-4-docker \ 141 | # && rm -rf /home/linuxgsm/linuxgsm/.git \ 142 | # # Install GameConfigs 143 | # && git clone "https://github.com/GameServerManagers/Game-Server-Configs.git" /home/linuxgsm/linuxgsm/lgsm/config-default/config-game/ \ 144 | # && rm -rf /home/linuxgsm/linuxgsm-config/.git 145 | 146 | # ADD --chown=linuxgsm:linuxgsm src /home/linuxgsm/linuxgsm 147 | # RUN git clone "https://github.com/GameServerManagers/Game-Server-Configs.git" /home/linuxgsm/linuxgsm/lgsm/config-default/config-game/ \ 148 | # && rm -rf /home/linuxgsm/linuxgsm-config/.git 149 | 150 | USER root 151 | 152 | RUN find /home/linuxgsm/linuxgsm -type f -name "*.sh" -exec chmod u+x {} \; \ 153 | && find /home/linuxgsm/linuxgsm -type f -name "*.py" -exec chmod u+x {} \; \ 154 | && chmod u+x /home/linuxgsm/linuxgsm/lgsm/functions/README.md 155 | 156 | ADD --chown=linuxgsm:linuxgsm common.cfg.tmpl ./lgsm/config-default/config-lgsm/ 157 | ADD --chown=linuxgsm:linuxgsm docker-runner.sh ./ 158 | # ADD --chown=linuxgsm:linuxgsm lgsm/ /home/linuxgsm/linuxgsm/lgsm/ 159 | ADD --chown=linuxgsm:linuxgsm config-game-template/ /home/linuxgsm/linuxgsm/lgsm/config-default/config-game-template/ 160 | 161 | # This file isn't always created when running in docker. Ideally we shouldn't need it. 162 | RUN touch /.dockerenv 163 | 164 | USER linuxgsm 165 | 166 | COPY --chown=linuxgsm:linuxgsm --from=builder /monitor monitor 167 | 168 | RUN mkdir logs serverfiles 169 | 170 | # This dir shouldn't be used anymore, use Saves instead 171 | RUN mkdir serverfiles/Saves 172 | 173 | # serverfiles/Saves is meant to be a common place to put save files when a server supports putting the files somewhere. 174 | # Creating this folder now works around https://github.com/docker/compose/issues/3270 175 | RUN mkdir Saves 176 | 177 | ARG OS=linux 178 | ARG ARCH=amd64 179 | 180 | HEALTHCHECK --start-period=60s --timeout=300s --interval=60s --retries=3 CMD curl -f http://localhost:28080/live || exit 1 181 | 182 | ENTRYPOINT ["bash", "./docker-runner.sh"] 183 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Daniel Gibbs 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 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | GO := go 2 | 3 | COMMIT ?= `git rev-parse --short HEAD 2>/dev/null` 4 | VERSION ?= `git describe --abbrev=0 --tags $(git rev-list --tags --max-count=1) 2>/dev/null | sed 's/v\(.*\)/\1/'` 5 | BUILD_DATE ?= `date -u +"%Y-%m-%dT%H:%M:%SZ"` 6 | 7 | COMMIT_FLAG := -X `go list ./src/version`.GitCommit=$(COMMIT) 8 | VERSION_FLAG := -X `go list ./src/version`.Version=$(VERSION) 9 | BUILD_DATE_FLAG := -X `go list ./src/version`.BuildDate=$(BUILD_DATE) 10 | 11 | GOOS ?= $(shell go version | sed 's/^.*\ \([a-z0-9]*\)\/\([a-z0-9]*\)/\1/') 12 | GOARCH ?= $(shell go version | sed 's/^.*\ \([a-z0-9]*\)\/\([a-z0-9]*\)/\2/') 13 | 14 | build: 15 | @docker build \ 16 | --compress \ 17 | -f Dockerfile \ 18 | -t joshhsoj1902/linuxgsm-docker \ 19 | . 20 | docker tag joshhsoj1902/linuxgsm-docker:latest joshhsoj1902/linuxgsm-docker:local 21 | start: 22 | docker-compose up game 23 | stackup: 24 | docker stack deploy -c docker-stack.yml a 25 | stackdown: 26 | docker stack rm a 27 | 28 | build-monitor: 29 | GOOS=$(shell echo $* | cut -f1 -d-) GOARCH=$(shell echo $* | cut -f2 -d- | cut -f1 -d.) CGO_ENABLED=0 \ 30 | $(GO) build \ 31 | -ldflags "-w -s $(COMMIT_FLAG) $(VERSION_FLAG) $(BUILD_DATE_FLAG)" \ 32 | -o monitor \ 33 | ./src/cmd/monitor/monitor.go 34 | 35 | test: 36 | ./scripts/test-gomplate.sh 37 | 38 | .PHONY: build 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **NOTE**: This repo will likely be archived soon. LinuxGSM now has beta support for docker as seen [here](https://github.com/GameServerManagers/docker-gameserver). I've been working on extending it [here](https://github.com/joshhsoj1902/docker-linuxgsm-scripts). Anyone looking for a starting point for running LinuxGSM in a docker container, this repo isn't a good place to start anymore. 2 | 3 | --- 4 | 5 | # linuxgsm-docker 6 | 7 | [![CircleCI][circle-image]][circle-url] 8 | 9 | Unoffical Dockerized version of the [Linux Game Server Manager][lgsm-home] project 10 | ## Usage 11 | 12 | The simplest way to start a server is to use a docker-compose command that looks like this: 13 | 14 | ```shell 15 | docker-compose -p css -f examples/docker-compose.css.yml up 16 | ``` 17 | 18 | `-p` sets the "project" name, this isn't needed, but it'll help if you're running multiple servers. 19 | 20 | `-f` sets the compose file you want to run. 21 | 22 | ## Examples 23 | 24 | In the examples folder there are sample setups for many game servers. Each compose file has a status section that describes the current state of that server. If I know the server is in a working state it'll say it there. There are many popular games that I don't own so can't properly test, if you are able to confirm that a server is working please let me know and I'll update the status section. 25 | 26 | There will also be links to find what config options exist for that server and some details on save files. 27 | 28 | ## Configuration 29 | 30 | All configuration is done via environment variables. All servers will reference a config file in the main linuxGSM project. For css that file is [here](https://github.com/GameServerManagers/LinuxGSM/blob/master/lgsm/config-default/config-lgsm/cssserver/_default.cfg). All settings in those `_default.cfg` can be set by prepending `LGSM_` onto the name of the config, everything should be capitalized. 31 | 32 | For example, if you wanted to set the css "gslt" value the environment variable it would look like: 33 | 34 | ```yaml 35 | environment: 36 | - LGSM_GAMESERVERNAME=cssserver 37 | - LGSM_UPDATEINSTALLSKIP=UPDATE 38 | - LGSM_PORT=27015 39 | - LGSM_GSLT=myValue 40 | ``` 41 | 42 | Some games also support a config file. The config files currently supported are found [here](https://github.com/joshhsoj1902/linuxgsm-docker/tree/master/config-game-template). The configs in that folder are templated so that the environment variables can be injected more easily. If the game you're looking to play needs a custom config file I will need to manually add it, If the config file is out of date I'll need to manually update it. If this happens please open an issue and I'll get around to it ASAP. 43 | 44 | To set one of these configs you just need to use the same variable you see in the config file. For example, if you wanted to change the default max players allowed on a minecraft server, you can see the config for that [here](https://github.com/joshhsoj1902/linuxgsm-docker/blob/master/config-game-template/Minecraft/server.properties.tmpl#L20), the config in this case would be `LGSM_MAX_PLAYERS`, So to change that in the docker-compose file you would want to set it like this: 45 | 46 | ```yaml 47 | environment: 48 | ## Out of the box LGSM 49 | - LGSM_GAMESERVERNAME=mcserver 50 | - LGSM_UPDATEINSTALLSKIP=UPDATE 51 | - LGSM_PORT=25565 52 | - LGSM_MAX_PLAYERS=10 53 | ``` 54 | 55 | ## Save files 56 | 57 | Many gameservers save files. By default all the compose files create a volume called `[project]_serverfiles`. The files in the volume are preserved across container restarts, but if you were to accidentally delete that volume the files would be gone. 58 | 59 | Another option is to change how the files are saved. In the compose file if you update the `volumes` section to look like this 60 | 61 | ```yaml 62 | volumes: 63 | - /local/path/where/you/want/to/save:/home/linuxgsm/linuxgsm/serverfiles 64 | ``` 65 | 66 | The "left" side of that can be updated to a local folder on your computer. The files that the server writes will now be saved there instead. Since the data is now stored outside of docker it's a little easier to manage and backup. 67 | 68 | 69 | [circle-image]: https://circleci.com/gh/joshhsoj1902/linuxgsm-docker/tree/master.svg?style=svg 70 | [circle-url]: https://circleci.com/gh/joshhsoj1902/linuxgsm-docker/tree/master 71 | [lgsm-config]: https://github.com/GameServerManagers/LinuxGSM/tree/master/lgsm/config-default/config-lgsm 72 | [lgsm-home]: https://github.com/GameServerManagers/LinuxGSM 73 | -------------------------------------------------------------------------------- /common.cfg.tmpl: -------------------------------------------------------------------------------- 1 | ################################## 2 | ######## Instance Settings ######## 3 | ################################## 4 | # PLACE COMMON SETTINGS HERE 5 | # 6 | 7 | {{if (datasource "env").Envs}} 8 | 9 | {{ range (datasource "env").Envs -}} 10 | {{ .name }}={{ .value | quote }} 11 | {{ end }} 12 | 13 | {{else}} 14 | 15 | {{ range (datasource "env").envs -}} 16 | {{ .name }}={{ .value | quote }} 17 | {{ end }} 18 | 19 | {{end}} 20 | 21 | # TODO This handles reading the save from the right place, It doesn't handle creation 22 | # https://github.com/GameServerManagers/LinuxGSM/blob/3f1f2aa2d8ab5e2d2b6ecb4af795b287e06b46ff/lgsm/functions/install_factorio_save.sh 23 | # Can that ^ be done in an override? likely not if the server hasn't been installed yet... 24 | 25 | {{if eq (getenv "LGSM_GAMESERVERNAME") "fctrserver"}} 26 | ## Server Start Command | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters 27 | fn_parms(){ 28 | savepath="${LGSM_SAVE_PATH:-${serverfiles}/save1.zip}" 29 | parms="--start-server ${savepath} --server-settings ${servercfgfullpath} --port ${port} --rcon-port ${rconport} --rcon-password ${rconpassword}" 30 | } 31 | {{end}} 32 | -------------------------------------------------------------------------------- /config-game-template/7DaysToDie/serverconfig.xml.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | {{if (getenv "LGSM_SERVER_PORT")}} 14 | 15 | {{else}} 16 | 17 | {{end}} 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 123 | 124 | -------------------------------------------------------------------------------- /config-game-template/Factorio/server-settings.json.tmpl: -------------------------------------------------------------------------------- 1 | { 2 | {{if (getenv "LGSM_SERVER_NAME")}} 3 | "name": "{{getenv "LGSM_SERVER_NAME" "SERVERNAME"}}", 4 | {{else}} 5 | "name": "{{getenv "LGSM_HOSTNAME" "SERVERNAME"}}", 6 | {{end}} 7 | "description": "Description of the game that will appear in the listing", 8 | "tags": {{getenv "LGSM_TAGS" "[\"game\", \"tags\"]"}}, 9 | 10 | "_comment_max_players": "Maximum number of players allowed, admins can join even a full server. 0 means unlimited.", 11 | "max_players": {{getenv "LGSM_MAX_PLAYERS" "0"}}, 12 | 13 | "_comment_visibility": ["public: Game will be published on the official Factorio matching server", 14 | "lan: Game will be broadcast on LAN"], 15 | "visibility": 16 | { 17 | "public": {{getenv "LGSM_PUBLIC" "true"}}, 18 | "lan": {{getenv "LGSM_LAN" "true"}} 19 | }, 20 | 21 | "_comment_credentials": "Your factorio.com login credentials. Required for games with visibility public", 22 | "username": "", 23 | "password": "", 24 | 25 | "_comment_token": "Authentication token. May be used instead of 'password' above.", 26 | "token": "{{getenv "LGSM_TOKEN" ""}}", 27 | 28 | "game_password": "{{getenv "LGSM_GAME_PASSWORD" ""}}", 29 | 30 | "_comment_require_user_verification": "When set to true, the server will only allow clients that have a valid Factorio.com account", 31 | "require_user_verification": {{getenv "LGSM_REQUIRE_USER_VERIFICATION" "true"}}, 32 | 33 | "_comment_max_upload_in_kilobytes_per_second" : "optional, default value is 0. 0 means unlimited.", 34 | "max_upload_in_kilobytes_per_second": {{getenv "LGSM_MAX_UPLOAD_IN_KILOBYTES_PER_SECOND" "0"}}, 35 | 36 | "_comment_minimum_latency_in_ticks": "optional one tick is 16ms in default speed, default value is 0. 0 means no minimum.", 37 | "minimum_latency_in_ticks": {{getenv "LGSM_MINIMUM_LATENCY_IN_TICKS" "0"}}, 38 | 39 | "_comment_ignore_player_limit_for_returning_players": "Players that played on this map already can join even when the max player limit was reached.", 40 | "ignore_player_limit_for_returning_players": {{getenv "LGSM_IGNORE_PLAYER_LIMIT_FOR_RETURNING_PLAYERS" "false"}}, 41 | 42 | "_comment_allow_commands": "possible values are, true, false and admins-only", 43 | "allow_commands": "{{getenv "LGSM_ALLOW_COMMANDS" "admins-only" }}", 44 | 45 | "_comment_autosave_interval": "Autosave interval in minutes", 46 | "autosave_interval": {{getenv "LGSM_AUTOSAVE_INTERVAL" "10"}}, 47 | 48 | "_comment_autosave_slots": "server autosave slots, it is cycled through when the server autosaves.", 49 | "autosave_slots": {{getenv "LGSM_AUTOSAVE_SLOTS" "5"}}, 50 | 51 | "_comment_afk_autokick_interval": "How many minutes until someone is kicked when doing nothing, 0 for never.", 52 | "afk_autokick_interval": {{getenv "LGSM_AFK_AUTOKICK_INTERVAL" "0"}}, 53 | 54 | "_comment_auto_pause": "Whether should the server be paused when no players are present.", 55 | "auto_pause": {{getenv "LGSM_AUTO_PAUSE" "true"}}, 56 | 57 | "only_admins_can_pause_the_game": {{getenv "LGSM_ONLY_ADMINS_CAN_PAUSE_THE_GAME" "true"}}, 58 | 59 | "_comment_autosave_only_on_server": "Whether autosaves should be saved only on server or also on all connected clients. Default is true.", 60 | "autosave_only_on_server": {{getenv "LGSM_AUTOSAVE_ONLY_ON_SERVER" "true"}}, 61 | 62 | "_comment_admins": "List of case insensitive usernames, that will be promoted immediately", 63 | "admins": {{getenv "LGSM_ADMINS" "[]"}} 64 | 65 | } 66 | -------------------------------------------------------------------------------- /config-game-template/GarrysMod/server.cfg.tmpl: -------------------------------------------------------------------------------- 1 | // 28Sept2019 2 | 3 | // Hostname for server. 4 | {{if (getenv "LGSM_SERVER_NAME")}} 5 | hostname {{getenv "LGSM_SERVER_NAME" "SERVERNAME"}} 6 | {{else}} 7 | hostname {{getenv "LGSM_HOSTNAME" "SERVERNAME"}} 8 | {{end}} 9 | 10 | // RCON - remote console password. 11 | rcon_password {{getenv "LGSM_RCON_PASSWORD" "ADMINPASSWORD"}} 12 | 13 | // Server password - for private servers. 14 | sv_password {{getenv "LGSM_SV_PASSWORD" ""}} 15 | 16 | // Server Logging 17 | log on 18 | sv_logbans 1 19 | sv_logecho 1 20 | sv_logfile 1 21 | sv_log_onefile 0 22 | lua_log_sv 0 23 | 24 | sv_rcon_banpenalty 0 25 | sv_rcon_maxfailures 20 26 | sv_rcon_minfailures 20 27 | sv_rcon_minfailuretime 20 28 | 29 | // Network Settings 30 | sv_downloadurl "" 31 | sv_loadingurl "" 32 | net_maxfilesize 64 33 | sv_maxrate 0 34 | sv_minrate 800000 35 | sv_maxupdaterate 66 36 | sv_minupdaterate 33 37 | sv_maxcmdrate 66 38 | sv_mincmdrate 33 39 | 40 | // Server Settings 41 | sv_airaccelerate 100 42 | sv_gravity 600 43 | sv_allow_wait_command 0 44 | sv_allow_voice_from_file 0 45 | sv_turbophysics 0 46 | sv_max_usercmd_future_ticks 12 47 | gmod_physiterations 4 48 | sv_client_min_interp_ratio 1 49 | sv_client_max_interp_ratio 2 50 | think_limit 20 51 | sv_region 0 52 | sv_noclipspeed 5 53 | sv_noclipaccelerate 5 54 | sv_lan 0 55 | sv_alltalk 1 56 | sv_contact youremail@changeme.com 57 | sv_cheats 0 58 | sv_allowcslua 0 59 | sv_pausable 0 60 | sv_filterban 1 61 | sv_forcepreload 1 62 | sv_footsteps 1 63 | sv_voiceenable 1 64 | sv_voicecodec vaudio_speex 65 | sv_timeout 120 66 | sv_deltaprint 0 67 | sv_allowupload 0 68 | sv_allowdownload 0 69 | 70 | // Sandbox Settings 71 | sbox_noclip 0 72 | sbox_godmode 0 73 | sbox_weapons 0 74 | sbox_playershurtplayers 0 75 | sbox_maxprops 100 76 | sbox_maxragdolls 50 77 | sbox_maxnpcs 10 78 | sbox_maxballoons 10 79 | sbox_maxeffects 0 80 | sbox_maxdynamite 0 81 | sbox_maxlamps 5 82 | sbox_maxthrusters 20 83 | sbox_maxwheels 20 84 | sbox_maxhoverballs 20 85 | sbox_maxvehicles 1 86 | sbox_maxbuttons 20 87 | sbox_maxemitters 0 88 | 89 | // Misc Config 90 | exec banned_user.cfg 91 | exec banned_ip.cfg 92 | heartbeat 93 | -------------------------------------------------------------------------------- /config-game-template/Minecraft/server.properties.tmpl: -------------------------------------------------------------------------------- 1 | #Minecraft server properties (LGSM 210516) 2 | #Sat Aug 20 17:30:15 CEST 2016 3 | allow-flight={{getenv "LGSM_ALLOW_FLIGHT" "false"}} 4 | allow-nether={{getenv "LGSM_ALLOW_NETHER" "true"}} 5 | announce-player-achievements={{getenv "LGSM_ANNOUNCE_PLAYER_ACHIEVEMENTS" "true"}} 6 | difficulty={{getenv "LGSM_DIFFICULTY" "1"}} 7 | enable-command-block={{getenv "LGSM_ENABLE_COMMAND_BLOCK" "false"}} 8 | enable-query={{getenv "LGSM_ENABLE_QUERY" "true"}} 9 | enable-rcon={{getenv "LGSM_ENABLE_RCON" "false"}} 10 | query.port={{getenv "LGSM_QUERY_PORT" "25565"}} 11 | force-gamemode={{getenv "LGSM_FORCE_GAMEMODE" "false"}} 12 | gamemode={{getenv "LGSM_GAMEMODE" "0"}} 13 | generate-structures={{getenv "LGSM_GENERATOR_STRUCTURES" "true"}} 14 | generator-settings={{getenv "LGSM_GENERATOR_SETTINGS" ""}} 15 | hardcore={{getenv "LGSM_HARDCORE" "false"}} 16 | level-name={{getenv "LGSM_LEVEL_NAME" "world"}} 17 | level-seed={{getenv "LGSM_LEVEL_SEED" ""}} 18 | level-type={{getenv "LGSM_LEVEL_TYPE" "DEFAULT"}} 19 | max-build-height={{getenv "LGSM_MAX_BUILD_HEIGHT" "256"}} 20 | max-players={{getenv "LGSM_MAX_PLAYERS" "20"}} 21 | max-tick-time={{getenv "LGSM_MAX_TICK_TIME" "60000"}} 22 | max-world-size={{getenv "LGSM_MAX_WORLD_SIZE" "29999984"}} 23 | motd={{getenv "LGSM_MOTD" "SERVERNAME"}} 24 | network-compression-threshold={{getenv "LGSM_NETWORK_COMPRESSION_THRESHOLD" "256"}} 25 | online-mode={{getenv "LGSM_ONLINE_MODE" "true"}} 26 | op-permission-level={{getenv "LGSM_OP_PERMISSION_LEVEL" "4"}} 27 | player-idle-timeout={{getenv "LGSM_PLAYER_IDLE_TIMEOUT" "0"}} 28 | pvp={{getenv "LGSM_PVP" "true"}} 29 | rcon.password={{getenv "LGSM_RCON_PASSWORD" "ADMINPASSWORD"}} 30 | rcon.port={{getenv "LGSM_RCON_PORT" "25575"}} 31 | resource-pack-sha1= 32 | resource-pack= 33 | server-ip={{getenv "LGSM_IP" ""}} 34 | server-port={{getenv "LGSM_PORT" "25565"}} 35 | snooper-enabled={{getenv "LGSM_SNOOPER_ENABLED" "true"}} 36 | spawn-animals={{getenv "LGSM_SPAWN_ANIMALS" "true"}} 37 | spawn-monsters={{getenv "LGSM_SPAWN_MONSTERS" "true"}} 38 | spawn-npcs={{getenv "LGSM_SPAWN_NPCS" "true"}} 39 | use-native-transport={{getenv "LGSM_USE_NATIVE_TRANSPORT" "true"}} 40 | view-distance={{getenv "LGSM_VIEW_DISTANCE" "10"}} 41 | white-list=false 42 | -------------------------------------------------------------------------------- /config-game-template/README.md: -------------------------------------------------------------------------------- 1 | # Custom Configs 2 | 3 | Folders in here will override the default files found [here](https://github.com/GameServerManagers/Game-Server-Configs) 4 | -------------------------------------------------------------------------------- /docker-compose.citest.yml: -------------------------------------------------------------------------------- 1 | version: '3.1' 2 | services: 3 | css: 4 | image: joshhsoj1902/linuxgsm-docker:latest 5 | ports: 6 | - "30015:30015/tcp" 7 | - "30015:30015/udp" 8 | - "30020:30020/udp" 9 | - "30005:30005/udp" 10 | environment: 11 | - LGSM_GAMESERVERNAME=cssserver 12 | - LGSM_UPDATEINSTALLSKIP=UPDATE 13 | - LGSM_IP=0.0.0.0 14 | - LGSM_PORT=30015 15 | volumes: 16 | - "./logs:/home/linuxgsm/linuxgsm/logs" 17 | -------------------------------------------------------------------------------- /docker-compose.gmod.yml: -------------------------------------------------------------------------------- 1 | version: '3.1' 2 | services: 3 | game: 4 | image: joshhsoj1902/linuxgsm-docker:latest 5 | environment: 6 | - LGSM_GAMESERVERNAME=gmodserver 7 | - LGSM_UPDATEINSTALLSKIP=UPDATE 8 | - LGSM_PORT=20000 9 | - LGSM_DEFAULTMAP=gm_construct 10 | - LGSM_GAMEMODE=sandbox 11 | # - LGSM_WORKSHOPAUTH 12 | # - LGSM_WORKSHOPCOLLECTIONID 13 | volumes: 14 | - "/home/linuxgsm/linuxgsm/logs" 15 | - "/home/linuxgsm/linuxgsm/serverfiles/" 16 | 17 | 18 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.1' 2 | services: 3 | game: 4 | image: joshhsoj1902/linuxgsm-docker:latest 5 | environment: 6 | - LGSM_GAMESERVERNAME=cssserver 7 | - LGSM_UPDATEINSTALLSKIP=UPDATE 8 | - LGSM_PORT=27015 9 | volumes: 10 | - "/home/linuxgsm/linuxgsm/logs" 11 | -------------------------------------------------------------------------------- /docker-runner.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | cleanup() { 6 | echo "Exit received" 7 | 8 | echo "Stopping server" 9 | ./lgsm-gameserver stop 10 | echo "Server Stopped" 11 | 12 | echo "Shutting down" 13 | exit 0 14 | } 15 | 16 | trap 'cleanup' SIGINT SIGTERM 17 | 18 | for f in startup-scripts/*.sh; do 19 | bash "$f" -H || break 20 | done 21 | 22 | #Set ENV defaults 23 | if [ -n "$LGSM_PORT" ]; then 24 | if [ -z "$LGSM_CLIENTPORT" ]; then 25 | clientport=$(($LGSM_PORT-10)) 26 | echo "clientPort $clientport" 27 | export LGSM_CLIENTPORT=$clientport 28 | fi 29 | if [ -z "$LGSM_SOURCETVPORT" ]; then 30 | sourcetvport=$(($LGSM_PORT+5)) 31 | echo "sourcetvport $sourcetvport" 32 | export LGSM_SOURCETVPORT=$sourcetvport 33 | fi 34 | fi 35 | 36 | ./monitor & 37 | 38 | parse-env --env "LGSM_" > env.json 39 | 40 | rm -f INSTALLING.LOCK 41 | 42 | if [ -z "$LGSM_GAMESERVERNAME" ]; then echo "Need to set LGSM_GAMESERVERNAME environment" 43 | exit 1 44 | fi 45 | 46 | echo "IP is set to "${LGSM_IP} 47 | 48 | echo "Gomplating main config" 49 | mkdir -p ~/linuxgsm/lgsm/config-lgsm/$LGSM_GAMESERVERNAME 50 | gomplate -d env=~/linuxgsm/env.json -f ~/linuxgsm/lgsm/config-default/config-lgsm/common.cfg.tmpl -o ~/linuxgsm/lgsm/config-lgsm/$LGSM_GAMESERVERNAME/common.cfg 51 | if [ -f ~/linuxgsm/lgsm/config-lgsm/$LGSM_GAMESERVERNAME/$LGSM_GAMESERVERNAME.cfg.tmpl ]; then 52 | gomplate -d env=~/linuxgsm/env.json -f ~/linuxgsm/lgsm/config-lgsm/$LGSM_GAMESERVERNAME/$LGSM_GAMESERVERNAME.cfg.tmpl -o ~/linuxgsm/lgsm/config-lgsm/$LGSM_GAMESERVERNAME/$LGSM_GAMESERVERNAME.cfg 53 | fi 54 | 55 | echo "Gomplating game configs" 56 | for d in /home/linuxgsm/linuxgsm/lgsm/config-default/config-game-template/*/ ; do 57 | configGameFolder=$(basename $d) 58 | for f in $d/*.tmpl ; do 59 | configGameFile=$(basename $f) 60 | outputConfigGameFile=$(basename $f .tmpl) 61 | outputFile="/home/linuxgsm/linuxgsm/lgsm/config-default/config-game/$configGameFolder/$outputConfigGameFile" 62 | gomplate -f $f -o $outputFile 63 | chmod u+x,g+x $outputFile 64 | done 65 | done 66 | 67 | echo "DONE GOMPLATING" 68 | 69 | echo "Start tailing logs" 70 | 71 | if [ "$LGSM_CONSOLE_STDOUT" == "true" ]; then 72 | tail -F ~/linuxgsm/log/console/lgsm-gameserver-console.log & 73 | fi 74 | 75 | if [ "$LGSM_SCRIPT_STDOUT" == "true" ]; then 76 | tail -F ~/linuxgsm/log/script/lgsm-gameserver-script.log & 77 | fi 78 | 79 | if [ "$LGSM_ALERT_STDOUT" == "true" ]; then 80 | tail -F ~/linuxgsm/log/script/lgsm-gameserver-alert.log & 81 | fi 82 | 83 | if [ "$LGSM_GAME_STDOUT" == "true" ]; then 84 | tail -F ~/linuxgsm/log/server/output_log*.txt & 85 | fi 86 | 87 | 88 | if [ -n "$LGSM_UPDATEINSTALLSKIP" ]; then 89 | case "$LGSM_UPDATEINSTALLSKIP" in 90 | "UPDATE") 91 | touch INSTALLING.LOCK 92 | ./linuxgsm.sh $LGSM_GAMESERVERNAME 93 | mv $LGSM_GAMESERVERNAME lgsm-gameserver 94 | ./lgsm-gameserver auto-install || true 95 | exitcode="$?" 96 | 97 | if [ "$exitcode" -gt "0" ] && [ "$exitcode" != "3" ]; then 98 | # Retry once 99 | echo "Unexpected error when updating ($exitcode). Trying again." 100 | ./lgsm-gameserver auto-install || true 101 | exitcode="$?" 102 | fi 103 | 104 | rm -f INSTALLING.LOCK 105 | 106 | if [ "$exitcode" != "0" ] && [ "$exitcode" != "3" ]; then 107 | # exitcode 3 is a warning, in this case the warning we don't care about is steam not being installed 108 | # any other thing not being installed is an issue, but steam will be installed if it's missing. 109 | # we can't use the one in apt-get for some reason (it installs but it always hangs installing games) 110 | echo "Unexpected exit code during install $exitcode" 111 | exit $exitcode 112 | fi 113 | 114 | echo "Game has been updated. Starting" 115 | ;; 116 | "INSTALL") 117 | touch INSTALLING.LOCK 118 | ./linuxgsm.sh $LGSM_GAMESERVERNAME 119 | mv $LGSM_GAMESERVERNAME lgsm-gameserver || true 120 | ls -ltr 121 | ./lgsm-gameserver auto-install || true 122 | exitcode="$?" 123 | 124 | if [ "$exitcode" -gt "0" ] && [ "$exitcode" != "3" ]; then 125 | # Retry once 126 | echo "Unexpected error when installing ($exitcode). Trying again." 127 | ./lgsm-gameserver auto-install || true 128 | exitcode="$?" 129 | fi 130 | 131 | echo "Install returned code $exitcode" 132 | rm -f INSTALLING.LOCK 133 | 134 | if [ "$exitcode" != "0" ] && [ "$exitcode" != "3" ]; then 135 | # exitcode 3 is a warning, in this case the warning we don't care about is steam not being installed 136 | # any other thing not being installed is an issue, but steam will be installed if it's missing. 137 | # we can't use the one in apt-get for some reason (it installs but it always hangs installing games) 138 | echo "Unexpected exit code during uninstall $exitcode" 139 | exit $exitcode 140 | fi 141 | 142 | echo "Game has been installed. Exiting" 143 | exit 144 | ;; 145 | esac 146 | fi 147 | 148 | if [ ! -f lgsm-gameserver ]; then 149 | echo "No game is installed, please set LGSM_UPDATEINSTALLSKIP" 150 | exit 1 151 | fi 152 | 153 | # # configure game-specfic settings 154 | # gomplate -f ${servercfgfullpath}.tmpl -o ${servercfgfullpath} // I can't predict what the filename is. 155 | 156 | 157 | if [ "$LGSM_STOP_ON_FAILURE" == "true" ]; then 158 | ./lgsm-gameserver start 159 | else 160 | ./lgsm-gameserver start || true 161 | fi 162 | 163 | sleep 30s 164 | 165 | ./lgsm-gameserver details 166 | 167 | wait $! 168 | 169 | sleep 30s 170 | -------------------------------------------------------------------------------- /docker-stack.yml: -------------------------------------------------------------------------------- 1 | version: '3.2' 2 | services: 3 | game: 4 | image: joshhsoj1902/linuxgsm-docker:local 5 | ports: 6 | - target: 27015 7 | published: 27015 8 | protocol: tcp 9 | - target: 27015 10 | published: 27015 11 | protocol: udp 12 | - target: 27020 13 | published: 27020 14 | protocol: udp 15 | - target: 27005 16 | published: 27005 17 | protocol: udp 18 | deploy: 19 | mode: replicated 20 | replicas: 1 21 | environment: 22 | # - LGSM_GAMESERVERNAME=mumbleserver 23 | - LGSM_IP=0.0.0.0 24 | - LGSM_GAMESERVERNAME=cssserver 25 | - LGSM_UPDATEINSTALLSKIP=UPDATE 26 | 27 | 28 | -------------------------------------------------------------------------------- /examples/docker-compose.7dtd.yml: -------------------------------------------------------------------------------- 1 | ############################# 2 | # SERVER STATUS 3 | ############################# 4 | # 5 | # Working: Yes 6 | # Tested in CI: Yes 7 | # 8 | # Does this server have save files: Yes 9 | # Where are save files saved: See the `saves` volume 10 | # 11 | # Configuration: 12 | # - https://github.com/GameServerManagers/LinuxGSM/blob/master/lgsm/config-default/config-lgsm/sdtdserver/_default.cfg 13 | # - https://github.com/joshhsoj1902/linuxgsm-docker/blob/master/config-game-template/7DaysToDie/serverconfig.xml.tmpl 14 | # 15 | ############################ 16 | 17 | version: '3.3' 18 | volumes: 19 | saves: 20 | serverfiles: 21 | services: 22 | 7dtd: 23 | image: joshhsoj1902/linuxgsm-docker:latest 24 | ports: 25 | - 26900:26900 26 | environment: 27 | - LGSM_GAMESERVERNAME=sdtdserver 28 | - LGSM_SERVERCFGFULLPATHDEFAULT=/home/linuxgsm/linuxgsm/lgsm/config-default/config-game/7DaysToDie/serverconfig.xml 29 | - LGSM_UPDATEINSTALLSKIP=UPDATE 30 | 31 | # See /config-game-template/7DaysToDie/serverconfig.xml.tmpl for all config options 32 | - LGSM_PORT=26900 33 | 34 | # DO NOT SET LGSM_SERVER_VISIBILITY TO 0/1. LGSM uses this to check if server is running 35 | - LGSM_SERVER_VISIBILITY=2 36 | 37 | - LGSM_SERVER_NAME=LGSM Server 38 | - LGSM_GAME_NAME=My Game 39 | - LGSM_WORLD_GEN_SEED=ChangeMe 40 | - LGSM_GAME_WORLD=RWG 41 | # - LGSM_EAC_ENABLED=false 42 | 43 | # https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes 44 | volumes: 45 | - saves:/home/linuxgsm/linuxgsm/Saves 46 | - serverfiles:/home/linuxgsm/linuxgsm/serverfiles 47 | -------------------------------------------------------------------------------- /examples/docker-compose.ark.yml: -------------------------------------------------------------------------------- 1 | ############################# 2 | # SERVER STATUS 3 | ############################# 4 | # 5 | # Working: Unsure 6 | # Tested in CI: Yes 7 | # 8 | # Does this server have save files: Yes 9 | # Where are save files saved: Unsure, somewhere in `serverfiles` 10 | # 11 | # Configuration: 12 | # - https://github.com/GameServerManagers/LinuxGSM/blob/master/lgsm/config-default/config-lgsm/arkserver/_default.cfg 13 | # 14 | ############################ 15 | 16 | version: '3.3' 17 | volumes: 18 | serverfiles: 19 | services: 20 | ark: 21 | image: joshhsoj1902/linuxgsm-docker:latest 22 | ports: 23 | - 7777:7777/tcp 24 | - 7777:7777/udp 25 | environment: 26 | - LGSM_GAMESERVERNAME=arkserver 27 | - LGSM_UPDATEINSTALLSKIP=UPDATE 28 | - LGSM_PORT=7777 29 | - LGSM_QUERYPORT=27015 30 | - LGSM_RCONPORT=27020 31 | - LGSM_DEFAULTMAP=TheIsland 32 | - LGSM_MAXPLAYERS=70 33 | 34 | # https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes 35 | volumes: 36 | - serverfiles:/home/linuxgsm/linuxgsm/serverfiles 37 | -------------------------------------------------------------------------------- /examples/docker-compose.arma3.yml: -------------------------------------------------------------------------------- 1 | ############################# 2 | # SERVER STATUS 3 | ############################# 4 | # 5 | # Working: No Clue (I can't even install it) 6 | # Tested in CI: No 7 | # 8 | # Does this server have save files: Unsure 9 | # Where are save files saved: Unsure, somewhere in `serverfiles` 10 | # 11 | # Configuration: 12 | # - https://github.com/GameServerManagers/LinuxGSM/blob/master/lgsm/config-default/config-lgsm/arma3server/_default.cfg 13 | # 14 | ############################ 15 | 16 | version: '3.1' 17 | services: 18 | arma3: 19 | image: joshhsoj1902/linuxgsm-docker:latest 20 | ports: 21 | - 2302:2302/tcp 22 | - 2302:2302/udp 23 | environment: 24 | - LGSM_GAMESERVERNAME=arma3server 25 | - LGSM_UPDATEINSTALLSKIP=UPDATE 26 | - LGSM_PORT=2302 27 | # - LGSM_STEAMUSER="username" 28 | # - LGSM_STEAMPASS="password" 29 | 30 | ## ARMA 3 Modules 31 | # Add mods with relative paths: 32 | # mods/@cba_a3 33 | # To load the "Community Base Addons v3" module found in the 34 | # directory serverfiles/mods/@cba_a3. Load several mods as: 35 | # mods="mods/@ace\;mods/@acex\;mods/@cba_a3" 36 | - LGSM_MODS="" 37 | 38 | ## Server-side Mods 39 | - LGSM_SERVERMODS="" 40 | 41 | ## Path to BattlEye 42 | # Leave empty for default 43 | - LGSM_BEPATH="" 44 | 45 | # https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes 46 | volumes: 47 | - serverfiles:/home/linuxgsm/linuxgsm/serverfiles 48 | 49 | -------------------------------------------------------------------------------- /examples/docker-compose.csgo.yml: -------------------------------------------------------------------------------- 1 | ############################# 2 | # SERVER STATUS 3 | ############################# 4 | # 5 | # Working: Unsure 6 | # Tested in CI: Yes 7 | # 8 | # Does this server have save files: No 9 | # 10 | # Configuration: 11 | # - https://github.com/GameServerManagers/LinuxGSM/blob/master/lgsm/config-default/config-lgsm/csgoserver/_default.cfg 12 | # 13 | ############################ 14 | 15 | version: '3.3' 16 | volumes: 17 | serverfiles: 18 | services: 19 | csgo: 20 | image: joshhsoj1902/linuxgsm-docker:latest 21 | ports: 22 | - 27015:27015/tcp 23 | - 27015:27015/udp 24 | environment: 25 | - LGSM_GAMESERVERNAME=csgoserver 26 | - LGSM_UPDATEINSTALLSKIP=UPDATE 27 | - LGSM_PORT=27015 28 | 29 | # https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes 30 | volumes: 31 | - serverfiles:/home/linuxgsm/linuxgsm/serverfiles 32 | -------------------------------------------------------------------------------- /examples/docker-compose.css.yml: -------------------------------------------------------------------------------- 1 | ############################# 2 | # SERVER STATUS 3 | ############################# 4 | # 5 | # Working: Yes 6 | # Tested in CI: Yes 7 | # 8 | # Does this server have save files: No 9 | # 10 | # Configuration: 11 | # - https://github.com/GameServerManagers/LinuxGSM/blob/master/lgsm/config-default/config-lgsm/cssserver/_default.cfg 12 | # 13 | ############################ 14 | 15 | version: '3.3' 16 | volumes: 17 | serverfiles: 18 | services: 19 | css: 20 | image: joshhsoj1902/linuxgsm-docker:latest 21 | ports: 22 | - 27015:27015/tcp 23 | - 27015:27015/udp 24 | environment: 25 | - LGSM_GAMESERVERNAME=cssserver 26 | - LGSM_UPDATEINSTALLSKIP=UPDATE 27 | - LGSM_PORT=27015 28 | 29 | # https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes 30 | volumes: 31 | - serverfiles:/home/linuxgsm/linuxgsm/serverfiles 32 | -------------------------------------------------------------------------------- /examples/docker-compose.factorio.yml: -------------------------------------------------------------------------------- 1 | ############################# 2 | # SERVER STATUS 3 | ############################# 4 | # 5 | # Working: Yes 6 | # Tested in CI: No 7 | # 8 | # Does this server have save files: Yes 9 | # Where are save files saved: LGSM_SAVE_PATH environment config. 10 | # I highly recommend commenting out the `serverfiles` volume, then uncommenting out the localpath mount. 11 | # You'll need to update the path to a folder that exists on your local machine. Then you'll need to use single player 12 | # factorio to generate a world and then copy it to that folder. 13 | # 14 | # Configuration: 15 | # - https://github.com/GameServerManagers/LinuxGSM/blob/master/lgsm/config-default/config-lgsm/factserver/_default.cfg 16 | # - https://github.com/joshhsoj1902/linuxgsm-docker/blob/master/config-game-template/Factorio/server-settings.json.tmpl 17 | # 18 | ############################ 19 | 20 | version: '3.3' 21 | volumes: 22 | serverfiles: 23 | services: 24 | factorio: 25 | image: joshhsoj1902/linuxgsm-docker:latest 26 | ports: 27 | - 34197:34197/udp 28 | environment: 29 | - LGSM_GAMESERVERNAME=fctrserver 30 | - LGSM_UPDATEINSTALLSKIP=UPDATE 31 | - LGSM_PORT=34197 32 | 33 | # If LGSM_SAVE_PATH is set, a world file MUST already exist at that path. 34 | - LGSM_SAVE_PATH=/home/linuxgsm/linuxgsm/serverfiles/saves/save1.zip 35 | - LGSM_SERVER_NAME="my server" 36 | 37 | # - LGSM_MAX_PLAYERS="0" 38 | # - LGSM_PUBLIC="true" 39 | # - LGSM_LAN="true" 40 | # # factorio.com Authentication token 41 | # - LGSM_TOKEN="" 42 | # - LGSM_GAME_PASSWORD="" 43 | # - LGSM_REQUIRE_USER_VERIFICATION="true" 44 | # - LGSM_MAX_UPLOAD_IN_KILOBYTES_PER_SECOND="0" 45 | # - LGSM_MINIMUM_LATENCY_IN_TICKS="0" 46 | # - LGSM_IGNORE_PLAYER_LIMIT_FOR_RETURNING_PLAYERS="false" 47 | # - LGSM_ALLOW_COMMANDS="admins-only" 48 | # - LGSM_AUTOSAVE_INTERVAL="10" 49 | # - LGSM_AUTOSAVE_SLOTS="5" 50 | # - LGSM_AFK_AUTOKICK_INTERVAL="0" 51 | # - LGSM_AUTO_PAUSE="true" 52 | # - LGSM_ONLY_ADMINS_CAN_PAUSE_THE_GAME="true" 53 | # - LGSM_AUTOSAVE_ONLY_ON_SERVER="true" 54 | 55 | # https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes 56 | volumes: 57 | - serverfiles:/home/linuxgsm/linuxgsm/serverfiles 58 | # - /local/path:/home/linuxgsm/linuxgsm/serverfiles/saves 59 | -------------------------------------------------------------------------------- /examples/docker-compose.gmod.yml: -------------------------------------------------------------------------------- 1 | ############################# 2 | # SERVER STATUS 3 | ############################# 4 | # 5 | # Working: Yes 6 | # Tested in CI: Yes 7 | # 8 | # Does this server have save files: No 9 | # 10 | # Configuration: 11 | # - https://github.com/GameServerManagers/LinuxGSM/blob/master/lgsm/config-default/config-lgsm/gmodserver/_default.cfg 12 | # - https://github.com/joshhsoj1902/linuxgsm-docker/blob/master/config-game-template/GarrysMod/server.cfg.tmpl 13 | # 14 | ############################ 15 | 16 | version: '3.3' 17 | volumes: 18 | serverfiles: 19 | services: 20 | gmod: 21 | image: joshhsoj1902/linuxgsm-docker:latest 22 | ports: 23 | - 27015:27015/tcp 24 | - 27015:27015/udp 25 | environment: 26 | - LGSM_GAMESERVERNAME=gmodserver 27 | - LGSM_UPDATEINSTALLSKIP=UPDATE 28 | - LGSM_PORT=27015 29 | - LGSM_DEFAULTMAP=gm_construct 30 | - LGSM_GAMEMODE=sandbox 31 | # - LGSM_HOSTNAME=servername 32 | # - LGSM_SV_PASSWORD=password 33 | 34 | # https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes 35 | volumes: 36 | - serverfiles:/home/linuxgsm/linuxgsm/serverfiles 37 | -------------------------------------------------------------------------------- /examples/docker-compose.inss.yml: -------------------------------------------------------------------------------- 1 | ############################# 2 | # SERVER STATUS 3 | ############################# 4 | # 5 | # Working: Unsure 6 | # Tested in CI: No 7 | # 8 | # Does this server have save files: Unsure 9 | # Where are save files saved: Unsure, somewhere in `serverfiles` 10 | # 11 | # Configuration: 12 | # - https://github.com/GameServerManagers/LinuxGSM/blob/master/lgsm/config-default/config-lgsm/inssserver/_default.cfg 13 | # 14 | ############################ 15 | 16 | version: '3.3' 17 | volumes: 18 | serverfiles: 19 | services: 20 | inss: 21 | image: joshhsoj1902/linuxgsm-docker:latest 22 | ports: 23 | - 27102:27102/udp 24 | - 27131:27131/udp 25 | environment: 26 | - LGSM_GAMESERVERNAME=inssserver 27 | - LGSM_UPDATEINSTALLSKIP=UPDATE 28 | 29 | # https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes 30 | volumes: 31 | - serverfiles:/home/linuxgsm/linuxgsm/serverfiles 32 | -------------------------------------------------------------------------------- /examples/docker-compose.minecraft.yml: -------------------------------------------------------------------------------- 1 | ############################# 2 | # SERVER STATUS 3 | ############################# 4 | # 5 | # Working: Yes 6 | # Tested in CI: Yes 7 | # 8 | # Does this server have save files: Yes 9 | # Where are save files saved: In the `serverfiles` volume, 3 main folders `world`, `world_nether`, `world_the_end` 10 | # 11 | # Configuration: 12 | # - https://github.com/GameServerManagers/LinuxGSM/blob/master/lgsm/config-default/config-lgsm/mcserver/_default.cfg 13 | # - https://github.com/joshhsoj1902/linuxgsm-docker/blob/master/config-game-template/Minecraft/server.properties.tmpl 14 | # 15 | ############################ 16 | 17 | version: '3.3' 18 | volumes: 19 | serverfiles: 20 | services: 21 | minecraft: 22 | image: joshhsoj1902/linuxgsm-docker:latest 23 | # image: joshhsoj1902/linuxgsm-docker:0.2.0 24 | ports: 25 | - 25565:25565 26 | - 28080:28080 27 | environment: 28 | ## Out of the box LGSM 29 | - LGSM_GAMESERVERNAME=mcserver 30 | - LGSM_UPDATEINSTALLSKIP=UPDATE 31 | - LGSM_PORT=25565 32 | - LGSM_JAVARAM=512 # previously LGSM_JAVA_MEMORY 33 | 34 | ## server.properties https://minecraft.gamepedia.com/Server.properties 35 | # - LGSM_ALLOW_FLIGHT 36 | # - LGSM_ALLOW_NETHER 37 | # - LGSM_ANNOUNCE_PLAYER_ACHIEVEMENTS 38 | - LGSM_DIFFICULTY=3 39 | # - LGSM_ENABLE_COMMAND_BLOCK 40 | # - LGSM_ENABLE_QUERY 41 | # - LGSM_ENABLE_RCON 42 | # - LGSM_FORCE_GAMEMODE 43 | # - LGSM_GAMEMODE 44 | # - LGSM_GENERATOR_STRUCTURES 45 | # - LGSM_GENERATOR_SETTINGS 46 | # - LGSM_HARDCORE 47 | # - LGSM_LEVEL_NAME 48 | # - LGSM_LEVEL_SEED 49 | # - LGSM_LEVEL_TYPE 50 | # - LGSM_MAX_BUILD_HEIGHT 51 | # - LGSM_MAX_PLAYERS 52 | # - LGSM_MAX_TICK_TIME 53 | # - LGSM_MAX_WORLD_SIZE 54 | - LGSM_MOTD=Minecraft Docker 55 | # - LGSM_NETWORK_COMPRESSION_THRESHOLD 56 | # - LGSM_ONLINE_MODE 57 | # - LGSM_OP_PERMISSION_LEVEL 58 | # - LGSM_PLAYER_IDLE_TIMEOUT 59 | # - LGSM_PVP 60 | # - LGSM_RCON_PASSWORD 61 | # - LGSM_RCON_PORT 62 | - LGSM_IP=0.0.0.0 63 | # - LGSM_SNOOPER_ENABLED 64 | # - LGSM_SPAWN_ANIMALS 65 | # - LGSM_SPAWN_MONSTERS 66 | # - LGSM_SPAWN_NPCS 67 | # - LGSM_USE_NATIVE_TRANSPORT 68 | # - LGSM_VIEW_DISTANCE 69 | 70 | ## extra configs 71 | # - LGSM_STOP_ON_FAILURE=false # Useful for debugging 72 | 73 | # https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes 74 | volumes: 75 | - serverfiles:/home/linuxgsm/linuxgsm/serverfiles 76 | 77 | -------------------------------------------------------------------------------- /examples/docker-compose.mohaa.yml: -------------------------------------------------------------------------------- 1 | ############################# 2 | # SERVER STATUS 3 | ############################# 4 | # 5 | # Working: Unsure 6 | # Tested in CI: Yes 7 | # 8 | # Does this server have save files: Unsure 9 | # Where are save files saved: Unsure, somewhere in `serverfiles` 10 | # 11 | # Configuration: 12 | # - https://github.com/GameServerManagers/LinuxGSM/blob/master/lgsm/config-default/config-lgsm/mohaaserver/_default.cfg 13 | # 14 | ############################ 15 | 16 | version: '3.3' 17 | volumes: 18 | serverfiles: 19 | services: 20 | mohaa: 21 | image: joshhsoj1902/linuxgsm-docker:latest 22 | ports: 23 | - 12203:12203/tcp 24 | - 12203:12203/udp 25 | environment: 26 | - LGSM_GAMESERVERNAME=mohaaserver 27 | - LGSM_UPDATEINSTALLSKIP=UPDATE 28 | - LGSM_PORT=12203 29 | - LGSM_DEFAULTMAP="dm/mohdm1" 30 | 31 | # https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes 32 | volumes: 33 | - serverfiles:/home/linuxgsm/linuxgsm/serverfiles 34 | -------------------------------------------------------------------------------- /examples/docker-compose.pstbs.yml: -------------------------------------------------------------------------------- 1 | ############################# 2 | # SERVER STATUS 3 | ############################# 4 | # 5 | # Working: Unsure 6 | # Tested in CI: No 7 | # 8 | # Does this server have save files: Unsure 9 | # Where are save files saved: Unsure, somewhere in `serverfiles` 10 | # 11 | # Configuration: 12 | # - https://github.com/GameServerManagers/LinuxGSM/blob/master/lgsm/config-default/config-lgsm/inssserver/_default.cfg 13 | # 14 | ############################ 15 | 16 | version: '3.3' 17 | volumes: 18 | serverfiles: 19 | services: 20 | pstbs: 21 | image: joshhsoj1902/linuxgsm-docker:latest 22 | ports: 23 | - 10027:10027/tcp 24 | - 10027:10027/udp 25 | environment: 26 | - LGSM_GAMESERVERNAME=pstbsserver 27 | - LGSM_UPDATEINSTALLSKIP=UPDATE 28 | - LGSM_PORT=10027 29 | - LGSM_QUERYPORT=10037 30 | - LGSM_MAXPLAYERS=80 31 | - LGSM_NUMRESERVEDSLOTS=2 32 | 33 | # https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes 34 | volumes: 35 | - serverfiles:/home/linuxgsm/linuxgsm/serverfiles 36 | -------------------------------------------------------------------------------- /examples/docker-compose.valheim.yml: -------------------------------------------------------------------------------- 1 | ############################# 2 | # SERVER STATUS 3 | ############################# 4 | # 5 | # Working: Unsure 6 | # Tested in CI: Yes 7 | # 8 | # Does this server have save files: Yes 9 | # Where are save files saved: Unsure, somewhere in `serverfiles` 10 | # 11 | # Configuration: 12 | # - https://github.com/GameServerManagers/LinuxGSM/blob/master/lgsm/config-default/config-lgsm/vhserver/_default.cfg 13 | # 14 | ############################ 15 | 16 | version: '3.3' 17 | volumes: 18 | serverfiles: 19 | services: 20 | valheim: 21 | image: joshhsoj1902/linuxgsm-docker:latest 22 | ports: 23 | - 2456:2456/tcp 24 | - 2456:2456/udp 25 | environment: 26 | - LGSM_GAMESERVERNAME=vhserver 27 | - LGSM_SERVERNAME="My Game Name" 28 | - LGSM_UPDATEINSTALLSKIP=UPDATE 29 | - LGSM_PORT=2456 30 | # World Name 31 | - LGSM_GAMEWORLD 32 | # Private=0 Public=1 33 | - LGSM_PUBLIC=1 34 | 35 | # https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes 36 | volumes: 37 | - serverfiles:/home/linuxgsm/linuxgsm/serverfiles 38 | -------------------------------------------------------------------------------- /examples/docker-compose.wet.yml: -------------------------------------------------------------------------------- 1 | ############################# 2 | # SERVER STATUS 3 | ############################# 4 | # 5 | # Working: Unsure 6 | # Tested in CI: Yes 7 | # 8 | # Does this server have save files: Unsure 9 | # Where are save files saved: Unsure, somewhere in `serverfiles` 10 | # 11 | # Configuration: 12 | # - https://github.com/GameServerManagers/LinuxGSM/blob/master/lgsm/config-default/config-lgsm/wetserver/_default.cfg 13 | # 14 | ############################ 15 | 16 | version: '3.3' 17 | volumes: 18 | serverfiles: 19 | services: 20 | wet: 21 | image: joshhsoj1902/linuxgsm-docker:latest 22 | # ports: 23 | # - 10027:10027/tcp 24 | # - 10027:10027/udp 25 | environment: 26 | - LGSM_GAMESERVERNAME=wetserver 27 | - LGSM_UPDATEINSTALLSKIP=UPDATE 28 | 29 | # https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes 30 | volumes: 31 | - serverfiles:/home/linuxgsm/linuxgsm/serverfiles 32 | -------------------------------------------------------------------------------- /examples/docker-compose.wurm.yml: -------------------------------------------------------------------------------- 1 | ############################# 2 | # SERVER STATUS 3 | ############################# 4 | # 5 | # Working: Unsure 6 | # Tested in CI: No 7 | # 8 | # Does this server have save files: Unsure 9 | # Where are save files saved: Unsure, somewhere in `serverfiles` 10 | # 11 | # Configuration: 12 | # - https://github.com/GameServerManagers/LinuxGSM/blob/master/lgsm/config-default/config-lgsm/wurmserver/_default.cfg 13 | # 14 | ############################ 15 | 16 | version: '3.3' 17 | volumes: 18 | serverfiles: 19 | services: 20 | wurm: 21 | image: joshhsoj1902/linuxgsm-docker:latest 22 | # ports: 23 | # - 10027:10027/tcp 24 | # - 10027:10027/udp 25 | environment: 26 | - LGSM_GAMESERVERNAME=wurmserver 27 | - LGSM_UPDATEINSTALLSKIP=UPDATE 28 | 29 | # https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes 30 | volumes: 31 | - serverfiles:/home/linuxgsm/linuxgsm/serverfiles 32 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ], 5 | "ignorePaths": [ 6 | "docker-compose.yml", 7 | "docker-compose.citest.yml", 8 | "docker-compose.gmod.yml", 9 | "examples" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /scripts/test-gomplate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker run --rm joshhsoj1902/linuxgsm-docker:latest gomplate -f ./lgsm/config-default/config-lgsm/common.cfg.tmpl 4 | 5 | #Custom Configs 6 | echo "\n=============\n==MINECRAFT==\n=============" 7 | docker run --rm joshhsoj1902/linuxgsm-docker:latest gomplate -f /home/linuxgsm/linuxgsm/lgsm/config-default/config-game-template/Minecraft/server.properties.tmpl 8 | echo "\n========\n==7dtd==\n========" 9 | docker run --rm joshhsoj1902/linuxgsm-docker:latest gomplate -f /home/linuxgsm/linuxgsm/lgsm/config-default/config-game-template/7DaysToDie/serverconfig.xml.tmpl 10 | echo "\n==========\n==Mumble==\n==========" 11 | docker run --rm joshhsoj1902/linuxgsm-docker:latest gomplate -f /home/linuxgsm/linuxgsm/lgsm/config-default/config-game-template/7DaysToDie/serverconfig.xml.tmpl -------------------------------------------------------------------------------- /src/cmd/monitor/monitor.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | "os" 8 | "os/exec" 9 | "strings" 10 | ) 11 | 12 | func main() { 13 | httpServer := newHttpTransport() 14 | http.HandleFunc("/live", httpServer.liveServer) 15 | http.HandleFunc("/ready", httpServer.readyServer) 16 | http.HandleFunc("/gamedig", httpServer.gamedigServer) 17 | 18 | // 28080 is my attempt to not collide with any gameserver ports 19 | fmt.Printf("Listening on port 28080\n") 20 | http.ListenAndServe(":28080", nil) 21 | } 22 | 23 | func newHttpTransport() *httpTransport { 24 | gamedig := newGamedig() 25 | 26 | return &httpTransport{ 27 | gamedig: gamedig, 28 | } 29 | } 30 | 31 | // Gamedig service 32 | type httpTransport struct { 33 | gamedig *gamedig 34 | } 35 | 36 | func (h httpTransport) liveServer(w http.ResponseWriter, r *http.Request) { 37 | w.WriteHeader(http.StatusOK) 38 | } 39 | 40 | func (h httpTransport) readyServer(w http.ResponseWriter, r *http.Request) { 41 | 42 | _, err := os.Stat("INSTALLING.LOCK") 43 | // If the file exists, it's not ready 44 | if !os.IsNotExist(err) { 45 | w.WriteHeader(http.StatusServiceUnavailable) 46 | fmt.Fprintf(w, "Game installing\n") 47 | return 48 | } 49 | 50 | if h.gamedig.gameType != "" { 51 | result, err := h.gamedig.query() 52 | 53 | if err != nil { 54 | w.WriteHeader(http.StatusServiceUnavailable) 55 | fmt.Fprintf(w, "Error querying\n") 56 | return 57 | } 58 | 59 | if result["error"] != nil { 60 | w.WriteHeader(http.StatusServiceUnavailable) 61 | fmt.Fprintf(w, "Query returned error\n") 62 | return 63 | } 64 | 65 | w.WriteHeader(http.StatusOK) 66 | // fmt.Fprintf(w, "Ready, %+v!", result) 67 | fmt.Fprintf(w, "Ready") 68 | } else { 69 | // If game doesn't support gamedig, fallback on monitor 70 | result, reason := lgsmMonitor() 71 | if result == false { 72 | w.WriteHeader(http.StatusServiceUnavailable) 73 | fmt.Fprintf(w, "%s\n", reason) 74 | return 75 | } else { 76 | w.WriteHeader(http.StatusOK) 77 | fmt.Fprintf(w, "%s\n", reason) 78 | return 79 | } 80 | } 81 | } 82 | 83 | func (h httpTransport) gamedigServer(w http.ResponseWriter, r *http.Request) { 84 | 85 | if h.gamedig.gameType != "" { 86 | result, _ := h.gamedig.query() 87 | 88 | w.WriteHeader(http.StatusOK) 89 | fmt.Fprintf(w, "%+v!", result) 90 | } else { 91 | w.WriteHeader(http.StatusOK) 92 | fmt.Fprintf(w, "Gameserver doesn't support gamedig.") 93 | } 94 | 95 | } 96 | 97 | // Gamedig service 98 | type gamedig struct { 99 | serverIP string 100 | gameType string 101 | serverPort string 102 | } 103 | 104 | func newGamedig() *gamedig { 105 | serverIP := os.Getenv("LGSM_MONITOR_IP") 106 | if serverIP == "" { 107 | serverIP = getHostname() 108 | } 109 | 110 | gamedigType := getGamedigType(os.Getenv("LGSM_GAMESERVERNAME")) 111 | 112 | serverPort := os.Getenv("LGSM_QUERY_PORT") 113 | if serverPort == "" { 114 | serverPort = os.Getenv("LGSM_PORT") 115 | } 116 | 117 | return &gamedig{ 118 | serverIP: serverIP, 119 | serverPort: serverPort, 120 | gameType: gamedigType, 121 | } 122 | } 123 | 124 | func (g *gamedig) query() (map[string]interface{}, error) { 125 | app := "gamedig" 126 | 127 | arg0 := "--type" 128 | arg1 := g.gameType 129 | arg2 := fmt.Sprintf("%s:%s", g.serverIP, g.serverPort) 130 | 131 | cmd := exec.Command(app, arg0, arg1, arg2) 132 | stdout, err := cmd.Output() 133 | 134 | if err != nil { 135 | fmt.Println(err.Error()) 136 | return nil, err 137 | } 138 | 139 | var result map[string]interface{} 140 | json.Unmarshal(stdout, &result) 141 | 142 | // fmt.Printf("The results %+v\n", result) 143 | return result, nil 144 | } 145 | 146 | func getHostname() string { 147 | app := "hostname" 148 | arg0 := "-i" 149 | 150 | cmd := exec.Command(app, arg0) 151 | stdout, err := cmd.Output() 152 | 153 | if err != nil { 154 | fmt.Println(err.Error()) 155 | return "" 156 | } 157 | return strings.Trim(string(stdout), "\n") 158 | } 159 | 160 | // If the LGSM code doesn't match the gamedig code, map it here 161 | func getGamedigType(code string) string { 162 | shortCode := strings.Replace(code, "server", "", -1) 163 | 164 | // TODO: combare the lists and add any exceiptions that are missing: 165 | // https://github.com/GameServerManagers/LinuxGSM/blob/master/lgsm/data/serverlist.csv 166 | // https://github.com/gamedig/node-gamedig#supported 167 | 168 | switch shortCode { 169 | case "ac": 170 | return "assettocorsa" 171 | case "ahl": 172 | return "" 173 | case "ahl2": 174 | return "" 175 | case "ark": 176 | return "arkse" 177 | case "arma3": 178 | return "arma3" 179 | case "av": 180 | return "" 181 | case "bb": 182 | return "" 183 | case "bb2": 184 | return "" 185 | case "bd": 186 | return "" 187 | case "bf1942": 188 | return "bf1942" 189 | case "bfv": 190 | return "bfv" 191 | case "bmdm": 192 | return "" 193 | case "bo": 194 | return "" 195 | case "bs": 196 | return "" 197 | case "bt": 198 | return "" 199 | case "bt1944": 200 | return "bat1944" 201 | case "cc": 202 | return "" 203 | case "cmw": 204 | return "" 205 | case "cod": 206 | return "cod" 207 | case "cod2": 208 | return "cod2" 209 | case "cod4": 210 | return "cod4" 211 | case "codou": 212 | return "coduo" 213 | case "codwaw": 214 | return "codwaw" 215 | case "cs": 216 | return "cs16" 217 | case "cscz": 218 | return "cscz" 219 | case "csgo": 220 | return "csgo" 221 | case "css": 222 | return "css" 223 | case "dab": 224 | return "" 225 | case "dmc": 226 | return "" 227 | case "dod": 228 | return "dod" 229 | case "dods": 230 | return "dods" 231 | case "doi": 232 | return "doi" 233 | case "dst": 234 | return "" 235 | case "eco": 236 | return "" 237 | case "em": 238 | return "" 239 | case "etl": 240 | return "" 241 | case "fctr": 242 | return "" 243 | case "fof": 244 | return "" 245 | case "ges": 246 | return "ges" 247 | case "gmod": 248 | return "garrysmod" 249 | case "hl2dm": 250 | return "hl2dm" 251 | case "hldm": 252 | return "hldm" 253 | case "hldms": 254 | return "hldms" 255 | case "hw": 256 | return "hurtworld" 257 | case "ins": 258 | return "insurgency" 259 | case "inss": 260 | return "insurgencysandstorm" 261 | case "ios": 262 | return "" 263 | case "jc2": 264 | return "jc2mp" 265 | case "jc3": 266 | return "jc3mp" 267 | case "kf": 268 | return "killingfloor" 269 | case "kf2": 270 | return "killingfloor2" 271 | case "l4d": 272 | return "left4dead" 273 | case "l4d2": 274 | return "left4dead2" 275 | case "mc": 276 | return "minecraft" 277 | case "mcb": 278 | return "minecraftbe" 279 | case "mh": 280 | return "mordhau" 281 | case "mohaa": 282 | return "mohaa" 283 | case "mom": 284 | return "" 285 | case "mta": 286 | return "mtasa" 287 | case "mumble": 288 | return "mumble" 289 | case "nd": 290 | return "nucleardawn" 291 | case "nmrih": 292 | return "nmrih" 293 | case "ns": 294 | return "ns" 295 | case "ns2": 296 | return "ns2" 297 | case "ns2c": 298 | return "" 299 | case "onset": 300 | return "onset" 301 | case "opfor": 302 | return "" 303 | case "pc": 304 | return "" 305 | case "pstbs": 306 | return "" 307 | case "pvkii": 308 | return "" 309 | case "pz": 310 | return "" 311 | case "q2": 312 | return "quake2" 313 | case "q3": 314 | return "quake3" 315 | case "ql": 316 | return "quakelive" 317 | case "qw": 318 | return "quake1" 319 | case "ricochet": 320 | return "ricochet" 321 | case "ro": 322 | return "redorchestraost" 323 | case "rtcw": 324 | return "rtcw" 325 | case "rust": 326 | return "rust" 327 | case "rw": 328 | return "" 329 | case "samp": 330 | return "samp" 331 | case "sb": 332 | return "starbound" 333 | case "sbots": 334 | return "" 335 | case "sdtd": 336 | return "7d2d" 337 | case "sfc": 338 | return "" 339 | case "sof2": 340 | return "sof2" 341 | case "sol": 342 | return "soldat" 343 | case "squad": 344 | return "squad" 345 | case "ss3": 346 | return "" 347 | case "st": 348 | return "" 349 | case "sven": 350 | return "svencoop" 351 | case "terraria": 352 | return "terraria" 353 | // return "tshock" 354 | case "tf2": 355 | return "tf2" 356 | case "tfc": 357 | return "tfc" 358 | case "ts": 359 | return "" 360 | case "ts3": 361 | return "teamspeak3" 362 | case "tu": 363 | return "towerunite" 364 | case "tw": 365 | return "" 366 | case "unt": 367 | return "unturned" 368 | case "ut": 369 | return "ut" 370 | case "ut2k4": 371 | return "ut2004" 372 | case "ut3": 373 | return "ut3" 374 | case "ut99": 375 | return "" 376 | case "vs": 377 | return "" 378 | case "wet": 379 | return "wolfensteinet" 380 | case "wf": 381 | return "" 382 | case "wurm": 383 | return "" 384 | case "zmr": 385 | return "zombiemaster" 386 | case "zps": 387 | return "zps" 388 | default: 389 | fmt.Printf("Unexpected GameServer type (%s)\n", code) 390 | return "" 391 | } 392 | } 393 | 394 | func lgsmMonitor() (bool, string) { 395 | app := "./lgsm-gameserver" 396 | arg0 := "monitor" 397 | 398 | cmd := exec.Command(app, arg0) 399 | stdout, err := cmd.Output() 400 | 401 | if err != nil { 402 | return false, "Error querying" 403 | } 404 | 405 | if strings.Contains(string(stdout), "DELAY") { 406 | return false, "Starting" 407 | } 408 | 409 | if cmd.ProcessState.ExitCode() > 0 { 410 | return false, "Query returned error" 411 | } 412 | 413 | return true, "Ready" 414 | } 415 | -------------------------------------------------------------------------------- /src/version/version.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | var ( 4 | // Version will be overwritten automatically by the build 5 | Version = "0.0.0" 6 | // GitCommit will be overwritten automatically by the build 7 | GitCommit = "HEAD" 8 | // BuildDate will be overwritten automatically by the build 9 | BuildDate = "" 10 | ) 11 | --------------------------------------------------------------------------------