feat(nixos): add SteamCMD server support #34
@@ -66,6 +66,37 @@
|
||||
|
||||
registry.address.pikachu.self = "10.23.10.102";
|
||||
|
||||
modules.services.steamcmd = {
|
||||
enable = true;
|
||||
steamDir = "/pikachu/data/steamcmd";
|
||||
serviceName = "valheim";
|
||||
appId = 896660;
|
||||
installDir = "/pikachu/data/servers/valheim/main";
|
||||
stateDir = "/pikachu/media/games/servers/valheim/main";
|
||||
executable = "./valheim_server.x86_64";
|
||||
arguments = [
|
||||
"-nographics"
|
||||
"-batchmode"
|
||||
"-name"
|
||||
"main"
|
||||
"-port"
|
||||
"2456"
|
||||
"-world"
|
||||
"main"
|
||||
"-savedir"
|
||||
config.modules.services.steamcmd.stateDir
|
||||
"-password"
|
||||
"foobarbaz"
|
||||
"-public"
|
||||
"0"
|
||||
];
|
||||
udpPorts = [
|
||||
2456
|
||||
2457
|
||||
2458
|
||||
];
|
||||
};
|
||||
|
||||
guests.actualbudget = {
|
||||
enable = true;
|
||||
vlan = 20;
|
||||
|
||||
165
configs/nixos/modules/services/steamcmd.nix
Normal file
165
configs/nixos/modules/services/steamcmd.nix
Normal file
@@ -0,0 +1,165 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
options.modules.services.steamcmd = {
|
||||
enable = lib.mkEnableOption "SteamCMD-managed game server";
|
||||
|
||||
steamDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "/data/steamcmd";
|
||||
description = "Directory where SteamCMD stores metadata and cache files.";
|
||||
};
|
||||
|
||||
serviceName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "valheim";
|
||||
description = "Name of the systemd service that runs the game server.";
|
||||
};
|
||||
|
||||
appId = lib.mkOption {
|
||||
type = lib.types.ints.positive;
|
||||
example = 896660;
|
||||
description = "Steam app ID for the dedicated server package.";
|
||||
};
|
||||
|
||||
installDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "/data/servers/valheim/main";
|
||||
description = "Directory where SteamCMD installs the server files and where the game service starts.";
|
||||
};
|
||||
|
||||
stateDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "/data/state/valheim/main";
|
||||
description = "Writable directory for durable game server state.";
|
||||
};
|
||||
|
||||
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 = [
|
||||
"-name"
|
||||
"main"
|
||||
];
|
||||
description = "Arguments passed to the server executable.";
|
||||
};
|
||||
|
||||
udpPorts = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.port;
|
||||
default = [ ];
|
||||
description = "UDP ports opened for the game service.";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkMerge [
|
||||
{
|
||||
registry."stable-uid".${config.networking.hostName}.steamcmd = 20003;
|
||||
}
|
||||
|
||||
(lib.mkIf config.modules.services.steamcmd.enable (
|
||||
let
|
||||
service = config.modules.services.steamcmd;
|
||||
user = "steamcmd";
|
||||
group = "storage";
|
||||
|
||||
prepareScript = pkgs.writeShellScript "steamcmd-${service.serviceName}-prepare" ''
|
||||
set -eu
|
||||
|
||||
${pkgs.coreutils}/bin/install -d \
|
||||
-o ${user} \
|
||||
-g ${group} \
|
||||
-m 0770 \
|
||||
${lib.escapeShellArg service.steamDir} \
|
||||
${lib.escapeShellArg service.installDir} \
|
||||
${lib.escapeShellArg service.stateDir}
|
||||
'';
|
||||
|
||||
updateScript = pkgs.writeShellScript "steamcmd-${service.serviceName}-update" ''
|
||||
set -eu
|
||||
|
||||
export HOME=${lib.escapeShellArg service.steamDir}
|
||||
exec ${lib.getExe pkgs.steamcmd} \
|
||||
+force_install_dir ${lib.escapeShellArg service.installDir} \
|
||||
+login anonymous \
|
||||
+app_update ${toString service.appId} validate \
|
||||
+quit
|
||||
'';
|
||||
|
||||
startScript = pkgs.writeShellScript "steamcmd-${service.serviceName}-start" ''
|
||||
set -eu
|
||||
|
||||
cd ${lib.escapeShellArg service.installDir}
|
||||
export LD_LIBRARY_PATH=linux64:''${LD_LIBRARY_PATH-}
|
||||
exec ${lib.getExe pkgs.steam-run} ${lib.escapeShellArg service.executable} ${lib.escapeShellArgs service.arguments}
|
||||
'';
|
||||
in
|
||||
{
|
||||
users.users.${user} = {
|
||||
isSystemUser = true;
|
||||
uid = config.registry."stable-uid".${config.networking.hostName}.steamcmd;
|
||||
inherit group;
|
||||
home = service.steamDir;
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d ${service.steamDir} 0770 ${user} ${group} - -"
|
||||
"z ${service.steamDir} 0770 ${user} ${group} - -"
|
||||
"d ${service.installDir} 0770 ${user} ${group} - -"
|
||||
"z ${service.installDir} 0770 ${user} ${group} - -"
|
||||
"d ${service.stateDir} 0770 ${user} ${group} - -"
|
||||
"z ${service.stateDir} 0770 ${user} ${group} - -"
|
||||
];
|
||||
|
||||
systemd.services = {
|
||||
"steamcmd-${service.serviceName}-update" = {
|
||||
description = "Update ${service.serviceName} with SteamCMD";
|
||||
after = [ "network-online.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = user;
|
||||
Group = group;
|
||||
WorkingDirectory = "-${service.steamDir}";
|
||||
ExecStartPre = "+${prepareScript}";
|
||||
ExecStart = updateScript;
|
||||
};
|
||||
};
|
||||
|
||||
${service.serviceName} = {
|
||||
description = "${service.serviceName} game server";
|
||||
after = [
|
||||
"network-online.target"
|
||||
"steamcmd-${service.serviceName}-update.service"
|
||||
];
|
||||
wants = [ "network-online.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
User = user;
|
||||
Group = group;
|
||||
WorkingDirectory = "-${service.installDir}";
|
||||
ExecStartPre = [
|
||||
"+${prepareScript}"
|
||||
updateScript
|
||||
];
|
||||
ExecStart = startScript;
|
||||
Restart = "on-failure";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedUDPPorts = service.udpPorts;
|
||||
}
|
||||
))
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user