-
-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
183 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
{ | ||
lib, | ||
config, | ||
pkgs, | ||
... | ||
}: | ||
let | ||
cfg = config.services.pid-fan-controller; | ||
heatSource = { | ||
options = { | ||
name = lib.mkOption { | ||
type = lib.types.uniq lib.types.nonEmptyStr; | ||
description = "name of heat source"; | ||
}; | ||
wildcard_path = lib.mkOption { | ||
type = lib.types.nonEmptyStr; | ||
description = ''wildcard path of heat source hwmon "temp_input", can contain wildcards''; | ||
}; | ||
PID_params = { | ||
set_point = lib.mkOption { | ||
type = lib.types.ints.unsigned; | ||
description = "set point of controller in °C"; | ||
}; | ||
P = lib.mkOption { | ||
description = "K_p of PID controller"; | ||
type = lib.types.float; | ||
}; | ||
I = lib.mkOption { | ||
description = "K_i of PID controller"; | ||
type = lib.types.float; | ||
}; | ||
D = lib.mkOption { | ||
description = "K_d of PID controller"; | ||
type = lib.types.float; | ||
}; | ||
}; | ||
}; | ||
}; | ||
|
||
fan = { | ||
options = { | ||
wildcard_path = lib.mkOption { | ||
type = lib.types.str; | ||
description = '' | ||
wildcard path of the hwmon "pwm" file. | ||
If the fans are not to be found in /sys/class/hwmon/hwmon* the corresponding | ||
kernel module (like "nct6775") needs to be added to `boot.kernelModules`. | ||
See: [hwmon](https://www.kernel.org/doc/html/latest/hwmon/index.html) | ||
''; | ||
}; | ||
min_pwm = lib.mkOption { | ||
default = 0; | ||
type = lib.types.ints.between 0 255; | ||
description = "minimum PWM fan speed"; | ||
}; | ||
max_pwm = lib.mkOption { | ||
default = 255; | ||
type = lib.types.ints.between 0 255; | ||
description = "maximum PWM fan speed"; | ||
}; | ||
cutoff = lib.mkOption { | ||
default = false; | ||
type = lib.types.bool; | ||
description = "whether to stop fan when `min_pwm` is reached"; | ||
}; | ||
heat_pressure_srcs = lib.mkOption { | ||
type = lib.types.nonEmptyListOf lib.types.str; | ||
description = "heat pressure sources which are affected by the fan"; | ||
}; | ||
}; | ||
}; | ||
in | ||
{ | ||
options.services.pid-fan-controller = { | ||
enable = lib.mkEnableOption "Enable PID fan controller"; | ||
package = lib.mkPackageOption pkgs "pid-fan-controller" { }; | ||
settings = { | ||
interval = lib.mkOption { | ||
default = 500; | ||
type = lib.types.int; | ||
description = "Interval between controller cycles."; | ||
}; | ||
heat_srcs = lib.mkOption { | ||
type = lib.types.listOf (lib.types.submodule heatSource); | ||
description = "list of heat sources"; | ||
example = '' | ||
[ | ||
{ | ||
name = "cpu"; | ||
wildcard_path = "/sys/devices/pci0000:00/0000:00:18.3/hwmon/hwmon*/temp1_input"; | ||
PID_params = { | ||
set_point = 60; | ||
P = -5.0e-3; | ||
I = -2.0e-3; | ||
D = -6.0e-3; | ||
}; | ||
} | ||
{ | ||
name = "gpu"; | ||
wildcard_path = "/sys/class/drm/card*/device/hwmon/hwmon*/temp2_input"; | ||
PID_params = { | ||
set_point = 65; | ||
P = -5.0e-3; | ||
I = -2.0e-3; | ||
D = -6.0e-3; | ||
}; | ||
} | ||
]; | ||
''; | ||
}; | ||
fans = lib.mkOption { | ||
type = lib.types.listOf (lib.types.submodule fan); | ||
description = "list of fans"; | ||
example = '' | ||
[ | ||
{ | ||
wildcard_path = "/sys/devices/platform/nct6775.2592/hwmon/hwmon*/pwm1"; | ||
min_pwm = 60; | ||
max_pwm = 255; | ||
heat_pressure_srcs = [ | ||
"cpu" | ||
"gpu" | ||
]; | ||
} | ||
{ | ||
wildcard_path = "/sys/devices/platform/nct6775.2592/hwmon/hwmon*/pwm4"; | ||
min_pwm = 60; | ||
max_pwm = 200; | ||
cutoff = true; | ||
heat_pressure_srcs = [ | ||
"cpu" | ||
]; | ||
} | ||
]; | ||
''; | ||
}; | ||
}; | ||
}; | ||
config = lib.mkIf cfg.enable { | ||
environment.etc."pid-fan-settings.json".text = builtins.toJSON cfg.settings; | ||
|
||
systemd.services.pid-fan-controller = { | ||
wantedBy = [ "multi-user.target" ]; | ||
serviceConfig = { | ||
Type = "simple"; | ||
ExecStart = [ "${cfg.package}/bin/pid-fan-controller" ]; | ||
ExecStopPost = [ "${cfg.package}/bin/pid-fan-controller disable" ]; | ||
Restart = "always"; | ||
#This service needs to run as root to write to /sys. | ||
#therefore it should operate with the least amount of priviledges needed | ||
ProtectHome = "yes"; | ||
#strict is not possible as it needs /sys | ||
ProtectSystem = "full"; | ||
ProtectProc = "invisible"; | ||
PrivateNetwork = "yes"; | ||
NoNewPrivileges = "yes"; | ||
MemoryDenyWriteExecute = "yes"; | ||
RestrictNamespaces = "~user pid net uts mnt"; | ||
ProtectKernelModules = "yes"; | ||
RestrictRealtime = "yes"; | ||
SystemCallFilter = "@system-service"; | ||
CapabilityBoundingSet = "~CAP_KILL CAP_WAKE_ALARM CAP_IPC_LOC CAP_BPF CAP_LINUX_IMMUTABLE CAP_BLOCK_SUSPEND CAP_MKNOD"; | ||
}; | ||
# restart unit if config changed | ||
restartTriggers = [ config.environment.etc."pid-fan-settings.json".text ]; | ||
}; | ||
#sleep hook to restart the service as it breaks sometimes otherwise | ||
systemd.services.pid-fan-controller-sleep = { | ||
before = [ "sleep.target" ]; | ||
wantedBy = [ "sleep.target" ]; | ||
unitConfig = { | ||
StopWhenUnneeded = "yes"; | ||
}; | ||
serviceConfig = { | ||
Type = "oneshot"; | ||
RemainAfterExit = true; | ||
ExecStart = [ "${pkgs.systemd}/bin/systemctl stop pid-fan-controller.service" ]; | ||
ExecStop = [ "${pkgs.systemd}/bin/systemctl restart pid-fan-controller.service" ]; | ||
}; | ||
}; | ||
}; | ||
} |