From 889a1232316589ec55dc24062bbf8c564c1c06e7 Mon Sep 17 00:00:00 2001 From: alexion Date: Wed, 9 Sep 2026 20:24:50 -0400 Subject: [PATCH] docs: document SteamCMD server pattern --- docs/00 INBOX/ai/steamcmd-server.md | 226 ++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 docs/00 INBOX/ai/steamcmd-server.md diff --git a/docs/00 INBOX/ai/steamcmd-server.md b/docs/00 INBOX/ai/steamcmd-server.md new file mode 100644 index 0000000..6893d43 --- /dev/null +++ b/docs/00 INBOX/ai/steamcmd-server.md @@ -0,0 +1,226 @@ +# SteamCMD server notes + +These notes describe the emerging pattern for SteamCMD-based game servers in this monorepo. +They come from the Valheim prototype on Pikachu. + +## Goal + +Use NixOS to manage server operations, not game content. + +Nix owns service wiring, launch flags, ports, timers, users, and mounts. +SteamCMD owns downloaded server files. +The game owns world data, generated config, saves, and modded files. + +## Layering + +Use three layers for SteamCMD-based servers. + +```text +configs/nixos/modules/services/steamcmd.nix +configs/nixos/modules/services/.nix +configs/nixos/guests/.nix +``` + +### `modules.services.steamcmd` + +This module provides the generic SteamCMD machinery. + +It runs on any NixOS system. +That system can be a physical host or a guest. + +It owns: + +- the `steamcmd` service user, +- the shared SteamCMD data directory, +- per-instance Steam app updates, +- per-instance game service units, +- optional hard restart timers, +- firewall openings for declared ports. + +It does not know Valheim, PalWorld, or Project Zomboid semantics. +Game modules translate game-specific settings into SteamCMD instances. + +### `modules.services.` + +A game service module wraps `modules.services.steamcmd`. + +For Valheim, this layer owns: + +- Steam app id `896660`, +- the Valheim runtime app id, +- launch flags such as `-name`, `-world`, and `-port`, +- the expected UDP port range, +- the mapping from instance options to a SteamCMD instance. + +This layer exposes operational config only. +It avoids owning mutable gameplay files unless the game exposes stable launch flags. + +### `guests.` + +A guest module turns a game service into a deployable guest. + +It owns host-facing concerns: + +- VLAN placement, +- guest address registry entry, +- host paths and bind mounts, +- resource limits, +- secret file mounts, +- game-family instance declarations. + +Do not add a reusable `guests.steamcmd` base guest. +The guest auto-loader turns `configs/nixos/guests/steamcmd.nix` into a concrete guest. +A specialized guest cannot use it as a base without creating another container. + +## Instance model + +Use one guest per game family. +Use named instances inside that guest. + +For example, `guests.palworld` can contain `instances.current` and `instances.old`. +Each instance has its own ports and paths. +The host config must avoid clashes. + +For Valheim, the prototype uses `instances.foo`. +The instance name is the operational identity. +The world name defaults to the instance name. + +Keep these names separate in the module interface: + +```text +instance name -> unit names and paths +worldName -> game launch flag +``` + +This permits a test instance to load a copied world later. + +## Storage layout + +Use three storage roots. + +```text +/data/steamcmd +/data/servers// +/media/games/servers// +``` + +### `/data/steamcmd` + +Store SteamCMD data and cache here. + +This directory contains mutable Steam metadata and download state. +Do not treat it as durable game state. + +### `/data/servers//` + +Store the installed dedicated server files here. + +SteamCMD writes these files. +Mods can also mutate this tree. +For that reason, use per-instance app installs. +Do not share one app install between modded or historical instances. + +### `/media/games/servers//` + +Store world data, saves, generated config, and durable game state here. + +Backups are out of scope for the first prototype. +This path gives a stable backup boundary later. + +## Updates + +Do not pin game server versions in Nix. +Steam controls the server build. + +Nix controls when updates run. +The prototype updates on service start. +A daily hard restart timer can pull updates during a maintenance window. + +The generic SteamCMD layer supports a restart timer. +The default timer command restarts the instance service. +Game modules or host config can override that command later. + +Avoid generic player-warning or player-count logic in the SteamCMD layer. +Those flows are game-specific. + +## Secrets + +Use sops-backed environment files for durable configuration. +Mount them read-only into the guest. + +The Valheim prototype temporarily supports a hardcoded password. +That password leaks into the Nix store and process arguments. +Use it only for throwaway tests. + +The target model is: + +```text +host sops secret -> read-only guest mount -> systemd EnvironmentFile +``` + +For Valheim, the environment file contains: + +```sh +SERVER_PASSWORD=example-password +``` + +## Networking + +Open ports in the guest firewall from the game module. + +Valheim uses the base UDP port through `basePort + 2`. +The default base port is `2456`, so open UDP `2456-2458`. + +For public access, forward those UDP ports to the guest address. +DNS is optional for the first deployment. + +Use `machinectl status ` to confirm the current DHCP address. +Do not trust a guessed address. +Add a DHCP reservation before depending on a committed address. + +## Valheim prototype + +The prototype proved these facts: + +- Valheim runs inside a NixOS guest on Pikachu. +- SteamCMD installs the dedicated server files at service start. +- `steam-run` runs the mutable Valheim server binary. +- LAN clients can connect to the guest address and UDP port. +- The storage split works for SteamCMD data, server files, and world data. + +The prototype used: + +```text +guest: valheim +instance: foo +password: foobarbaz +actual DHCP address during test: 10.23.20.197 +``` + +The hardcoded password and test instance name need cleanup before a final PR. + +## Bring-up checklist + +1. Add or update `modules.services.`. +2. Map game-specific options to `modules.services.steamcmd.instances`. +3. Add or update `guests.`. +4. Mount `/data/steamcmd` into the guest. +5. Mount `/data/servers//` into the guest. +6. Mount `/media/games/servers//` into the guest. +7. Add a sops environment file for secrets. +8. Open the required game ports in the guest firewall. +9. Enable the guest on the target host. +10. Deploy with `deploy-to `. +11. Check `container@.service` on the host. +12. Enter the guest with `nixos-container root-login `. +13. Check the game service with `systemctl status`. +14. Follow logs with `journalctl -u -f`. +15. Connect from LAN before adding public forwarding. + +## Open cleanup items + +- Replace hardcoded prototype passwords with sops environment files. +- Choose durable instance names before long-term use. +- Add DHCP reservations for game guests. +- Add backup policy for world and modded server data. +- Decide whether server install trees need backup for modded servers.