···
cfg = config.services.thinkfan;
+
settingsFormat = pkgs.formats.yaml { };
+
configFile = settingsFormat.generate "thinkfan.yaml" cfg.settings;
+
thinkfan = pkgs.thinkfan.override { inherit (cfg) smartSupport; };
+
# fan-speed and temperature levels
+
levelType = with types;
+
tuple = ts: mkOptionType {
+
merge = mergeOneOption;
+
check = xs: all id (zipListsWith (t: x: t.check x) ts xs);
+
description = "tuple of" + concatMapStrings (t: " (${t.description})") ts;
+
special = enum [ "level auto" "level full-speed" "level disengage" ];
+
tuple [ (either level special) level level ];
+
sensorType = name: types.submodule {
+
freeformType = types.attrsOf settingsFormat.type;
+
type = types.enum [ "hwmon" "atasmart" "tpacpi" "nvml" ];
+
The ${name} type, can be
+
<literal>hwmon</literal> for standard ${name}s,
+
<literal>atasmart</literal> to read the temperature via
+
S.M.A.R.T (requires smartSupport to be enabled),
+
<literal>tpacpi</literal> for the legacy thinkpac_acpi driver, or
+
<literal>nvml</literal> for the (proprietary) nVidia driver.
+
The query string used to match one or more ${name}s: can be
+
a fullpath to the temperature file (single ${name}) or a fullpath
+
to a driver directory (multiple ${name}s).
+
When multiple ${name}s match, the query can be restricted using the
+
<option>name</option> or <option>indices</option> options.
+
type = with types; nullOr (listOf ints.unsigned);
+
A list of ${name}s to pick in case multiple ${name}s match the query.
+
<note><para>Indices start from 0.</para></note>
+
} // optionalAttrs (name == "sensor") {
+
correction = mkOption {
+
type = with types; nullOr (listOf int);
+
A list of values to be added to the temperature of each sensor,
+
can be used to equalize small discrepancies in temperature ratings.
+
# removes NixOS special and unused attributes
+
sensorToConf = { type, query, ... }@args:
+
(filterAttrs (k: v: v != null && !(elem k ["type" "query"])) args)
+
// { "${type}" = query; };
+
This section slightly departs from the thinkfan.conf syntax.
+
The type and path must be specified like this:
+
query = "/proc/acpi/ibm/${name}";
+
instead of a single declaration like:
+
- tpacpi: /proc/acpi/ibm/${name}
···
+
Whether to enable thinkfan, a fan control program.
+
This module targets IBM/Lenovo thinkpads by default, for
+
other hardware you will have configure it more carefully.
+
relatedPackages = [ "thinkfan" ];
smartSupport = mkOption {
+
Whether to build thinkfan with S.M.A.R.T. support to read temperatures
directly from hard disks.
+
type = types.listOf (sensorType "sensor");
+
query = "/proc/acpi/ibm/thermal";
+
List of temperature sensors thinkfan will monitor.
+
'' + syntaxNote "thermal";
+
type = types.listOf (sensorType "fan");
+
query = "/proc/acpi/ibm/fan";
+
List of fans thinkfan will control.
+
type = types.listOf levelType;
+
["level auto" 80 32767]
+
LEVEL is the fan level to use: it can be an integer (0-7 with thinkpad_acpi),
+
"level auto" (to keep the default firmware behavior), "level full-speed" or
+
"level disengage" (to run the fan as fast as possible).
+
LOW is the temperature at which to step down to the previous level.
+
HIGH is the temperature at which to step up to the next level.
+
All numbers are integers.
+
type = types.listOf types.str;
+
example = [ "-b" "0" ];
+
A list of extra command line arguments to pass to thinkfan.
+
Check the thinkfan(1) manpage for available arguments.
+
type = types.attrsOf settingsFormat.type;
+
Thinkfan settings. Use this option to configure thinkfan
+
settings not exposed in a NixOS option or to bypass one.
+
Before changing this, read the <literal>thinkfan.conf(5)</literal>
+
manpage and take a look at the example config file at
+
<link xlink:href="https://github.com/vmatare/thinkfan/blob/master/examples/thinkfan.yaml"/>
···
environment.systemPackages = [ thinkfan ];
+
services.thinkfan.settings = mapAttrs (k: v: mkDefault v) {
+
sensors = map sensorToConf cfg.sensors;
+
fans = map sensorToConf cfg.fans;
+
systemd.packages = [ thinkfan ];
+
thinkfan.environment.THINKFAN_ARGS = escapeShellArgs ([ "-c" configFile ] ++ cfg.extraArgs);
+
# must be added manually, see issue #81138
+
thinkfan.wantedBy = [ "multi-user.target" ];
+
thinkfan-wakeup.wantedBy = [ "sleep.target" ];
+
thinkfan-sleep.wantedBy = [ "sleep.target" ];
boot.extraModprobeConfig = "options thinkpad_acpi experimental=1 fan_control=1";