From e2b34f0f11ed8ad83d9ec9c14260192c3bcccb0d Mon Sep 17 00:00:00 2001 From: Sofi Date: Thu, 21 Jul 2022 21:05:43 +0200 Subject: [PATCH] nixos/minecraft-server: let server shutdown cleanly (#182149) --- .../services/games/minecraft-server.nix | 30 ++++++++++++++++++- nixos/tests/minecraft-server.nix | 1 + 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/nixos/modules/services/games/minecraft-server.nix b/nixos/modules/services/games/minecraft-server.nix index 8233962c1a2c..309fe43eaf4c 100644 --- a/nixos/modules/services/games/minecraft-server.nix +++ b/nixos/modules/services/games/minecraft-server.nix @@ -22,6 +22,15 @@ let '' + concatStringsSep "\n" (mapAttrsToList (n: v: "${n}=${cfgToString v}") cfg.serverProperties)); + stopScript = pkgs.writeShellScript "minecraft-server-stop" '' + echo stop > ${config.systemd.sockets.minecraft-server.socketConfig.ListenFIFO} + + # Wait for the PID of the minecraft server to disappear before + # returning, so systemd doesn't attempt to SIGKILL it. + while kill -0 "$1" 2> /dev/null; do + sleep 1s + done + ''; # To be able to open the firewall, we need to read out port values in the # server properties, but fall back to the defaults when those don't exist. @@ -172,16 +181,35 @@ in { }; users.groups.minecraft = {}; + systemd.sockets.minecraft-server = { + bindsTo = [ "minecraft-server.service" ]; + socketConfig = { + ListenFIFO = "/run/minecraft-server.stdin"; + SocketMode = "0660"; + SocketUser = "minecraft"; + SocketGroup = "minecraft"; + RemoveOnStop = true; + FlushPending = true; + }; + }; + systemd.services.minecraft-server = { description = "Minecraft Server Service"; wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; + requires = [ "minecraft-server.socket" ]; + after = [ "network.target" "minecraft-server.socket" ]; serviceConfig = { ExecStart = "${cfg.package}/bin/minecraft-server ${cfg.jvmOpts}"; + ExecStop = "${stopScript} $MAINPID"; Restart = "always"; User = "minecraft"; WorkingDirectory = cfg.dataDir; + + StandardInput = "socket"; + StandardOutput = "journal"; + StandardError = "journal"; + # Hardening CapabilityBoundingSet = [ "" ]; DeviceAllow = [ "" ]; diff --git a/nixos/tests/minecraft-server.nix b/nixos/tests/minecraft-server.nix index dbe2cd6d56fe..a51b36ff5308 100644 --- a/nixos/tests/minecraft-server.nix +++ b/nixos/tests/minecraft-server.nix @@ -33,5 +33,6 @@ in import ./make-test-python.nix ({ pkgs, ... }: { assert "${seed}" in server.succeed( "mcrcon -H localhost -P ${toString rcon-port} -p '${rcon-pass}' -c 'seed'" ) + server.succeed("systemctl stop minecraft-server") ''; })