refactor(nixos): localize SteamCMD script helpers

This commit is contained in:
2026-09-09 22:09:04 -04:00
parent fd60a08278
commit 1b450f434f

View File

@@ -6,45 +6,6 @@
}: }:
let let
cfg = config.modules.services.steamcmd; cfg = config.modules.services.steamcmd;
libraryPath = lib.concatStringsSep ":" cfg.libraryDirs;
prepareScript = pkgs.writeShellScript "steamcmd-${cfg.serviceName}-prepare" ''
set -eu
${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.escapeShellArg cfg.stateDir}
'';
updateScript = pkgs.writeShellScript "steamcmd-${cfg.serviceName}-update" ''
set -eu
export HOME=${lib.escapeShellArg cfg.steamDir}
exec ${lib.getExe cfg.package} \
+force_install_dir ${lib.escapeShellArg cfg.installDir} \
+login anonymous \
+app_update ${toString cfg.appId} ${lib.optionalString cfg.validateUpdate "validate"} \
+quit
'';
startScript = pkgs.writeShellScript "steamcmd-${cfg.serviceName}-start" ''
set -eu
cd ${lib.escapeShellArg cfg.installDir}
${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 =
if cfg.restart.command != null then
cfg.restart.command
else
"systemctl restart ${lib.escapeShellArg cfg.serviceName}.service";
in in
{ {
options.modules.services.steamcmd = { options.modules.services.steamcmd = {
@@ -181,87 +142,128 @@ in
registry."stable-uid".${config.networking.hostName}.steamcmd = 20003; registry."stable-uid".${config.networking.hostName}.steamcmd = 20003;
} }
(lib.mkIf cfg.enable { (lib.mkIf cfg.enable (
users.groups.${cfg.group} = { }; let
users.users.${cfg.user} = { prepareScript = pkgs.writeShellScript "steamcmd-${cfg.serviceName}-prepare" ''
isSystemUser = true; set -eu
uid = config.registry."stable-uid".${config.networking.hostName}.steamcmd;
group = cfg.group;
home = cfg.steamDir;
};
systemd.tmpfiles.rules = [ ${pkgs.coreutils}/bin/install -d \
"d ${cfg.steamDir} 0770 ${cfg.user} ${cfg.group} - -" -o ${lib.escapeShellArg cfg.user} \
"z ${cfg.steamDir} 0770 ${cfg.user} ${cfg.group} - -" -g ${lib.escapeShellArg cfg.group} \
"d ${cfg.installDir} 0770 ${cfg.user} ${cfg.group} - -" -m 0770 \
"z ${cfg.installDir} 0770 ${cfg.user} ${cfg.group} - -" ${lib.escapeShellArg cfg.steamDir} \
"d ${cfg.stateDir} 0770 ${cfg.user} ${cfg.group} - -" ${lib.escapeShellArg cfg.installDir} \
"z ${cfg.stateDir} 0770 ${cfg.user} ${cfg.group} - -" ${lib.escapeShellArg cfg.stateDir}
]; '';
systemd.services = { updateScript = pkgs.writeShellScript "steamcmd-${cfg.serviceName}-update" ''
"steamcmd-${cfg.serviceName}-update" = { set -eu
description = "Update ${cfg.serviceName} with SteamCMD";
after = [ "network-online.target" ]; export HOME=${lib.escapeShellArg cfg.steamDir}
wants = [ "network-online.target" ]; exec ${lib.getExe cfg.package} \
serviceConfig = { +force_install_dir ${lib.escapeShellArg cfg.installDir} \
Type = "oneshot"; +login anonymous \
User = cfg.user; +app_update ${toString cfg.appId} ${lib.optionalString cfg.validateUpdate "validate"} \
Group = cfg.group; +quit
WorkingDirectory = "-${cfg.steamDir}"; '';
ExecStartPre = "+${prepareScript}";
ExecStart = updateScript; libraryPath = lib.concatStringsSep ":" cfg.libraryDirs;
startScript = pkgs.writeShellScript "steamcmd-${cfg.serviceName}-start" ''
set -eu
cd ${lib.escapeShellArg cfg.installDir}
${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 =
if cfg.restart.command != null then
cfg.restart.command
else
"systemctl restart ${lib.escapeShellArg cfg.serviceName}.service";
in
{
users.groups.${cfg.group} = { };
users.users.${cfg.user} = {
isSystemUser = true;
uid = config.registry."stable-uid".${config.networking.hostName}.steamcmd;
group = cfg.group;
home = cfg.steamDir;
};
systemd.tmpfiles.rules = [
"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} - -"
"d ${cfg.stateDir} 0770 ${cfg.user} ${cfg.group} - -"
"z ${cfg.stateDir} 0770 ${cfg.user} ${cfg.group} - -"
];
systemd.services = {
"steamcmd-${cfg.serviceName}-update" = {
description = "Update ${cfg.serviceName} with SteamCMD";
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
serviceConfig = {
Type = "oneshot";
User = cfg.user;
Group = cfg.group;
WorkingDirectory = "-${cfg.steamDir}";
ExecStartPre = "+${prepareScript}";
ExecStart = updateScript;
};
};
${cfg.serviceName} = {
description = "${cfg.serviceName} game server";
after = [
"network-online.target"
"steamcmd-${cfg.serviceName}-update.service"
];
wants = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
path = [ pkgs.steam-run ];
serviceConfig = {
Type = "simple";
User = cfg.user;
Group = cfg.group;
WorkingDirectory = "-${cfg.installDir}";
EnvironmentFile = cfg.environmentFiles;
ExecStartPre = [
"+${prepareScript}"
] ++ lib.optional cfg.updateOnStart updateScript;
ExecStart = startScript;
Restart = "on-failure";
};
};
"steamcmd-${cfg.serviceName}-restart" = lib.mkIf cfg.restart.enable {
description = "Restart ${cfg.serviceName}";
serviceConfig = {
Type = "oneshot";
ExecStart = pkgs.writeShellScript "steamcmd-${cfg.serviceName}-restart" ''
set -eu
exec ${restartCommand}
'';
};
}; };
}; };
${cfg.serviceName} = { systemd.timers."steamcmd-${cfg.serviceName}-restart" = lib.mkIf cfg.restart.enable {
description = "${cfg.serviceName} game server"; description = "Restart ${cfg.serviceName} on a schedule";
after = [ wantedBy = [ "timers.target" ];
"network-online.target" timerConfig = {
"steamcmd-${cfg.serviceName}-update.service" OnCalendar = cfg.restart.onCalendar;
]; RandomizedDelaySec = cfg.restart.randomizedDelaySec;
wants = [ "network-online.target" ]; Persistent = true;
wantedBy = [ "multi-user.target" ];
path = [ pkgs.steam-run ];
serviceConfig = {
Type = "simple";
User = cfg.user;
Group = cfg.group;
WorkingDirectory = "-${cfg.installDir}";
EnvironmentFile = cfg.environmentFiles;
ExecStartPre = [
"+${prepareScript}"
] ++ lib.optional cfg.updateOnStart updateScript;
ExecStart = startScript;
Restart = "on-failure";
}; };
}; };
"steamcmd-${cfg.serviceName}-restart" = lib.mkIf cfg.restart.enable { networking.firewall.allowedTCPPorts = cfg.tcpPorts;
description = "Restart ${cfg.serviceName}"; networking.firewall.allowedUDPPorts = cfg.udpPorts;
serviceConfig = { }
Type = "oneshot"; ))
ExecStart = pkgs.writeShellScript "steamcmd-${cfg.serviceName}-restart" ''
set -eu
exec ${restartCommand}
'';
};
};
};
systemd.timers."steamcmd-${cfg.serviceName}-restart" = lib.mkIf cfg.restart.enable {
description = "Restart ${cfg.serviceName} on a schedule";
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = cfg.restart.onCalendar;
RandomizedDelaySec = cfg.restart.randomizedDelaySec;
Persistent = true;
};
};
networking.firewall.allowedTCPPorts = cfg.tcpPorts;
networking.firewall.allowedUDPPorts = cfg.udpPorts;
})
]; ];
} }