- Shell 86.1%
- Dockerfile 13.9%
|
All checks were successful
Build and Push — vintage-story / docker (push) Successful in 5s
|
||
|---|---|---|
| .forgejo/workflows | ||
| docs | ||
| garrysmod | ||
| hytale | ||
| minecraft | ||
| vintage-story | ||
| README.md | ||
ShardHost — Game Server Docker Images
Docker images designed to work with the ShardHost game hosting platform
(shard-rs + server-rs). Each image acts as a self-contained game server runner that:
- Downloads and installs the game server on first start
- Stores all persistent data in
/data(mounted byshard-rs) - Accepts configuration via environment variables
- Keeps stdin open for console command input
- Handles graceful shutdown via
SIGTERM
Architecture
shard-rs ─────────────────────────────────────────────────────────────────────
│
│ mounts {data_dir}/{container_name} → /data (inside container)
│ SFTP chroot also rooted at the same /data directory
│
└─► Docker container
├── /data/ ← persistent volume (game files, saves, logs, config)
└── / ← read-only image layer (binaries, entrypoint)
| Concern | How it is handled |
|---|---|
| Persistent data | shard-rs mounts {data_dir}/{container_name} as /data inside the container. All game files, saves, and logs live here. |
| SFTP access | Users are chrooted to the same /data directory — they see exactly what the game server sees. |
| Resource limits | CPU, memory, and disk quotas are enforced at the Docker container level by shard-rs. |
| Container security | no-new-privileges flag set; capabilities dropped to the minimum required (CHOWN, NET_BIND_SERVICE, KILL). Game server processes run as uid 1000 (gameserver). |
Available Images
| Image | Game | Default Port | Base Image |
|---|---|---|---|
git.plochit.pl/shardhost.eu/minecraft |
Minecraft Java Edition | 25565 TCP/UDP | eclipse-temurin:21-jre-alpine |
git.plochit.pl/shardhost.eu/vintage-story |
Vintage Story | 42420 TCP/UDP | dotnet/runtime:8.0-bookworm-slim |
git.plochit.pl/shardhost.eu/garrysmod |
Garry's Mod | 27015 TCP/UDP | debian:bookworm-slim |
git.plochit.pl/shardhost.eu/hytale |
Hytale (placeholder) | 25565 TCP | alpine:3.20 |
Configuration in server-rs
Each game requires a RuntimeConfig row in the database. The docker_image field identifies
which image to run; env_vars (JSON object) are injected as container environment variables.
Minecraft
INSERT INTO runtime_configs (name, docker_image, env_vars, internal_port, startup_command, description)
VALUES (
'Minecraft Java (Paper)',
'git.plochit.pl/shardhost.eu/minecraft:latest',
'{"MC_TYPE":"paper","MC_VERSION":"latest","EULA":"true","MEMORY":"max","ONLINE_MODE":"true"}',
25565,
'',
'Minecraft Java Edition — PaperMC'
);
Vintage Story
INSERT INTO runtime_configs (name, docker_image, env_vars, internal_port, startup_command, description)
VALUES (
'Vintage Story',
'git.plochit.pl/shardhost.eu/vintage-story:latest',
'{"VS_VERSION":"latest","ADVERTISE":"false"}',
42420,
'',
'Vintage Story dedicated server'
);
Garry's Mod
INSERT INTO runtime_configs (name, docker_image, env_vars, internal_port, startup_command, description)
VALUES (
'Garry''s Mod',
'git.plochit.pl/shardhost.eu/garrysmod:latest',
'{"GM_GAMEMODE":"sandbox","GM_MAP":"gm_flatgrass","TICKRATE":"66"}',
27015,
'',
'Garry''s Mod dedicated server (SteamCMD)'
);
Environment Variables
Minecraft (git.plochit.pl/shardhost.eu/minecraft)
| Variable | Default | Description |
|---|---|---|
MC_VERSION |
latest |
Server version (e.g. 1.21.4) |
MC_TYPE |
paper |
Server type: paper, vanilla, purpur |
SERVER_PORT |
25565 |
Game port (TCP+UDP) |
EULA |
false |
Must be true to start — accepts the Mojang EULA |
MEMORY |
1024 |
JVM heap in MB (recommended: ~85% of container memory limit) |
MAX_PLAYERS |
20 |
Maximum simultaneous players |
DIFFICULTY |
normal |
peaceful / easy / normal / hard |
GAMEMODE |
survival |
survival / creative / adventure / spectator |
MOTD |
A Minecraft Server |
Description shown in the server list |
ONLINE_MODE |
true |
Require premium (Mojang/Microsoft) authentication |
EXTRA_FLAGS |
(empty) | Additional JVM arguments appended to the launch command |
Vintage Story (git.plochit.pl/shardhost.eu/vintage-story)
| Variable | Default | Description |
|---|---|---|
VS_VERSION |
latest |
Server version (e.g. 1.20.0) |
SERVER_PORT |
42420 |
Game port (TCP+UDP) |
MAX_CLIENTS |
16 |
Maximum simultaneous players |
SERVER_NAME |
Vintage Story Server |
Server display name |
WORLD_NAME |
default |
World / save name |
SAVE_BACKUPS |
3 |
Number of rolling backup saves to keep |
ADVERTISE |
false |
List the server on the public server list |
MOTD |
(empty) | Server description shown on join |
Garry's Mod (git.plochit.pl/shardhost.eu/garrysmod)
| Variable | Default | Description |
|---|---|---|
SERVER_PORT |
27015 |
Game port (TCP+UDP) |
GM_MAP |
gm_flatgrass |
Starting map |
GM_GAMEMODE |
sandbox |
Default gamemode |
GM_MAXPLAYERS |
16 |
Maximum simultaneous players |
STEAM_TOKEN |
(empty) | GSL token — server is LAN-only without one |
SERVER_NAME |
Garry's Mod Server |
Server hostname (visible in browser) |
SERVER_PASS |
(empty) | Join password (empty = no password) |
TICKRATE |
66 |
Server tickrate |
EXTRA_ARGS |
(empty) | Additional srcds arguments |
Data Directory Layout
The /data volume is what users see when they connect over SFTP. Its structure
varies per game:
/data/ ← SFTP root (chrooted here)
│
├── [minecraft]
│ ├── server.jar ← Downloaded server binary
│ ├── eula.txt
│ ├── server.properties ← Edit to customise beyond env vars
│ ├── world/ ← World data
│ ├── plugins/ ← Paper/Purpur plugins
│ └── logs/
│
├── [vintage-story]
│ ├── server/ ← VS server binary (auto-managed, do not edit)
│ ├── serverconfig.json ← Regenerated from env vars on each start
│ └── Data/
│ ├── Saves/
│ ├── Logs/
│ └── ModConfig/
│
└── [garrysmod]
└── server/ ← Full game install (auto-updated via SteamCMD)
└── garrysmod/
├── cfg/
│ └── server.cfg ← Regenerated from env vars on each start
├── addons/ ← Install Workshop add-ons here
└── maps/
Building
# Build all images
docker build -t git.plochit.pl/shardhost.eu/minecraft:latest ./minecraft
docker build -t git.plochit.pl/shardhost.eu/vintage-story:latest ./vintage-story
docker build -t git.plochit.pl/shardhost.eu/garrysmod:latest ./garrysmod
docker build -t git.plochit.pl/shardhost.eu/hytale:latest ./hytale
Notes
-
Garry's Mod / SteamCMD — the game server is updated on every container start. Keep
/data/server/on a persistent volume to avoid re-downloading the full game (~8 GB) each time. -
Minecraft
server.properties— env vars update known keys on each start, but the file is never recreated from scratch. Custom properties added manually are preserved across restarts. -
Vintage Story
serverconfig.json— this file is fully regenerated from env vars on every start. To persist custom settings, use theData/subdirectory for mods and configuration that VS reads separately. -
User security — all images run the game server process as uid 1000 (
gameserver). The container itself runs withno-new-privilegesand a reduced Linux capability set. -
Hytale placeholder — the
git.plochit.pl/shardhost.eu/hytaleimage keeps the container alive and records a log entry at/data/logs/shardhost.log. It will be replaced with a real implementation once the game releases.