refactor(nixos): trim SteamCMD module options

This commit is contained in:
2026-09-09 22:13:45 -04:00
parent 16f34f3a8d
commit 5e2f6e0c1b

View File

@@ -8,33 +8,18 @@
options.modules.services.steamcmd = { options.modules.services.steamcmd = {
enable = lib.mkEnableOption "SteamCMD-managed game server"; enable = lib.mkEnableOption "SteamCMD-managed game server";
package = lib.mkPackageOption pkgs "steamcmd" { }; steamDir = lib.mkOption {
type = lib.types.str;
example = "/data/steamcmd";
description = "Directory where SteamCMD stores metadata and cache files.";
};
serviceName = lib.mkOption { serviceName = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = "steamcmd";
example = "valheim"; example = "valheim";
description = "Name of the systemd service that runs the game server."; description = "Name of the systemd service that runs the game server.";
}; };
user = lib.mkOption {
type = lib.types.str;
default = "steamcmd";
description = "User account that runs SteamCMD and the game server.";
};
group = lib.mkOption {
type = lib.types.str;
default = "storage";
description = "Group account that owns writable server files.";
};
steamDir = lib.mkOption {
type = lib.types.str;
default = "/data/steamcmd";
description = "Directory where SteamCMD stores metadata and cache files.";
};
appId = lib.mkOption { appId = lib.mkOption {
type = lib.types.ints.positive; type = lib.types.ints.positive;
example = 896660; example = 896660;
@@ -69,69 +54,11 @@
description = "Arguments passed to the server executable."; description = "Arguments passed to the server executable.";
}; };
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 {
type = lib.types.listOf lib.types.path;
default = [ ];
description = "Environment files loaded by the game service.";
};
updateOnStart = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Runs SteamCMD before each game service start.";
};
validateUpdate = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Passes validate to SteamCMD app_update.";
};
tcpPorts = lib.mkOption {
type = lib.types.listOf lib.types.port;
default = [ ];
description = "TCP ports opened for the game service.";
};
udpPorts = lib.mkOption { udpPorts = lib.mkOption {
type = lib.types.listOf lib.types.port; type = lib.types.listOf lib.types.port;
default = [ ]; default = [ ];
description = "UDP ports opened for the game service."; description = "UDP ports opened for the game service.";
}; };
restart = {
enable = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Enables the scheduled restart timer.";
};
onCalendar = lib.mkOption {
type = lib.types.str;
default = "daily";
example = "*-*-* 05:00:00";
description = "Calendar expression for the restart timer.";
};
randomizedDelaySec = lib.mkOption {
type = lib.types.str;
default = "15m";
description = "Maximum randomized delay for the restart timer.";
};
command = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "systemctl restart valheim.service";
description = "Command run by the restart timer.";
};
};
}; };
config = lib.mkMerge [ config = lib.mkMerge [
@@ -141,125 +68,97 @@
(lib.mkIf config.modules.services.steamcmd.enable ( (lib.mkIf config.modules.services.steamcmd.enable (
let let
prepareScript = pkgs.writeShellScript "steamcmd-${config.modules.services.steamcmd.serviceName}-prepare" '' service = config.modules.services.steamcmd;
user = "steamcmd";
group = "storage";
prepareScript = pkgs.writeShellScript "steamcmd-${service.serviceName}-prepare" ''
set -eu set -eu
${pkgs.coreutils}/bin/install -d \ ${pkgs.coreutils}/bin/install -d \
-o ${lib.escapeShellArg config.modules.services.steamcmd.user} \ -o ${user} \
-g ${lib.escapeShellArg config.modules.services.steamcmd.group} \ -g ${group} \
-m 0770 \ -m 0770 \
${lib.escapeShellArg config.modules.services.steamcmd.steamDir} \ ${lib.escapeShellArg service.steamDir} \
${lib.escapeShellArg config.modules.services.steamcmd.installDir} \ ${lib.escapeShellArg service.installDir} \
${lib.escapeShellArg config.modules.services.steamcmd.stateDir} ${lib.escapeShellArg service.stateDir}
''; '';
updateScript = pkgs.writeShellScript "steamcmd-${config.modules.services.steamcmd.serviceName}-update" '' updateScript = pkgs.writeShellScript "steamcmd-${service.serviceName}-update" ''
set -eu set -eu
export HOME=${lib.escapeShellArg config.modules.services.steamcmd.steamDir} export HOME=${lib.escapeShellArg service.steamDir}
exec ${lib.getExe config.modules.services.steamcmd.package} \ exec ${lib.getExe pkgs.steamcmd} \
+force_install_dir ${lib.escapeShellArg config.modules.services.steamcmd.installDir} \ +force_install_dir ${lib.escapeShellArg service.installDir} \
+login anonymous \ +login anonymous \
+app_update ${toString config.modules.services.steamcmd.appId} ${lib.optionalString config.modules.services.steamcmd.validateUpdate "validate"} \ +app_update ${toString service.appId} validate \
+quit +quit
''; '';
libraryPath = lib.concatStringsSep ":" config.modules.services.steamcmd.libraryDirs; startScript = pkgs.writeShellScript "steamcmd-${service.serviceName}-start" ''
startScript = pkgs.writeShellScript "steamcmd-${config.modules.services.steamcmd.serviceName}-start" ''
set -eu set -eu
cd ${lib.escapeShellArg config.modules.services.steamcmd.installDir} cd ${lib.escapeShellArg service.installDir}
${lib.optionalString (config.modules.services.steamcmd.libraryDirs != [ ]) ''export LD_LIBRARY_PATH=${lib.escapeShellArg libraryPath}:''${LD_LIBRARY_PATH-}''} export LD_LIBRARY_PATH=linux64:''${LD_LIBRARY_PATH-}
exec ${lib.getExe pkgs.steam-run} ${lib.escapeShellArg config.modules.services.steamcmd.executable} ${lib.escapeShellArgs config.modules.services.steamcmd.arguments} exec ${lib.getExe pkgs.steam-run} ${lib.escapeShellArg service.executable} ${lib.escapeShellArgs service.arguments}
''; '';
restartCommand =
if config.modules.services.steamcmd.restart.command != null then
config.modules.services.steamcmd.restart.command
else
"systemctl restart ${lib.escapeShellArg config.modules.services.steamcmd.serviceName}.service";
in in
{ {
users.groups.${config.modules.services.steamcmd.group} = { }; users.users.${user} = {
users.users.${config.modules.services.steamcmd.user} = {
isSystemUser = true; isSystemUser = true;
uid = config.registry."stable-uid".${config.networking.hostName}.steamcmd; uid = config.registry."stable-uid".${config.networking.hostName}.steamcmd;
group = config.modules.services.steamcmd.group; inherit group;
home = config.modules.services.steamcmd.steamDir; home = service.steamDir;
}; };
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules = [
"d ${config.modules.services.steamcmd.steamDir} 0770 ${config.modules.services.steamcmd.user} ${config.modules.services.steamcmd.group} - -" "d ${service.steamDir} 0770 ${user} ${group} - -"
"z ${config.modules.services.steamcmd.steamDir} 0770 ${config.modules.services.steamcmd.user} ${config.modules.services.steamcmd.group} - -" "z ${service.steamDir} 0770 ${user} ${group} - -"
"d ${config.modules.services.steamcmd.installDir} 0770 ${config.modules.services.steamcmd.user} ${config.modules.services.steamcmd.group} - -" "d ${service.installDir} 0770 ${user} ${group} - -"
"z ${config.modules.services.steamcmd.installDir} 0770 ${config.modules.services.steamcmd.user} ${config.modules.services.steamcmd.group} - -" "z ${service.installDir} 0770 ${user} ${group} - -"
"d ${config.modules.services.steamcmd.stateDir} 0770 ${config.modules.services.steamcmd.user} ${config.modules.services.steamcmd.group} - -" "d ${service.stateDir} 0770 ${user} ${group} - -"
"z ${config.modules.services.steamcmd.stateDir} 0770 ${config.modules.services.steamcmd.user} ${config.modules.services.steamcmd.group} - -" "z ${service.stateDir} 0770 ${user} ${group} - -"
]; ];
systemd.services = { systemd.services = {
"steamcmd-${config.modules.services.steamcmd.serviceName}-update" = { "steamcmd-${service.serviceName}-update" = {
description = "Update ${config.modules.services.steamcmd.serviceName} with SteamCMD"; description = "Update ${service.serviceName} with SteamCMD";
after = [ "network-online.target" ]; after = [ "network-online.target" ];
wants = [ "network-online.target" ]; wants = [ "network-online.target" ];
serviceConfig = { serviceConfig = {
Type = "oneshot"; Type = "oneshot";
User = config.modules.services.steamcmd.user; User = user;
Group = config.modules.services.steamcmd.group; Group = group;
WorkingDirectory = "-${config.modules.services.steamcmd.steamDir}"; WorkingDirectory = "-${service.steamDir}";
ExecStartPre = "+${prepareScript}"; ExecStartPre = "+${prepareScript}";
ExecStart = updateScript; ExecStart = updateScript;
}; };
}; };
${config.modules.services.steamcmd.serviceName} = { ${service.serviceName} = {
description = "${config.modules.services.steamcmd.serviceName} game server"; description = "${service.serviceName} game server";
after = [ after = [
"network-online.target" "network-online.target"
"steamcmd-${config.modules.services.steamcmd.serviceName}-update.service" "steamcmd-${service.serviceName}-update.service"
]; ];
wants = [ "network-online.target" ]; wants = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
path = [ pkgs.steam-run ];
serviceConfig = { serviceConfig = {
Type = "simple"; Type = "simple";
User = config.modules.services.steamcmd.user; User = user;
Group = config.modules.services.steamcmd.group; Group = group;
WorkingDirectory = "-${config.modules.services.steamcmd.installDir}"; WorkingDirectory = "-${service.installDir}";
EnvironmentFile = config.modules.services.steamcmd.environmentFiles;
ExecStartPre = [ ExecStartPre = [
"+${prepareScript}" "+${prepareScript}"
] ++ lib.optional config.modules.services.steamcmd.updateOnStart updateScript; updateScript
];
ExecStart = startScript; ExecStart = startScript;
Restart = "on-failure"; Restart = "on-failure";
}; };
}; };
"steamcmd-${config.modules.services.steamcmd.serviceName}-restart" = lib.mkIf config.modules.services.steamcmd.restart.enable {
description = "Restart ${config.modules.services.steamcmd.serviceName}";
serviceConfig = {
Type = "oneshot";
ExecStart = pkgs.writeShellScript "steamcmd-${config.modules.services.steamcmd.serviceName}-restart" ''
set -eu
exec ${restartCommand}
'';
};
};
}; };
systemd.timers."steamcmd-${config.modules.services.steamcmd.serviceName}-restart" = lib.mkIf config.modules.services.steamcmd.restart.enable { networking.firewall.allowedUDPPorts = service.udpPorts;
description = "Restart ${config.modules.services.steamcmd.serviceName} on a schedule";
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = config.modules.services.steamcmd.restart.onCalendar;
RandomizedDelaySec = config.modules.services.steamcmd.restart.randomizedDelaySec;
Persistent = true;
};
};
networking.firewall.allowedTCPPorts = config.modules.services.steamcmd.tcpPorts;
networking.firewall.allowedUDPPorts = config.modules.services.steamcmd.udpPorts;
} }
)) ))
]; ];