72 lines
2.8 KiB
Nix
72 lines
2.8 KiB
Nix
{
|
|
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 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;
|
|
ProtectHome = true;
|
|
ProtectSystem = "strict";
|
|
PrivateTmp = true;
|
|
RestrictAddressFamilies = [
|
|
"AF_UNIX" # systemctl talks to systemd over D-Bus unix socket
|
|
];
|
|
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";
|
|
GRACE_PERIOD = "15";
|
|
# Background services (qbittorrent, bitmagnet, postgresql, etc.) produce
|
|
# 15-25% non-nice CPU during normal operation. The stop threshold must
|
|
# sit above transient spikes; the resume threshold must be below the
|
|
# steady-state floor to avoid restarting xmrig while services are active.
|
|
CPU_STOP_THRESHOLD = "40";
|
|
CPU_RESUME_THRESHOLD = "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" ];
|
|
}
|