xmrig-auto-pause: use cgroup.freeze and thaws

This commit is contained in:
2026-04-21 14:30:03 -04:00
parent a8cf95c7dd
commit 018b590e0d
3 changed files with 492 additions and 218 deletions

View File

@@ -2,15 +2,33 @@
config,
lib,
pkgs,
service_configs,
...
}:
let
cgroupDir = "/sys/fs/cgroup/system.slice/xmrig.service";
cgroupFreeze = "${cgroupDir}/cgroup.freeze";
in
lib.mkIf config.services.xmrig.enable {
systemd.services.xmrig-auto-pause = {
description = "Auto-pause xmrig when other services need CPU";
description = "Auto-pause xmrig via cgroup freezer when other services need CPU";
after = [ "xmrig.service" ];
# PartOf cascades stop/restart: when xmrig stops (deploy, apcupsd battery,
# manual), systemd stops auto-pause first and ExecStop thaws xmrig so
# xmrig's own stop does not hang on a frozen cgroup.
partOf = [ "xmrig.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${pkgs.python3}/bin/python3 ${./xmrig-auto-pause.py}";
# Safety net: any exit path (SIGTERM from PartOf cascade, systemctl stop,
# crash with Restart=) must leave xmrig thawed. The Python SIGTERM
# handler does the same thing; this covers SIGKILL / hard crash paths
# too. Idempotent.
ExecStop = pkgs.writeShellScript "xmrig-auto-pause-thaw" ''
f=${cgroupFreeze}
[ -w "$f" ] && echo 0 > "$f" || true
'';
Restart = "always";
RestartSec = "10s";
NoNewPrivileges = true;
@@ -22,6 +40,9 @@ lib.mkIf config.services.xmrig.enable {
];
MemoryDenyWriteExecute = true;
StateDirectory = "xmrig-auto-pause";
# Required so the script can write to cgroup.freeze under
# ProtectSystem=strict (which makes /sys read-only by default).
ReadWritePaths = [ cgroupDir ];
};
environment = {
POLL_INTERVAL = "3";
@@ -32,8 +53,19 @@ lib.mkIf config.services.xmrig.enable {
# steady-state floor to avoid restarting xmrig while services are active.
CPU_STOP_THRESHOLD = "40";
CPU_RESUME_THRESHOLD = "10";
STARTUP_COOLDOWN = "10";
STATE_DIR = "/var/lib/xmrig-auto-pause";
XMRIG_CGROUP_FREEZE = cgroupFreeze;
# Per-service CPU thresholds. Catches sub-threshold activity that never
# trips the system-wide gauge — a single Minecraft player uses 3-15% of
# one core (0.3-1.3% of a 12-thread host) which is pure noise in
# /proc/stat but dominant in the minecraft cgroup.
WATCHED_SERVICES = lib.concatStringsSep "," (
lib.optional config.services.minecraft-servers.enable "minecraft-server-${service_configs.minecraft.server_name}:2"
);
};
};
# Pull auto-pause along whenever xmrig starts. After= on auto-pause ensures
# correct order; Wants= here ensures it actually starts.
systemd.services.xmrig.wants = [ "xmrig-auto-pause.service" ];
}