Fan control daemon for TrueNAS SCALE with Netdata metrics
Project description
truefan
Fan control daemon for TrueNAS SCALE systems on Supermicro X11 boards. Takes over fan control from the BMC so you can tune noise vs. cooling to your environment. Reads temperatures from IPMI, SMART, NVMe, and lm-sensors, then sets fan duty cycles via IPMI raw commands. Metrics go to Netdata via statsd.
Features
- Auto-detection of sensors and fans — classifies by type (cpu, drive, nvme, ambient, other) and applies per-class interpolation curves.
- Self-calibrating — learns each fan's setpoint table by ramping duty down and recording RPMs. Can be recalibrated as fans age or collect dust.
- Failsafe — fans go to 100% on crash, total sensor class failure, or stalled fan. The watchdog parent restarts the daemon automatically.
- Config validation — startup, reload, and the
checkcommand validate config syntax, values, and hardware match before touching any fans. - Syslog logging — the daemon logs to syslog;
truefan logswraps journalctl for easy access. - Netdata metrics — per-sensor temperature and thermal load, per-zone duty, per-fan target RPM, daemon uptime, and restart count via statsd. Optional alert configs included.
Requirements
- Python 3.11+
ipmitoolsmartctl(smartmontools) — for SATA/SAS drive tempsnvme-cli— for NVMe tempslm-sensors— for kernel-exposed sensors- Supermicro X11 motherboard with IPMI
Install
TrueNAS SCALE doesn't ship ensurepip, so create the venv without it and
bootstrap pip manually:
python3 -m venv --without-pip /mnt/pool1/venvs/truefan
source /mnt/pool1/venvs/truefan/bin/activate
curl -sS https://bootstrap.pypa.io/get-pip.py | python3
pip install truefan
Put the venv on a pool — the boot drive is wiped on OS updates.
Quick start
# Detect sensors, calibrate fans, write config
# (ramps fans up and down for a few minutes)
sudo truefan init
# Start the daemon (daemonizes and returns immediately)
sudo truefan start
# Check if it's running
truefan status
# Show detected sensors and current readings
truefan sensors
# Follow daemon logs
truefan logs -f
# Reload config without restarting
sudo truefan reload
# Re-calibrate after cleaning or replacing fans
sudo truefan recalibrate
# Stop the daemon
sudo truefan stop
To get Netdata dashboards and alerts, install the bundled configs:
truefan netdata install
Use truefan netdata uninstall to remove them. Use truefan netdata check to verify
configs are up to date.
Configuration
truefan init generates a truefan.toml with sensible defaults. Example:
poll_interval_seconds = 15
spindown_window_seconds = 180
[thermal.class.drive]
no_cooling_temp = 30
max_cooling_temp = 45
fan_zones = ["peripheral"]
# Per-sensor overrides for components that run hotter than their class
[thermal.sensor.lmsensors_mlx5_pci_0200_sensor0]
no_cooling_temp = 60
max_cooling_temp = 95
# Learned via calibration — duty % = expected RPM
[fans.FAN1]
zone = "cpu"
[fans.FAN1.setpoints]
25 = 320
30 = 450
40 = 620
50 = 780
100 = 1500
Use --config PATH with any command to specify an alternate config location.
Running on boot
TrueNAS SCALE's Init/Shutdown Scripts (under System > Advanced) run commands at boot and shutdown.
Add a script (Type: Command, When: Post Init):
/mnt/pool1/venvs/truefan/bin/truefan start
No tmux or nohup needed — start forks into the background on its own.
Use truefan logs -f to follow output and truefan status to check if
it's running.
How it works
Each sensor class has a temperature-to-duty curve. Between no_cooling_temp
and max_cooling_temp, duty is linearly interpolated from 0% to 100%;
hardware-reported thermal limits override max_cooling_temp when available.
The hottest sensor in each fan zone sets the duty, which is then snapped to
the nearest calibrated fan setpoint. A spindown window prevents rapid cycling.
If a fan stalls, the zone goes to 100% and the lowest setpoint is removed so the minimum duty rises going forward.
Send SIGUSR1 to dump current sensor readings, thermal loads, and zone
duties to syslog (kill -USR1 $(cat /var/run/truefan.pid); view with
truefan logs).
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file truefan-1.4.0.tar.gz.
File metadata
- Download URL: truefan-1.4.0.tar.gz
- Upload date:
- Size: 80.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d8608626cbe26a71cfa511585f159b85e3e874276bcddae9c2f9b4a1ddbc66f2
|
|
| MD5 |
5bf954e03d8f520cb25a8d7f1c9ad5f8
|
|
| BLAKE2b-256 |
1babf3ea72e063235f8f7ac682d376ae1bcce08a39b548aa9a6e4c8be08950fd
|
Provenance
The following attestation bundles were made for truefan-1.4.0.tar.gz:
Publisher:
ci.yml on zvea/truefan
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
truefan-1.4.0.tar.gz -
Subject digest:
d8608626cbe26a71cfa511585f159b85e3e874276bcddae9c2f9b4a1ddbc66f2 - Sigstore transparency entry: 1240905861
- Sigstore integration time:
-
Permalink:
zvea/truefan@b6b206ec3784a55666689bb47c5d30af23f665b3 -
Branch / Tag:
refs/tags/v1.4.0 - Owner: https://github.com/zvea
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@b6b206ec3784a55666689bb47c5d30af23f665b3 -
Trigger Event:
push
-
Statement type:
File details
Details for the file truefan-1.4.0-py3-none-any.whl.
File metadata
- Download URL: truefan-1.4.0-py3-none-any.whl
- Upload date:
- Size: 43.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0260fb6ad8dac69bad51bc0d57e8135af43970f77b03e4ecc2652d18ca48a3d9
|
|
| MD5 |
27c11ad5d786a82cc43597013603e8bb
|
|
| BLAKE2b-256 |
ca01fb54a5f72171a2152d4bb8b322eede49f82de6687058c6edfeca03fe0030
|
Provenance
The following attestation bundles were made for truefan-1.4.0-py3-none-any.whl:
Publisher:
ci.yml on zvea/truefan
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
truefan-1.4.0-py3-none-any.whl -
Subject digest:
0260fb6ad8dac69bad51bc0d57e8135af43970f77b03e4ecc2652d18ca48a3d9 - Sigstore transparency entry: 1240906080
- Sigstore integration time:
-
Permalink:
zvea/truefan@b6b206ec3784a55666689bb47c5d30af23f665b3 -
Branch / Tag:
refs/tags/v1.4.0 - Owner: https://github.com/zvea
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@b6b206ec3784a55666689bb47c5d30af23f665b3 -
Trigger Event:
push
-
Statement type: