1 Commits
main ... main

Author SHA1 Message Date
Liam A Edwards
e26ebd1ebf Update README.md 2026-01-01 17:57:54 +00:00
6 changed files with 133 additions and 227 deletions

View File

@@ -1,93 +1,48 @@
# #
name: Build SS14 Watchdog Server name: Create and publish a Docker image
# Configures this workflow to run every time a change is pushed to the branch called `release`.
on: on:
push: push:
branches: ['main'] branches: ['main']
workflow_dispatch:
# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.
env: env:
REGISTRY: git.wylab.me REGISTRY: ghcr.io
IMAGE_NAME: wylab/ws14-docker-linux-server IMAGE_NAME: ${{ github.repository }}
BUILDKIT_PROGRESS: plain
# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
jobs: jobs:
build-arm64: build-and-push-image:
runs-on: [self-hosted, macos-arm64] runs-on: ubuntu-latest
timeout-minutes: 60 # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
permissions: permissions:
contents: read contents: read
packages: write packages: write
#
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
# Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
- name: Set up Docker Buildx - name: Log in to the Container registry
uses: docker/setup-buildx-action@v3 uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
- name: Log in to the container registry
uses: docker/login-action@v3
with: with:
registry: ${{ env.REGISTRY }} registry: ${{ env.REGISTRY }}
username: ${{ secrets.REGISTRY_USERNAME || github.actor }} username: ${{ github.actor }}
password: ${{ secrets.REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
# This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
- name: Build and push Docker image (arm64) - name: Extract metadata (tags, labels) for Docker
uses: docker/build-push-action@v5 id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages.
# It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository.
# It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
- name: Build and push Docker image
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
with: with:
context: . context: .
provenance: false
platforms: linux/arm64
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-arm64
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-arm64,mode=max
push: true push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main-arm64 tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-amd64:
runs-on: [self-hosted, linux-amd64]
timeout-minutes: 60
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to the container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.REGISTRY_USERNAME || github.actor }}
password: ${{ secrets.REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}
- name: Build and push Docker image (amd64)
uses: docker/build-push-action@v5
with:
context: .
provenance: false
platforms: linux/amd64
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-amd64
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-amd64,mode=max
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main-amd64
create-manifest:
needs: [build-amd64, build-arm64]
runs-on: [self-hosted]
steps:
- name: Log in to the container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.REGISTRY_USERNAME || github.actor }}
password: ${{ secrets.REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}
- name: Create and push multi-arch manifest
run: |
docker manifest create --amend ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main-amd64 \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main-arm64
docker manifest push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main

View File

@@ -1,40 +1,24 @@
# syntax=docker/dockerfile:1.7
#
# SS14 Watchdog Docker Image (based on LiamAEdwards/SS14-Docker-Linux-Server)
# Downloads game server from CDN and builds SS14.Watchdog
#
# Build stage # Build stage
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
ARG TARGETPLATFORM
# Update and install necessary tools # Update and install necessary tools
RUN apt-get -y update && \ RUN apt-get -y update && \
apt-get -y install curl unzip wget git jq apt-get -y install curl unzip wget git jq
# Determine platform RID based on Docker TARGETPLATFORM # Download and extract SS14 server (latest version compatible with .NET 9)
RUN if [ "${TARGETPLATFORM:-linux/amd64}" = "linux/arm64" ]; then \ # Using manifest to get current server build
echo "linux-arm64" > /tmp/platform_rid; \ RUN SERVER_URL=$(curl -sL https://central.spacestation14.io/builds/wizards/manifest.json | \
else \ jq -r '.builds | to_entries | sort_by(.value.time) | last | .value.server."linux-x64".url') && \
echo "linux-x64" > /tmp/platform_rid; \
fi && \
echo "Building for platform: $(cat /tmp/platform_rid)"
# Download and extract SS14 server from WYLAB CDN
RUN PLATFORM_RID=$(cat /tmp/platform_rid) && \
SERVER_URL=$(curl -sL https://cdn.wylab.me/fork/wylab/manifest | \
jq -r ".builds | to_entries | sort_by(.value.time) | last | .value.server.\"${PLATFORM_RID}\".url") && \
echo "Downloading server from: $SERVER_URL" && \ echo "Downloading server from: $SERVER_URL" && \
wget -O SS14.Server.zip "$SERVER_URL" && \ wget -O SS14.Server_linux-x64.zip "$SERVER_URL" && \
unzip SS14.Server.zip -d /ss14-default/ unzip SS14.Server_linux-x64.zip -d /ss14-default/
# Download and build Watchdog # Download and build Watchdog
RUN PLATFORM_RID=$(cat /tmp/platform_rid) && \ RUN wget https://github.com/space-wizards/SS14.Watchdog/archive/refs/heads/master.zip -O Watchdog.zip && \
wget https://github.com/space-wizards/SS14.Watchdog/archive/refs/heads/master.zip -O Watchdog.zip && \
unzip Watchdog.zip -d Watchdog && \ unzip Watchdog.zip -d Watchdog && \
cd Watchdog/SS14.Watchdog-master && \ cd Watchdog/SS14* && \
dotnet publish SS14.Watchdog -c Release -r "${PLATFORM_RID}" --no-self-contained -o /ss14-default/publish dotnet publish -c Release -r linux-x64 --no-self-contained && \
cp -r SS14.Watchdog/bin/Release/net9.0/linux-x64/publish /ss14-default
# Server stage # Server stage
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS server FROM mcr.microsoft.com/dotnet/sdk:9.0 AS server
@@ -43,8 +27,7 @@ FROM mcr.microsoft.com/dotnet/sdk:9.0 AS server
COPY --from=build /ss14-default /ss14-default COPY --from=build /ss14-default /ss14-default
# Install necessary tools # Install necessary tools
RUN apt-get -y update && apt-get -y install unzip && \ RUN apt-get -y update && apt-get -y install unzip
rm -rf /var/lib/apt/lists/*
# Expose necessary ports # Expose necessary ports
EXPOSE 1212/tcp EXPOSE 1212/tcp
@@ -55,8 +38,8 @@ EXPOSE 8080/tcp
VOLUME [ "/ss14" ] VOLUME [ "/ss14" ]
# Add configurations # Add configurations
COPY appsettings.yml /ss14-default/publish/appsettings.yml ADD appsettings.yml /ss14-default/publish/appsettings.yml
COPY server_config.toml /ss14-default/publish/server_config.toml ADD server_config.toml /ss14-default/publish/server_config.toml
COPY start.sh /start.sh COPY start.sh /start.sh
RUN chmod +x /start.sh RUN chmod +x /start.sh

128
README.md
View File

@@ -1,4 +1,4 @@
<h1 align="center">SS14-Docker-Linux-Server 🚀</h1> <h1 align="center">SS14-Docker-Linux-Server </h1>
<p align="center"> <p align="center">
Containerized deployment of the <a href="https://spacestation14.io/">Space Station 14</a> server on Linux. Containerized deployment of the <a href="https://spacestation14.io/">Space Station 14</a> server on Linux.
@@ -13,110 +13,58 @@
### Overview ### Overview
This project is for those who prefer containerized solutions. It's based on the [official documentation](https://docs.spacestation14.com/en/general-development/setup/server-hosting-tutorial.html) but wraps the [wylab-station-14](https://git.wylab.me/wylab/wylab-station-14) fork in a Docker image that is built from source during the Docker build. This project is for those who prefer containerized solutions. It's based on the [official documentation](https://docs.spacestation14.com/en/general-development/setup/server-hosting-tutorial.html) but wrapped up in a Docker container for convenience.
### Building the Image ### Quick Start
1. **Clone this repository** 1. **Clone the repository**
```bash ```bash
git clone https://git.wylab.me/wylab/WS14-Docker-Linux-Server.git git clone https://github.com/LiamAEdwards/SS14-Docker-Linux-Server.git && cd SS14-Docker-Linux-Server
cd WS14-Docker-Linux-Server
``` ```
2. **Configure your server defaults** 2. **Configure Your Server**
Edit `appsettings.yml` and `server_config.toml` with the values you want baked into the image. These files will be copied into `/ss14-default/publish` on first run. Edit the `appsettings.yml` & `server_config.toml` to match your desired configuration.
3. **Build the Docker image** 3. **Run the Server**
Using Docker directly:
```bash ```bash
docker build \ docker run -d \
--build-arg SOURCE_REPO=https://git.wylab.me/wylab/wylab-station-14.git \ -p 1212:1212/tcp \
--build-arg SOURCE_REF=master \ -p 1212:1212/udp \
--build-arg TARGET_PLATFORM=auto \ -p 5000:5000/tcp \
-t git.wylab.me/wylab/WS14-Docker-Linux-Server:local . -p 5000:5000/udp \
-v /path/on/host:/ss14 \
ghcr.io/liamaedwards/ss14-docker-linux-server:main
``` ```
- `SOURCE_REPO` Git URL of the content repo to compile (defaults to the wylab fork). Or using Docker Compose:
- `SOURCE_REF` Branch, tag, or commit to check out (defaults to `master`).
- `TARGET_PLATFORM` Runtime identifier passed to the packaging tool. Use `auto` (default) to match the Docker target platform automatically, or override with `linux-x64`, `linux-arm64`, or `linux-arm` to force an architecture.
If you are building on one architecture and running on another (for example, building on x86 and deploying to an ARM board), build with an explicit platform to avoid `exec format error`: First, create a `docker-compose.yml` file:
```yaml
version: '3'
services:
ss14-server:
image: ghcr.io/liamaedwards/ss14-docker-linux-server:main
ports:
- "1212:1212/tcp"
- "1212:1212/udp"
- "5000:5000/tcp"
- "5000:5000/udp"
volumes:
- /path/on/host:/ss14
restart: always
```
Then, run with:
```bash ```bash
docker buildx build \ docker-compose up -d
--platform linux/arm64 \
--build-arg TARGET_PLATFORM=linux-arm64 \
-t git.wylab.me/wylab/WS14-Docker-Linux-Server:arm64 .
``` ```
The build container clones the selected ref, runs `RUN_THIS.py --quiet` to fetch submodules, and executes `dotnet run --project Content.Packaging server` to generate a release zip that is baked into the final layer.
### Running the Server
```bash
docker run -d \
-p 1212:1212/tcp \
-p 1212:1212/udp \
-p 5000:5000/tcp \
-p 5000:5000/udp \
-v /path/on/host:/ss14 \
--name wylab-ss14 \
git.wylab.me/wylab/WS14-Docker-Linux-Server:latest
```
On first start the container copies `/ss14-default` into your mounted volume (if empty) so you can edit configs or upload new builds persistently.
You can still wrap the container in Docker Compose if desired:
```yaml
version: '3.9'
services:
ss14-server:
image: git.wylab.me/wylab/WS14-Docker-Linux-Server:latest
ports:
- "1212:1212/tcp"
- "1212:1212/udp"
- "5000:5000/tcp"
- "5000:5000/udp"
volumes:
- /path/on/host:/ss14
restart: unless-stopped
```
### CI/CD
Two workflows keep this image up to date:
1. **`wylab-station-14/.github/workflows/publish.yml`**
- Triggered on pushes to `master`, manual dispatch, or nightly cron.
- Checks `https://cdn.wylab.me/fork/wylab/manifest` first; if the current commit already exists on the CDN it exits early.
- Uses `actions/cache` to persist `~/.nuget/packages` and `RobustToolbox/bin`, so repeated builds reuse restored packages/engine binaries when the inputs havent changed.
- Otherwise builds the server/client packages via `Content.Packaging`, uploads them via `Tools/publish_multi_request.py`, and fires a `repository_dispatch` event (`event_type: ss14-package-ready`) to this repo.
Required secrets in the wylab-station-14 repo:
`PUBLISH_TOKEN`, `DOCKER_TRIGGER_TOKEN`, and (if used) `SECRETS_PRIVATE_KEY`.
To send the dispatch, add `DOCKER_TRIGGER_TOKEN` (a PAT with repo access).
2. **`WS14-Docker-Linux-Server/.github/workflows/main.yml`**
- Triggered on pushes here, manual dispatch, or the `ss14-package-ready` event.
- Resolves the target wylab commit (uses the payload commit if provided).
- Logs into `git.wylab.me` and runs `docker manifest inspect` before building; if an image tagged with that commit already exists it skips the build.
- Otherwise builds the Docker image with `SOURCE_REF=<commit>` and pushes:
- `git.wylab.me/wylab/ws14-docker-linux-server:latest`
- `git.wylab.me/wylab/ws14-docker-linux-server:<docker repo commit>`
- `git.wylab.me/wylab/ws14-docker-linux-server:<wylab commit>`
Required secrets here: `REGISTRY_USERNAME` / `REGISTRY_PASSWORD` (credentials for `git.wylab.me`).
After the build finishes, Unraid (or any host) can pull:
```
git.wylab.me/wylab/ws14-docker-linux-server:latest
```
Use that string in Unraids “Repository” field and map `/ss14` to persistent storage.
--- ---

View File

@@ -25,25 +25,35 @@ Serilog:
AllowedHosts: "*" AllowedHosts: "*"
# Force Kestrel to bind to 0.0.0.0 (IPv4) instead of [::] (IPv6) # Force Kestrel to bind to 0.0.0.0 (IPv4) instead of [::] (IPv6)
# This fixes the Host header issue with http://[::]:8080
Urls: "http://0.0.0.0:8080" Urls: "http://0.0.0.0:8080"
# API URL your watchdog is accessible from. # API URL your watchdog is accessible from.
# This NEEDS to be reachable by the game server. # This NEEDS to be reachable by the game server.
# If you don't want the watchdog to be public,
# do `http://localhost:8080/` here.
#BaseUrl: https://your.domain.com/watchdog/
BaseUrl: http://localhost:8080/ BaseUrl: http://localhost:8080/
Servers: Servers:
Instances: Instances:
wylab: # ID (and directory) of your server.
Name: "WyLab Station 14" test:
# Name of the server
Name: "Test Instance"
# Token to control the instance remotely
ApiToken: "foobar" ApiToken: "foobar"
# Port OF THE GAME SERVER.
# This should match the HTTP status API
# or watchdog can't contact the server.
ApiPort: 1212 ApiPort: 1212
TimeoutSeconds: 120
# Override the baseUrl to use localhost # Override the baseUrl to use localhost instead of [::]
EnvironmentVariables: EnvironmentVariables:
ROBUST_CVAR_watchdog__baseUrl: "http://localhost:8080/" ROBUST_CVAR_watchdog__baseUrl: "http://localhost:8080/"
# Auto update from WyLab CDN # Auto update configuration. This can be
# omitted to skip auto updates.
UpdateType: "Manifest" UpdateType: "Manifest"
Updates: Updates:
ManifestUrl: "https://cdn.wylab.me/fork/wylab/manifest" ManifestUrl: "https://central.spacestation14.io/builds/wizards/manifest.json"

View File

@@ -34,24 +34,13 @@ bind = "*:1212"
[watchdog] [watchdog]
# Token must match ApiToken in appsettings.yml # Token must match ApiToken in appsettings.yml
token = "foobar" token = "foobar"
# Key must match the instance key in appsettings.yml # Key must match the instance key in appsettings.yml (e.g., "test")
key = "wylab" key = "test"
# BaseUrl must match BaseUrl in appsettings.yml # BaseUrl must match BaseUrl in appsettings.yml
baseUrl = "http://localhost:8080/" baseUrl = "http://localhost:8080/"
[game] [game]
hostname = "MyServer" hostname = "MyServer"
lobbyenabled = true
# Lobby wait in seconds before round start (default 150s)
lobbyduration = 180
defaultpreset = "secret"
fallbackpreset = "Traitor,Extended"
fallbackenabled = true
# Use built-in rotation list; edit this when you add custom pools.
map_pool = "DefaultMapPool"
map_rotation = true
# How many past rounds are remembered when picking the next map.
map_memory_depth = 8
[console] [console]
# If this is true, people connecting from this machine (loopback) # If this is true, people connecting from this machine (loopback)
@@ -74,18 +63,37 @@ server_url = ""
hub_urls = "https://central.spacestation14.io/hub/" hub_urls = "https://central.spacestation14.io/hub/"
[build] [build]
# Watchdog automatically provides build info from CDN manifest # *Absolutely all of these can be supplied using a "build.json" file*
# These are only used as fallback if watchdog doesn't provide them # For further information, see https://github.com/space-wizards/space-station-14/blob/master/Tools/gen_build_info.py
# The main reason you'd want to supply any of these manually is for a custom fork and if you have no tools.
[database] # Useful to override if the existing version is bad.
# Database engine: sqlite or postgres # See https://github.com/space-wizards/RobustToolbox/tags for version values, remove the 'v'.
engine = "postgres" # The value listed here is almost certainly wrong - it is ONLY a demonstration of format.
# PostgreSQL connection settings # engine_version = "0.7.6"
pg_host = "192.168.1.50"
pg_port = 5432 # This one is optional, the launcher will delete other ZIPs of the same fork to save space.
pg_database = "ss14" # fork_id = "abacusstation"
pg_username = "ss14"
pg_password = "hyphar-cAqtu6-wyzfet" # Automatically set if self-hosting client zip, but otherwise use this when updating client build.
# There is no required format, any change counts as a new version.
# version = "Example1"
# This is where the launcher will download the client ZIP from.
# If this isn't supplied, the server will check for a file called "Content.Client.zip",
# and will host it on the status server.
# If that isn't available, the server will attempt to find and use "../../Resources" and
# "../../bin/Content.Client" to automatically construct a client zip.
# It will then host this on the status server.
# Note that these paths do not work on "FULL_RELEASE" servers.
# FULL_RELEASE servers expect to be used with a specific "packaged" layout.
# As such, whatever script you're using to package them is expected to create the ZIP.
# download_url = "http://example.com/compass.zip"
# Build hash - this is a *capitalized* SHA256 hash of the client ZIP.
# Optional in any case and automatically set if hosting a client ZIP.
# This hash is an example only.
# build = "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855"
[auth] [auth]
# Authentication (accounts): # Authentication (accounts):

View File

@@ -1,10 +1,12 @@
#!/bin/bash #!/bin/bash
# Copy default files to volume on first run # Check if directory is empty
if [ ! "$(ls -A /ss14)" ]; then if [ ! "$(ls -A /ss14)" ]; then
cp -r /ss14-default/* /ss14/ # Copy the default files
cp -R /ss14-default/* /ss14/
fi fi
# Run watchdog # Start the original command
cd /ss14/publish/ cd /ss14/publish/
exec ./SS14.Watchdog "$@" ./SS14.Watchdog "$@"