From ab4f13a38556b9b6ba518e0d1d46ed21253373b9 Mon Sep 17 00:00:00 2001 From: alexion Date: Thu, 10 Sep 2026 10:20:56 -0400 Subject: [PATCH] docs: generalize SteamCMD server workflow --- docs/00 INBOX/ai/steamcmd servers.md | 84 ++++++++++++++++------------ 1 file changed, 49 insertions(+), 35 deletions(-) diff --git a/docs/00 INBOX/ai/steamcmd servers.md b/docs/00 INBOX/ai/steamcmd servers.md index 62d68d9..9b9e8da 100644 --- a/docs/00 INBOX/ai/steamcmd servers.md +++ b/docs/00 INBOX/ai/steamcmd servers.md @@ -1,12 +1,13 @@ # SteamCMD servers -This note records the workflow used to add the Valheim server. -The workflow starts with the lowest useful layer. -Each later step moves game knowledge into a narrower module. +This note describes the workflow for adding a server that SteamCMD installs. +Start with the generic runner on a host. +Then move game behavior into a game module. +Move deployment behavior into a guest module after validation. -## Stage 1: Run one server with `steamcmd` +## Stage 1: Run the server with `steamcmd` -Start by proving the generic SteamCMD runner works on a host. +Prove the generic SteamCMD runner before adding game-specific modules. Configure `modules.services.steamcmd` directly in the host file. ```nix @@ -41,33 +42,41 @@ modules.services.steamcmd = { }; ``` -This layer owns SteamCMD update behavior and systemd wiring. -It also owns directory setup for SteamCMD metadata, server files, and state. +Use real values for the target game. +The example shows Valheim because it was the first server added. + +This layer owns shared SteamCMD behavior: + +- service user +- directory creation +- SteamCMD install and update command +- systemd service wrapper +- firewall ports Do not pin the game server version in Nix. SteamCMD mutates the installed server files. ## Stage 2: Add a game service module -After direct SteamCMD deployment works, create a game module. +Create a game module after direct SteamCMD deployment works. Use `configs/nixos/modules/services/games/.nix`. -The game module owns game-specific details: +The game module owns game-specific behavior: - Steam app ID - server executable -- required command-line flags -- documented UDP ports -- private or public listing policy +- command-line flags +- documented ports +- default listing policy -The host keeps deployment-specific values: +The host owns deployment-specific values: -- host paths +- paths - server name - secret choice -- guest placement, when a guest exists +- network placement -For Valheim, the host config became: +A host can run the game module directly during validation: ```nix modules.services.games.valheim = { @@ -76,17 +85,17 @@ modules.services.games.valheim = { installDir = "/pikachu/data/servers/valheim/main"; stateDir = "/pikachu/media/games/servers/valheim/main"; serverName = "main"; - password = "foobarbaz"; + passwordFile = "/run/secrets/services/game-servers/password"; }; ``` -The Valheim module translated that into `modules.services.steamcmd`. -It generated the Valheim argument list and UDP ports. +The game module translates its options into `modules.services.steamcmd`. +It passes the app ID, executable, arguments, and ports to the runner. ## Stage 3: Add UDP ingress -Valheim uses UDP. -HTTP virtual hosts do not route Valheim traffic. +Many game servers use UDP. +HTTP virtual hosts do not route raw UDP traffic. Extend `registry.route` with UDP ports: @@ -102,11 +111,11 @@ registry.route.pikachu.valheim = { Keep `domain` mandatory. Nix does not own public DNS today. -The route domain still identifies the public route. +The route domain identifies the public route. A future LAN DNS module can also consume it. The reverse-proxy module joins `registry.route` with `registry.address`. -It renders nginx `stream` entries for UDP ports. +It renders nginx `stream` entries for UDP routes. ```nginx server { @@ -134,15 +143,19 @@ Configure router forwarding outside Nix: 2457/udp -> reverse-proxy guest:2457 ``` +Use the game documentation to choose the port list. +For Valheim, the official guide says it uses the configured port and port plus one. + ## Stage 4: Move the server into a guest -After the host-level game module works, add a guest module. +Add a guest module after host-level validation succeeds. Use `configs/nixos/guests/.nix`. The guest module wraps `modules.services.games.`. -It also maps host paths into guest paths. +It maps host paths into guest paths. +It also connects guest address and route options to the registry. -For Valheim, the host config became: +The host config then owns deployment wiring: ```nix guests.valheim = { @@ -186,8 +199,8 @@ registry.route.pikachu.valheim = config.guests.valheim.reverseProxy.route; ## Secrets -Use SOPS for the game server password. -Use one shared secret for game servers: +Use SOPS for game server passwords. +Use one shared secret when servers can share a password: ```yaml services: @@ -203,7 +216,7 @@ passwordSecret = "services/game-servers/password"; The host decrypts the secret. The guest module bind-mounts the decrypted file into the guest. -The Valheim module reads the password file at runtime. +The game module reads the password file at runtime. Edit shared secrets with the host key: @@ -232,7 +245,7 @@ Check the host secret: sudo test -s /run/secrets/services/game-servers/password && echo secret-ok ``` -Check the Valheim guest: +Check the guest: ```sh sudo systemctl status container@valheim.service --no-pager @@ -244,21 +257,22 @@ Check the guest secret: sudo nixos-container run valheim -- test -s /run/secrets/services/game-servers/password ``` -Check the Valheim service: +Check the game service: ```sh sudo nixos-container run valheim -- systemctl status valheim.service --no-pager sudo nixos-container run valheim -- journalctl -u valheim.service -n 200 --no-pager ``` -Wait for these log lines: +Wait for the game-specific ready log. +For Valheim, wait for these lines: ```text Game server connected Opened Steam server ``` -Check Valheim UDP listeners: +Check game UDP listeners: ```sh sudo nixos-container run valheim -- ss -lunp | grep -E '2456|2457|valheim' @@ -284,8 +298,8 @@ Test direct guest connectivity when ingress fails: ## Operational notes -A first Valheim start can spend time generating a world. -The service accepts connections after `Opened Steam server` appears. +A first server start can spend time preparing state. +For Valheim, first start can generate a world. SteamCMD can leave old ownership on migrated server files. The SteamCMD module uses recursive tmpfiles repair for its managed directories.