1+ #
2+ # fan2go.nix
3+ #
4+ # sudo systemctl status fan2go
5+ # sudo ls /var/lib/fan2go
6+ #
7+ # See also: https://github.com/arnarg/config/blob/8de65cf5f1649a4fe6893102120ede4363de9bfa/hosts/terra/fan2go.nix
8+ #
9+ {
10+ lib ,
11+ config ,
12+ pkgs ,
13+ ...
14+ } :
15+ let
16+ cfg = config . hardware . fan2go ;
17+
18+ fan2goConfig = pkgs . writeText "fan2go.yaml" ''
19+ #
20+ # fan2go.yaml
21+ #
22+ dbPath: ${ cfg . dbPath }
23+
24+ fans:
25+ # Define the fan to be controlled. This is Fan 1 on the Corsair Commander Core XT.
26+ - id: corsair_fan1
27+ # Use liquidctl to set the fan speed.
28+ # The fan type for external commands is `cmd`.
29+ # Assumes the Corsair Commander Core XT is the first device liquidctl finds.
30+ cmd:
31+ # The `setPwm` command is required. It receives a value from 0-255.
32+ # We use a shell command to convert the 0-255 PWM value from fan2go
33+ # into a 0-100 percentage for liquidctl.
34+ setPwm:
35+ exec: "/run/current-system/sw/bin/bash"
36+ args: ["-c", "percent=$((%pwm% * 100 / 255)); /run/current-system/sw/bin/liquidctl set fan1 speed $percent"]
37+ # The `getPwm` command is optional but good practice.
38+ # It should return a value from 0-255.
39+ getPwm:
40+ exec: "/run/current-system/sw/bin/bash"
41+ args: ["-c", "percent=$(/run/current-system/sw/bin/liquidctl status --json | ${ pkgs . jq } /bin/jq '.[0].status[] | select(.key == \"Fan speed 1\").value | tonumber'); echo $((percent * 255 / 100))"]
42+ # Fan speed is a percentage for liquidctl
43+ min: 20
44+ max: 100
45+ ## Ensures the fan never fully stops, maintaining minimum airflow.
46+ #neverStop: true
47+ # The curve ID that should be used to determine the speed of this fan.
48+ curve: gpu_cooling_curve
49+
50+ sensors:
51+ # Define the temperature sensor to monitor. This is the Radeon Pro VII/MI50.
52+ # From `fan2go detect`, this is platform `amdgpu-pci-04400`.
53+ # The sensor type is `hwmon`.
54+ - id: gpu_mi50_temp
55+ hwmon:
56+ platform: amdgpu-pci-04400
57+ # Use the junction temperature (temp2_input) as it's a good indicator of core heat.
58+ index: 2
59+
60+ curves:
61+ # Link the GPU temperature to the case fan speed.
62+ - id: gpu_cooling_curve
63+ # Use a linear interpolation curve based on the defined points.
64+ linear:
65+ # The sensor ID to use as a temperature input for this curve.
66+ sensor: gpu_mi50_temp
67+ # Define the temperature-to-fan-speed mapping.
68+ # Temps are in Celsius, fan speed is in percent.
69+ points:
70+ - [40, 20] # At 40°C, run fan at 20%
71+ - [50, 40] # At 50°C, run fan at 40%
72+ - [60, 60] # At 60°C, run fan at 60%
73+ - [70, 80] # At 70°C, run fan at 80%
74+ - [80, 100] # At 80°C and above, run fan at 100%
75+
76+ statistics:
77+ # Whether to enable the prometheus exporter or not
78+ enabled: true
79+ # The port to expose the exporter on
80+ port: 9900
81+ '' ;
82+ in
83+ {
84+ options . hardware . fan2go = with lib ; {
85+ enable = mkEnableOption "fan2go" ;
86+
87+ dbPath = mkOption {
88+ type = types . str ;
89+ default = "/var/lib/fan2go/fan2go.db" ;
90+ description = "The path of the database file" ;
91+ } ;
92+ } ;
93+
94+ config = lib . mkIf cfg . enable {
95+ systemd . services . fan2go = {
96+ description = "A simple daemon providing dynamic fan speed control based on temperature sensors" ;
97+ wantedBy = [ "multi-user.target" ] ;
98+ after = [ "lm_sensors.service" ] ;
99+
100+ serviceConfig = {
101+ ExecStart = lib . concatStringsSep " " [
102+ "${ pkgs . fan2go } /bin/fan2go"
103+ "-c"
104+ "${ fan2goConfig } "
105+ "--no-style"
106+ ] ;
107+ LimitNOFILE = 8192 ;
108+ } ;
109+ } ;
110+ } ;
111+ }
0 commit comments