Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
*
!entrypoint.sh
!healthcheck/
!healthcheck/query.py
49 changes: 49 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Copy this file to .env (untracked - never commit real secrets) and edit
# the values below. See README.md and docs/operations.md for details.

# --- Identity / permissions -------------------------------------------------
# UID/GID the game server runs as inside the container. Must be able to
# write to the runtime/ directories on the host. Defaults match the image's
# built-in "abiotic" user.
PUID=10000
PGID=10000

# --- Update behavior ---------------------------------------------------------
STEAM_APP_ID=2857200
STEAM_BRANCH=public
AUTO_UPDATE=true
VALIDATE_ON_START=true
STEAMCMD_RETRIES=5

# --- Server configuration -----------------------------------------------------
SERVER_NAME=Abiotic Factor Dedicated Server
# REQUIRED. There is no safe default - the container refuses to start if
# this is left as "replace-me". Set a real password, or set it to an empty
# value (SERVER_PASSWORD=) for an intentionally open server.
SERVER_PASSWORD=replace-me
# Optional. Grants in-game admin whitelisting when set. Leave empty to disable.
ADMIN_PASSWORD=
GAME_PORT=7777
QUERY_PORT=27015
MAX_SERVER_PLAYERS=6
WORLD_SAVE_NAME=Cascade
USE_PERF_THREADS=true
DISABLE_ASYNC_LOADING_THREAD=false
# Extra raw launch arguments appended verbatim, e.g.:
# ADDITIONAL_ARGS=-SandboxIniPath=Config/WindowsServer/Server1Sandbox.ini
ADDITIONAL_ARGS=

# --- Shutdown ------------------------------------------------------------------
# Seconds to wait for the game process to exit after SIGTERM before SIGKILL.
SHUTDOWN_TIMEOUT=60

# --- Backups ---------------------------------------------------------------
BACKUP_RETENTION=14

# --- Misc ------------------------------------------------------------------
TZ=America/Chicago

# --- Deployment (used by docker-compose.yml and systemd units, not the
# container itself) ----------------------------------------------------------
RUNTIME_DIR=/srv/abiotic-factor/runtime
IMAGE_REVISION=dev
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
data/
gamefiles/
.env
runtime/
*.log
90 changes: 80 additions & 10 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,17 +1,87 @@
# syntax=docker/dockerfile:1
#
# Abiotic Factor dedicated server (App ID 2857200) under Wine.
#
# The dedicated server is a Windows-only Steam Tool (confirmed via
# `steamcmd +app_info_print 2857200`: oslist=windows). There is no Linux
# build, so Wine is required. See docs/upstream-review.md for how the
# executable path and launch parameters below were verified against the
# current Steam depot rather than assumed from the old entrypoint.
FROM ubuntu:22.04

ARG ABIOTIC_UID=10000
ARG ABIOTIC_GID=10000
ARG IMAGE_REVISION=dev

LABEL org.opencontainers.image.title="abiotic-factor-server" \
org.opencontainers.image.revision="${IMAGE_REVISION}" \
org.opencontainers.image.source="https://github.com/johnseth97/abiotic-factor-linux-docker"

ENV DEBIAN_FRONTEND=noninteractive \
PATH="/usr/games:${PATH}" \
LANG=en_US.UTF-8 \
LANGUAGE=en_US:en \
LC_ALL=en_US.UTF-8 \
WINEARCH=win64 \
WINEDEBUG=-all

# NOTE: we deliberately do NOT use Ubuntu's `steamcmd` apt package. It ships
# a years-stale bootstrap shim (steamcmd:i386 0~20180105-4 on 22.04) that, in
# testing on this host, failed outright with "Steamcmd needs to be online to
# update" even with working network access. We fetch the current, officially
# distributed steamcmd tarball from Valve instead - the same thing every
# well-regarded SteamCMD container does. See docs/upstream-review.md.
#
# locales fixes the setlocale warning from PR #25
# (https://github.com/Pleut/abiotic-factor-linux-docker/pull/25); gosu drops
# privileges from root to the unprivileged runtime user; rsync backs the
# staged-update promotion in entrypoint.sh; python3 backs the health check.
RUN dpkg --add-architecture i386 && \
apt-get update && \
echo steam steam/question select "I AGREE" | debconf-set-selections && \
echo steam steam/license note '' | debconf-set-selections && \
DEBIAN_FRONTEND=noninteractive apt-get install -y wine64 steamcmd && \
apt-get clean autoclean && \
apt-get autoremove -y && \
rm -rf /var/lib/apt/lists/*
apt-get install -y --no-install-recommends \
wine64 \
curl \
ca-certificates \
lib32gcc-s1 \
locales \
gosu \
rsync \
python3 \
&& mkdir -p /opt/steamcmd \
&& curl -sqL "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz" \
| tar zxf - -C /opt/steamcmd \
&& ln -s /opt/steamcmd/steamcmd.sh /opt/steamcmd/steamcmd \
# Valve's tarball ships steamcmd.sh owned by an arbitrary uid (5020) with
# no execute bit for group/other, so the unprivileged runtime user can't
# run it as-is. Confirmed by testing - fails with "Permission denied".
&& chmod -R a+rX /opt/steamcmd \
&& locale-gen en_US.UTF-8 \
&& update-locale LANG=en_US.UTF-8 \
&& apt-get clean autoclean \
&& apt-get autoremove -y \
&& rm -rf /var/lib/apt/lists/*

ENV PATH="/opt/steamcmd:${PATH}"

# Dedicated unprivileged user. UID/GID are overridden at container start
# (via usermod/groupmod in entrypoint.sh) to match PUID/PGID so bind-mounted
# host directories are writable without running the game as root.
RUN groupadd --gid "${ABIOTIC_GID}" abiotic && \
useradd --uid "${ABIOTIC_UID}" --gid "${ABIOTIC_GID}" \
--create-home --home-dir /home/abiotic --shell /usr/sbin/nologin abiotic && \
mkdir -p /data/gamefiles /data/logs /home/abiotic/.wine && \
chown -R abiotic:abiotic /data /home/abiotic

ENV PATH="$PATH:/usr/games"
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
COPY healthcheck/query.py /usr/local/bin/abiotic-healthcheck.py
RUN chmod 0755 /usr/local/bin/entrypoint.sh /usr/local/bin/abiotic-healthcheck.py

WORKDIR /steamcmd
WORKDIR /data

COPY ./entrypoint.sh /entrypoint.sh
ENTRYPOINT ["bash", "/entrypoint.sh"]
# Runs as root initially so the entrypoint can reconcile PUID/PGID and fix
# bind-mount ownership; entrypoint.sh drops to the unprivileged user via
# gosu before running steamcmd or wine. Zombie reaping/PID 1 signal handling
# is provided by Compose's `init: true` (Docker's own tini-equivalent) - a
# second init baked in here would just become an unnecessary PID 2 hop, so
# we don't duplicate it.
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
Loading