Files
panel/modules/minecraft-java/module.yaml
T
2026-07-14 23:37:25 -07:00

141 lines
5.6 KiB
YAML

# Minecraft Java Edition module.
#
# Uses the itzg/minecraft-server community image — widely deployed, actively
# maintained, designed for panel/automation use. All configuration is driven
# by env vars (unlike 7DTD, which fights us). Boots in ~60-90s on first run
# (downloads the server jar) and ~10-15s on subsequent runs.
#
# RCON uses Source RCON (binary protocol), which our agent doesn't yet have
# an adapter for — so this module declares the RCON port/password for future
# use but leaves the `rcon:` section out for now. Adding a source_rcon adapter
# is ~200 lines in agent/internal/rcon/ when we get to it.
id: minecraft-java
name: "Minecraft Java Edition"
version: 0.1.0
authors:
- panel contributors
supported_modes:
- docker
runtime:
docker:
image: itzg/minecraft-server:latest
# Host networking -- container shares the host net namespace, so
# any port the game/mod binds is directly on the LAN. AMP-like
# model. Multi-instance safety comes from env-driven per-instance
# ports (panel allocator + env: mapping on each ports entry).
network_mode: host
env:
EULA: "TRUE"
TYPE: "VANILLA"
VERSION: "LATEST"
MEMORY: "2G"
ENABLE_RCON: "true"
RCON_PASSWORD: "panel_rcon" # default only — a generated per-instance secret overrides this at create
MOTD: "Running on panel"
ONLINE_MODE: "TRUE"
DIFFICULTY: "normal"
VIEW_DISTANCE: "10"
# Pre-declared so the agent's resolve.go filter lets allocator-derived
# ports flow through to the container env. itzg honors both SERVER_PORT
# and RCON_PORT — defaults match the manifest port defaults below.
SERVER_PORT: "25565"
RCON_PORT: "25575"
volumes:
# /data holds the whole server including worlds, mods, configs.
# Named volume for speed; survives instance recreation unless operator
# explicitly removes it.
- { type: volume, name: "panel-$INSTANCE_ID-mc", container: "/data" }
ports:
- { name: game, proto: tcp, default: 25565, required: true, env: SERVER_PORT }
- { name: rcon, proto: tcp, default: 25575, internal: true, env: RCON_PORT }
# Per-instance generated RCON secret — overrides the env default below
# at create so every instance gets a unique password.
secrets:
- name: RCON_PASSWORD
description: "Minecraft RCON password — generated per instance"
generated: true
rcon:
adapter: source_rcon
host_port: rcon
auth: source_rcon_login
password_secret: RCON_PASSWORD
# Legacy fallback only (pre-generated-secret instances). New instances
# always get the generated RCON_PASSWORD secret above.
password_literal: "panel_rcon"
commands:
list: "list"
say: "say {msg}"
kick: "kick {player} {reason}"
stop: "stop"
save: "save-all"
state_sources:
- type: rcon
command: "list"
every: 60s
parse:
kind: regex
pattern: 'There are (?P<players>\d+) of a max of (?P<max>\d+) players online'
fields:
players_online: players
players_max: max
resources:
min_ram_mb: 2048
recommended_ram_mb: 4096
# /data has world saves mixed with downloadable libraries/, mods/ cache,
# and the server jar. Back up the player-state stuff; libraries +
# server jar regenerate from itzg's image on next start.
backup:
include:
- "world" # default world dir (overworld)
- "world_nether" # nether
- "world_the_end" # end
- "*.properties" # server.properties + others
- "*.json" # whitelist, ops, banned-players, banned-ips, usercache
- "plugins" # bukkit/spigot plugins (config + state inside each)
- "mods" # Forge/Fabric mod jars (mod configs in plugins/)
- "config" # mod config files
exclude:
- "logs" # rotates infinitely
- "crash-reports" # never useful in restore
- "libraries" # auto-downloaded by itzg
- "cache" # JVM/itzg fluff
- "tmp"
notes: "World data + plugins + mods + configs (~50-500 MB typical). Server jar + libraries fetched fresh by itzg on next start."
# itzg/minecraft-server handles install + version pinning via the VERSION env
# var on first container start — there's no SteamCMD / GitHub / direct flow
# the panel needs to drive.
#
# But: the manifest validator REQUIRES at least one update_provider. So we
# keep a placeholder. Without `auto_update_on_create: false` the agent kicks
# off this provider on first boot and direct.go errors out on the missing
# target_path — observed 2026-04-29. The combination here (placeholder +
# auto-update opt-out) is the right shape for any image-managed module.
auto_update_on_create: false
update_providers:
- id: image-managed
kind: direct
url: "https://hub.docker.com/r/itzg/minecraft-server"
target_path: ".panel-image-managed-marker" # never written; auto-update is suppressed above
events:
join:
pattern: "(?P<name>[A-Za-z0-9_]+) joined the game"
kind: join
leave:
pattern: "(?P<name>[A-Za-z0-9_]+) left the game"
kind: leave
chat:
pattern: "<(?P<name>[A-Za-z0-9_]+)> (?P<msg>.*)"
kind: chat
# --- Manifest-driven UI metadata (WI-07) --------------------------
# Consumed by the CONTROLLER/dashboard only (the controller loads its
# own ./modules copy at startup); the agent ignores these at runtime.
# ready_pattern is a JavaScript regex (slash-delimited when it needs
# flags) moved verbatim from the dashboard's READY_PATTERNS map.
ready_pattern: 'Done \([\d.]+s\)! For help'
appearance:
emoji: "🧱"
grad: "linear-gradient(135deg,#4c8b32,#84ce5c)"
art: "/game-art/minecraft-java.png"