refactor(nixos): simplify SteamCMD server options

This commit is contained in:
2026-09-09 21:51:20 -04:00
parent 266b90e488
commit 12e613fea4
2 changed files with 65 additions and 72 deletions

View File

@@ -68,33 +68,28 @@
modules.services.steamcmd = { modules.services.steamcmd = {
enable = true; enable = true;
dataDir = "/pikachu/data/steamcmd"; steamDir = "/pikachu/data/steamcmd";
serviceName = "valheim"; serviceName = "valheim";
appId = 896660; appId = 896660;
runtimeAppId = 892970;
installDir = "/pikachu/data/servers/valheim/main"; installDir = "/pikachu/data/servers/valheim/main";
workingDirectory = "/pikachu/data/servers/valheim/main"; stateDir = "/pikachu/media/games/servers/valheim/main";
group = "storage"; executable = "./valheim_server.x86_64";
dataDirs = [ "/pikachu/media/games/servers/valheim/main" ]; arguments = [
packages = [ pkgs.steam-run ]; "-nographics"
environment = { "-batchmode"
SteamAppId = "892970"; "-name"
SERVER_PASSWORD = "foobarbaz"; "main"
}; "-port"
command = [ "2456"
"${pkgs.bash}/bin/bash" "-world"
"-c" "main"
'' "-savedir"
export LD_LIBRARY_PATH="$PWD/linux64:$LD_LIBRARY_PATH" "/pikachu/media/games/servers/valheim/main"
exec steam-run ./valheim_server.x86_64 \ "-password"
-nographics \ "foobarbaz"
-batchmode \ "-public"
-name main \ "0"
-port 2456 \
-world main \
-savedir /pikachu/media/games/servers/valheim/main \
-password "$SERVER_PASSWORD" \
-public 0
''
]; ];
udpPorts = [ udpPorts = [
2456 2456

View File

@@ -7,6 +7,9 @@
let let
cfg = config.modules.services.steamcmd; 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" '' prepareScript = pkgs.writeShellScript "steamcmd-${cfg.serviceName}-prepare" ''
set -eu set -eu
@@ -14,20 +17,15 @@ let
-o ${lib.escapeShellArg cfg.user} \ -o ${lib.escapeShellArg cfg.user} \
-g ${lib.escapeShellArg cfg.group} \ -g ${lib.escapeShellArg cfg.group} \
-m 0770 \ -m 0770 \
${lib.escapeShellArg cfg.dataDir} ${lib.escapeShellArg cfg.steamDir} \
${pkgs.coreutils}/bin/install -d \
-o ${lib.escapeShellArg cfg.user} \
-g ${lib.escapeShellArg cfg.group} \
-m 0770 \
${lib.escapeShellArg cfg.installDir} \ ${lib.escapeShellArg cfg.installDir} \
${lib.escapeShellArgs cfg.dataDirs} ${lib.escapeShellArg cfg.stateDir}
''; '';
updateScript = pkgs.writeShellScript "steamcmd-${cfg.serviceName}-update" '' updateScript = pkgs.writeShellScript "steamcmd-${cfg.serviceName}-update" ''
set -eu set -eu
export HOME=${lib.escapeShellArg cfg.dataDir} export HOME=${lib.escapeShellArg cfg.steamDir}
exec ${lib.getExe cfg.package} \ exec ${lib.getExe cfg.package} \
+force_install_dir ${lib.escapeShellArg cfg.installDir} \ +force_install_dir ${lib.escapeShellArg cfg.installDir} \
+login anonymous \ +login anonymous \
@@ -38,8 +36,10 @@ let
startScript = pkgs.writeShellScript "steamcmd-${cfg.serviceName}-start" '' startScript = pkgs.writeShellScript "steamcmd-${cfg.serviceName}-start" ''
set -eu set -eu
cd ${lib.escapeShellArg cfg.workingDirectory} cd ${lib.escapeShellArg cfg.installDir}
exec ${lib.escapeShellArgs cfg.command} 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 = restartCommand =
@@ -69,11 +69,11 @@ in
group = lib.mkOption { group = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = "steamcmd"; default = "storage";
description = "Group account that owns writable server files."; description = "Group account that owns writable server files.";
}; };
dataDir = lib.mkOption { steamDir = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = "/data/steamcmd"; default = "/data/steamcmd";
description = "Directory where SteamCMD stores metadata and cache files."; description = "Directory where SteamCMD stores metadata and cache files.";
@@ -82,37 +82,48 @@ in
appId = lib.mkOption { appId = lib.mkOption {
type = lib.types.ints.positive; type = lib.types.ints.positive;
example = 896660; 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 { installDir = lib.mkOption {
type = lib.types.str; type = lib.types.str;
example = "/data/servers/valheim/main"; 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; type = lib.types.str;
default = cfg.installDir; example = "/data/state/valheim/main";
defaultText = lib.literalExpression "config.modules.services.steamcmd.installDir"; description = "Writable directory for durable game server state.";
example = "/data/servers/valheim/main";
description = "Directory where the game service starts.";
}; };
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; type = lib.types.listOf lib.types.str;
default = [ ];
example = [ example = [
"/data/servers/valheim/main/valheim_server.x86_64"
"-name" "-name"
"main" "main"
]; ];
description = "Command that starts the game server."; description = "Arguments passed to the server executable.";
}; };
environment = lib.mkOption { libraryDirs = lib.mkOption {
type = lib.types.attrsOf lib.types.str; type = lib.types.listOf lib.types.str;
default = { }; default = [ "linux64" ];
description = "Environment variables for the game service."; description = "Library directories added to LD_LIBRARY_PATH before starting the server.";
}; };
environmentFiles = lib.mkOption { environmentFiles = lib.mkOption {
@@ -121,13 +132,6 @@ in
description = "Environment files loaded by the game service."; 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 { updateOnStart = lib.mkOption {
type = lib.types.bool; type = lib.types.bool;
default = true; default = true;
@@ -140,12 +144,6 @@ in
description = "Passes validate to SteamCMD app_update."; 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 { tcpPorts = lib.mkOption {
type = lib.types.listOf lib.types.port; type = lib.types.listOf lib.types.port;
default = [ ]; default = [ ];
@@ -198,16 +196,17 @@ in
isSystemUser = true; isSystemUser = true;
uid = config.registry."stable-uid".${config.networking.hostName}.steamcmd; uid = config.registry."stable-uid".${config.networking.hostName}.steamcmd;
group = cfg.group; group = cfg.group;
home = cfg.dataDir; home = cfg.steamDir;
}; };
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules = [
"d ${cfg.dataDir} 0770 ${cfg.user} ${cfg.group} - -" "d ${cfg.steamDir} 0770 ${cfg.user} ${cfg.group} - -"
"z ${cfg.dataDir} 0770 ${cfg.user} ${cfg.group} - -" "z ${cfg.steamDir} 0770 ${cfg.user} ${cfg.group} - -"
"d ${cfg.installDir} 0770 ${cfg.user} ${cfg.group} - -" "d ${cfg.installDir} 0770 ${cfg.user} ${cfg.group} - -"
"z ${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 "d ${cfg.stateDir} 0770 ${cfg.user} ${cfg.group} - -"
++ map (dataDir: "z ${dataDir} 0770 ${cfg.user} ${cfg.group} - -") cfg.dataDirs; "z ${cfg.stateDir} 0770 ${cfg.user} ${cfg.group} - -"
];
systemd.services = { systemd.services = {
"steamcmd-${cfg.serviceName}-update" = { "steamcmd-${cfg.serviceName}-update" = {
@@ -218,7 +217,7 @@ in
Type = "oneshot"; Type = "oneshot";
User = cfg.user; User = cfg.user;
Group = cfg.group; Group = cfg.group;
WorkingDirectory = "-${cfg.dataDir}"; WorkingDirectory = "-${cfg.steamDir}";
ExecStartPre = "+${prepareScript}"; ExecStartPre = "+${prepareScript}";
ExecStart = updateScript; ExecStart = updateScript;
}; };
@@ -232,13 +231,12 @@ in
]; ];
wants = [ "network-online.target" ]; wants = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
path = cfg.packages; path = [ pkgs.steam-run ];
environment = cfg.environment;
serviceConfig = { serviceConfig = {
Type = "simple"; Type = "simple";
User = cfg.user; User = cfg.user;
Group = cfg.group; Group = cfg.group;
WorkingDirectory = "-${cfg.workingDirectory}"; WorkingDirectory = "-${cfg.installDir}";
EnvironmentFile = cfg.environmentFiles; EnvironmentFile = cfg.environmentFiles;
ExecStartPre = [ ExecStartPre = [
"+${prepareScript}" "+${prepareScript}"