# Valheim — panel-native dedicated server module. # # Native Linux binary from SteamCMD app 896660. No RCON natively — the # server reads admin commands from stdin and prints to stdout, which is # a "STDIO adapter" thing we haven't shipped yet. So v1 runs without an # RCON/Players tab, same story as Empyrion. # # Reference: https://github.com/CubeCoders/AMPTemplates (Valheim.kvp) id: valheim name: "Valheim" version: 0.1.0 authors: - panel contributors supported_modes: - docker runtime: docker: image: panel-valheim: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 browseable_root: /game-saves browseable_roots: - name: "Saves & Configs" path: /game-saves hint: "Worlds + adminlist.txt + banlist.txt (via $HOME/.config/unity3d)" - name: "Game Files" path: /game hint: "Binaries, plugins — drop BepInEx/Jotunn here" env: SERVER_NAME: "panel Valheim" SERVER_WORLD: "Dedicated" SERVER_PASSWORD: "secret12" # Valheim requires ≥5 chars + not part of name/world SERVER_PUBLIC: "1" # 1 = listed, 0 = unlisted # Optional curated knobs (surfaced as Settings fields in gamehost). Must # be pre-declared here so the agent's config_values override is honoured # by ResolveDocker (it only passes through keys already in this block). SERVER_CROSSPLAY: "0" # 1 = enable PlayFab crossplay SERVER_SAVEINTERVAL: "1800" # world autosave interval, seconds SERVER_PRESET: "" # normal|casual|easy|hard|hardcore|immersive|hammer SERVER_MODIFIERS: "" # "combat hard deathpenalty casual ..." pairs VALHEIM_MODS_ENABLED: "0" # 1 = inject BepInEx/Doorstop at launch (mods installed) VALHEIM_PLUS_ENABLED: "0" # 1 = ValheimPlus is the active mod (drives the V+ settings UI) # Port env vars MUST be pre-declared here (with the manifest default) so # the agent's per-port `env:` injection is allowed to override them at # create time. ResolveDocker only honours config_values for keys that # already exist in this static env block — otherwise the injected # PORT_GAME is silently dropped and the entrypoint falls back to 2456. PORT_GAME: "2456" PORT_GAMEA: "2457" PORT_QUERY: "2458" volumes: - { type: volume, name: "panel-$INSTANCE_ID-saves", container: "/game-saves" } - { type: volume, name: "panel-$INSTANCE_ID-game", container: "/game" } - { target: "$DATA_PATH/logs", container: "/game-saves/logs" } # The panel allocator assigns a per-instance host port for each entry and, # thanks to the `env:` mapping, injects it into the container so the entrypoint # binds the ALLOCATED port instead of the hardcoded default. Without this the # game binds 2456/2457 regardless of allocation and every public forward (which # targets the allocated port) misses — server unreachable / not in the browser. # Valheim actually opens and +1 for play and +1 for the # Steam query/browser; we pass PORT_GAME and let the binary take port+1. The # allocator hands out contiguous ports so gameA/query line up. ports: - { name: game, proto: udp, default: 2456, required: true, env: PORT_GAME } - { name: gameA, proto: udp, default: 2457, required: true, env: PORT_GAMEA } - { name: query, proto: udp, default: 2458, required: true, env: PORT_QUERY } resources: min_ram_mb: 2048 recommended_ram_mb: 4096 rcon: # Valheim has no network RCON; admin commands go straight to the server's # stdin console. The stdio adapter auto-enables OpenStdin on the container. adapter: stdio commands: save: "save" broadcast: "broadcast \"{msg}\"" kick: "kick {player}" ban: "ban {player}" shutdown: "shutdown" # Log-derived player events. Regexes converted from CubeCoders' # AMPTemplates (valheim.kvp) — .NET (?) syntax -> Go (?P). # Sourced-from-template; not yet exercised against a live client. events: join: pattern: 'Got character ZDOID from (?P.+?) : (?P-?\d+):\d+' kind: join leave: pattern: 'Destroying abandoned non persistent zdo -?\d+:\d+ owner (?P-?\d+)$' kind: leave update_providers: - id: stable kind: steamcmd app_id: "896660" install_path: /game # --- 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: '/Game server connected|Dedicated server started/i' appearance: emoji: "⚔️" grad: "linear-gradient(135deg,#3b5998,#8da5d4)" art: "/game-art/valheim.jpg" steam: "892970"