From 12e613fea4022893e5f563d099d675c30bc1938d Mon Sep 17 00:00:00 2001 From: alexion Date: Wed, 9 Sep 2026 21:51:20 -0400 Subject: [PATCH] refactor(nixos): simplify SteamCMD server options --- configs/nixos/hosts/pikachu/default.nix | 43 +++++----- configs/nixos/modules/services/steamcmd.nix | 94 ++++++++++----------- 2 files changed, 65 insertions(+), 72 deletions(-) diff --git a/configs/nixos/hosts/pikachu/default.nix b/configs/nixos/hosts/pikachu/default.nix index b788730..66e677b 100644 --- a/configs/nixos/hosts/pikachu/default.nix +++ b/configs/nixos/hosts/pikachu/default.nix @@ -68,33 +68,28 @@ modules.services.steamcmd = { enable = true; - dataDir = "/pikachu/data/steamcmd"; + steamDir = "/pikachu/data/steamcmd"; serviceName = "valheim"; appId = 896660; + runtimeAppId = 892970; installDir = "/pikachu/data/servers/valheim/main"; - workingDirectory = "/pikachu/data/servers/valheim/main"; - group = "storage"; - dataDirs = [ "/pikachu/media/games/servers/valheim/main" ]; - packages = [ pkgs.steam-run ]; - environment = { - SteamAppId = "892970"; - SERVER_PASSWORD = "foobarbaz"; - }; - command = [ - "${pkgs.bash}/bin/bash" - "-c" - '' - export LD_LIBRARY_PATH="$PWD/linux64:$LD_LIBRARY_PATH" - exec steam-run ./valheim_server.x86_64 \ - -nographics \ - -batchmode \ - -name main \ - -port 2456 \ - -world main \ - -savedir /pikachu/media/games/servers/valheim/main \ - -password "$SERVER_PASSWORD" \ - -public 0 - '' + stateDir = "/pikachu/media/games/servers/valheim/main"; + executable = "./valheim_server.x86_64"; + arguments = [ + "-nographics" + "-batchmode" + "-name" + "main" + "-port" + "2456" + "-world" + "main" + "-savedir" + "/pikachu/media/games/servers/valheim/main" + "-password" + "foobarbaz" + "-public" + "0" ]; udpPorts = [ 2456 diff --git a/configs/nixos/modules/services/steamcmd.nix b/configs/nixos/modules/services/steamcmd.nix index 21ce947..1af7a57 100644 --- a/configs/nixos/modules/services/steamcmd.nix +++ b/configs/nixos/modules/services/steamcmd.nix @@ -7,6 +7,9 @@ let cfg = config.modules.services.steamcmd; + runtimeAppId = if cfg.runtimeAppId == null then cfg.appId else cfg.runtimeAppId; + libraryPath = lib.concatStringsSep ":" cfg.libraryDirs; + prepareScript = pkgs.writeShellScript "steamcmd-${cfg.serviceName}-prepare" '' set -eu @@ -14,20 +17,15 @@ let -o ${lib.escapeShellArg cfg.user} \ -g ${lib.escapeShellArg cfg.group} \ -m 0770 \ - ${lib.escapeShellArg cfg.dataDir} - - ${pkgs.coreutils}/bin/install -d \ - -o ${lib.escapeShellArg cfg.user} \ - -g ${lib.escapeShellArg cfg.group} \ - -m 0770 \ + ${lib.escapeShellArg cfg.steamDir} \ ${lib.escapeShellArg cfg.installDir} \ - ${lib.escapeShellArgs cfg.dataDirs} + ${lib.escapeShellArg cfg.stateDir} ''; updateScript = pkgs.writeShellScript "steamcmd-${cfg.serviceName}-update" '' set -eu - export HOME=${lib.escapeShellArg cfg.dataDir} + export HOME=${lib.escapeShellArg cfg.steamDir} exec ${lib.getExe cfg.package} \ +force_install_dir ${lib.escapeShellArg cfg.installDir} \ +login anonymous \ @@ -38,8 +36,10 @@ let startScript = pkgs.writeShellScript "steamcmd-${cfg.serviceName}-start" '' set -eu - cd ${lib.escapeShellArg cfg.workingDirectory} - exec ${lib.escapeShellArgs cfg.command} + cd ${lib.escapeShellArg cfg.installDir} + export SteamAppId=${lib.escapeShellArg (toString runtimeAppId)} + ${lib.optionalString (cfg.libraryDirs != [ ]) ''export LD_LIBRARY_PATH=${lib.escapeShellArg libraryPath}:''${LD_LIBRARY_PATH-}''} + exec ${lib.getExe pkgs.steam-run} ${lib.escapeShellArg cfg.executable} ${lib.escapeShellArgs cfg.arguments} ''; restartCommand = @@ -69,11 +69,11 @@ in group = lib.mkOption { type = lib.types.str; - default = "steamcmd"; + default = "storage"; description = "Group account that owns writable server files."; }; - dataDir = lib.mkOption { + steamDir = lib.mkOption { type = lib.types.str; default = "/data/steamcmd"; description = "Directory where SteamCMD stores metadata and cache files."; @@ -82,37 +82,48 @@ in appId = lib.mkOption { type = lib.types.ints.positive; example = 896660; - description = "Steam app ID for the dedicated server."; + description = "Steam app ID for the dedicated server package."; + }; + + runtimeAppId = lib.mkOption { + type = lib.types.nullOr lib.types.ints.positive; + default = null; + example = 892970; + description = "Steam app ID exposed to the running server through SteamAppId. Defaults to appId."; }; installDir = lib.mkOption { type = lib.types.str; example = "/data/servers/valheim/main"; - description = "Directory where SteamCMD installs the server files."; + description = "Directory where SteamCMD installs the server files and where the game service starts."; }; - workingDirectory = lib.mkOption { + stateDir = lib.mkOption { type = lib.types.str; - default = cfg.installDir; - defaultText = lib.literalExpression "config.modules.services.steamcmd.installDir"; - example = "/data/servers/valheim/main"; - description = "Directory where the game service starts."; + example = "/data/state/valheim/main"; + description = "Writable directory for durable game server state."; }; - command = lib.mkOption { + executable = lib.mkOption { + type = lib.types.str; + example = "./valheim_server.x86_64"; + description = "Server executable, relative to installDir or absolute."; + }; + + arguments = lib.mkOption { type = lib.types.listOf lib.types.str; + default = [ ]; example = [ - "/data/servers/valheim/main/valheim_server.x86_64" "-name" "main" ]; - description = "Command that starts the game server."; + description = "Arguments passed to the server executable."; }; - environment = lib.mkOption { - type = lib.types.attrsOf lib.types.str; - default = { }; - description = "Environment variables for the game service."; + libraryDirs = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ "linux64" ]; + description = "Library directories added to LD_LIBRARY_PATH before starting the server."; }; environmentFiles = lib.mkOption { @@ -121,13 +132,6 @@ in description = "Environment files loaded by the game service."; }; - dataDirs = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = [ ]; - example = [ "/media/games/servers/valheim/main" ]; - description = "Additional writable directories created before the game service starts."; - }; - updateOnStart = lib.mkOption { type = lib.types.bool; default = true; @@ -140,12 +144,6 @@ in description = "Passes validate to SteamCMD app_update."; }; - packages = lib.mkOption { - type = lib.types.listOf lib.types.package; - default = [ ]; - description = "Packages added to the game service path."; - }; - tcpPorts = lib.mkOption { type = lib.types.listOf lib.types.port; default = [ ]; @@ -198,16 +196,17 @@ in isSystemUser = true; uid = config.registry."stable-uid".${config.networking.hostName}.steamcmd; group = cfg.group; - home = cfg.dataDir; + home = cfg.steamDir; }; systemd.tmpfiles.rules = [ - "d ${cfg.dataDir} 0770 ${cfg.user} ${cfg.group} - -" - "z ${cfg.dataDir} 0770 ${cfg.user} ${cfg.group} - -" + "d ${cfg.steamDir} 0770 ${cfg.user} ${cfg.group} - -" + "z ${cfg.steamDir} 0770 ${cfg.user} ${cfg.group} - -" "d ${cfg.installDir} 0770 ${cfg.user} ${cfg.group} - -" "z ${cfg.installDir} 0770 ${cfg.user} ${cfg.group} - -" - ] ++ map (dataDir: "d ${dataDir} 0770 ${cfg.user} ${cfg.group} - -") cfg.dataDirs - ++ map (dataDir: "z ${dataDir} 0770 ${cfg.user} ${cfg.group} - -") cfg.dataDirs; + "d ${cfg.stateDir} 0770 ${cfg.user} ${cfg.group} - -" + "z ${cfg.stateDir} 0770 ${cfg.user} ${cfg.group} - -" + ]; systemd.services = { "steamcmd-${cfg.serviceName}-update" = { @@ -218,7 +217,7 @@ in Type = "oneshot"; User = cfg.user; Group = cfg.group; - WorkingDirectory = "-${cfg.dataDir}"; + WorkingDirectory = "-${cfg.steamDir}"; ExecStartPre = "+${prepareScript}"; ExecStart = updateScript; }; @@ -232,13 +231,12 @@ in ]; wants = [ "network-online.target" ]; wantedBy = [ "multi-user.target" ]; - path = cfg.packages; - environment = cfg.environment; + path = [ pkgs.steam-run ]; serviceConfig = { Type = "simple"; User = cfg.user; Group = cfg.group; - WorkingDirectory = "-${cfg.workingDirectory}"; + WorkingDirectory = "-${cfg.installDir}"; EnvironmentFile = cfg.environmentFiles; ExecStartPre = [ "+${prepareScript}"