fix(nixos): decouple game startup from guest readiness #50

Merged
alexion merged 2 commits from fix/game-guest-readiness into main 2026-09-15 19:09:00 -04:00
4 changed files with 37 additions and 8 deletions

View File

@@ -50,6 +50,12 @@ in
description = "Public IP address advertised by the Palworld server."; description = "Public IP address advertised by the Palworld server.";
}; };
autoStart = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Start the Palworld server after the guest reaches network readiness.";
};
passwordSecret = lib.mkOption { passwordSecret = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = "services/game-servers/password"; default = "services/game-servers/password";
@@ -82,7 +88,7 @@ in
guests.palworld = { guests.palworld = {
interior.modules.services.games.palworld = { interior.modules.services.games.palworld = {
enable = true; enable = true;
inherit (cfg) serverName port publicIP; inherit (cfg) serverName port publicIP autoStart;
inherit steamDir installDir stateDir; inherit steamDir installDir stateDir;
passwordFile = "/run/secrets/${cfg.passwordSecret}"; passwordFile = "/run/secrets/${cfg.passwordSecret}";
adminPasswordFile = "/run/secrets/${cfg.adminPasswordSecret}"; adminPasswordFile = "/run/secrets/${cfg.adminPasswordSecret}";

View File

@@ -94,6 +94,7 @@
installPath = "/pikachu/data/servers/palworld/tracion"; installPath = "/pikachu/data/servers/palworld/tracion";
statePath = "/pikachu/media/games/servers/palworld/tracion"; statePath = "/pikachu/media/games/servers/palworld/tracion";
serverName = "Tracion"; serverName = "Tracion";
autoStart = false;
adminPasswordSecret = "services/game-servers/admin/password"; adminPasswordSecret = "services/game-servers/admin/password";
publicIP = config.guests.palworld.address; publicIP = config.guests.palworld.address;
reverseProxy = { reverseProxy = {

View File

@@ -56,6 +56,12 @@
description = "Advertise the server in Palworld's public lobby."; description = "Advertise the server in Palworld's public lobby.";
}; };
autoStart = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Start the Palworld server after the guest reaches network readiness.";
};
rcon = { rcon = {
enable = lib.mkEnableOption "Palworld RCON" // { enable = lib.mkEnableOption "Palworld RCON" // {
default = true; default = true;
@@ -126,6 +132,7 @@
inherit (service) steamDir installDir stateDir; inherit (service) steamDir installDir stateDir;
serviceName = "palworld-${lib.toLower service.serverName}"; serviceName = "palworld-${lib.toLower service.serverName}";
appId = 2394010; appId = 2394010;
inherit (service) autoStart;
executable = "${startScript}"; executable = "${startScript}";
arguments = arguments =
[ [

View File

@@ -65,6 +65,12 @@
default = [ ]; default = [ ];
description = "TCP ports opened for the game service."; description = "TCP ports opened for the game service.";
}; };
autoStart = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Start the game service after the guest reaches network readiness.";
};
}; };
config = lib.mkMerge [ config = lib.mkMerge [
@@ -142,24 +148,33 @@
}; };
}; };
"${service.serviceName}-autostart" = {
description = "Queue ${service.serviceName} game server startup";
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
wantedBy = lib.mkIf service.autoStart [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.systemd}/bin/systemctl --no-block start ${service.serviceName}.service";
};
};
${service.serviceName} = { ${service.serviceName} = {
description = "${service.serviceName} game server"; description = "${service.serviceName} game server";
after = [ after = [
"multi-user.target"
"network-online.target" "network-online.target"
"steamcmd-${service.serviceName}-update.service" "steamcmd-${service.serviceName}-update.service"
]; ];
wants = [ "network-online.target" ]; wants = [
wantedBy = [ "multi-user.target" ]; "network-online.target"
"steamcmd-${service.serviceName}-update.service"
];
serviceConfig = { serviceConfig = {
Type = "simple"; Type = "simple";
User = user; User = user;
Group = group; Group = group;
WorkingDirectory = "-${service.installDir}"; WorkingDirectory = "-${service.installDir}";
ExecStartPre = [ ExecStartPre = "+${prepareScript}";
"+${prepareScript}"
updateScript
];
ExecStart = startScript; ExecStart = startScript;
Restart = "on-failure"; Restart = "on-failure";
TimeoutStartSec = "15min"; TimeoutStartSec = "15min";