Automatically controlling fan speeds on SuperMicro motherboards with IPMI and Python
The Problem
The tiny 2U CPU cooler fans in my server are extremely loud even though the temps are low. None of the default fan curves quiet the fans to an acceptable level. The server uses a Supermicro motherboard, and my specific model lacks any sort of complex fan management from the stock tools.
The Solution
There is a premade solution appropriately called fancontrol. Try this first, it might work on your model of motherboard. Unfortunately this did not work for me as it did not recognize the fans and sensors properly.
Instead, I am going to write a script to automatically ramp the fan speed based on temperature. To do this we need 2 things:
-
The current temperature of the CPU(s)
-
A way to set the fan speed
To knock out the first item, we want to read out the temperatures we want to monitor. Before you
start, you will likely need to load the kernel module for your temperature sensors. You can do this with sensors-detect
from the lm-sensors
package. Make sure to add this to /etc/modules
and load it with modprobe.
Once we have done this, we can read temps. My server
is running Proxmox which is based on Debian, so these temperatures can be read with
cat /sys/class/thermal/thermal_zoneX/temp
where X is a number starting from 0. You will probably only have 1 or 2 of
these zones. First step done!
If you’ve used a Supermicro motherboard in your server(s), you’re probably familiar with IPMI.
It’s a tool we can use to remotely (or locally) manage the motherboard’s hardware from inside
our operating system. For reference, the specific motherboard I have is a Supermicro X9DRH-iTF.
If you don’t already have it, install ipmitools
so we can execute commands.
This tutorial assumes you are executing these commands locally on the host OS of the server.
So first we want to turn off all fan control and keep the fans at maximum speed. To do this we need to use IPMI raw commands. These will likely differ based on your specific motherboard, so do your research. Fortunately a user on reddit documented the commands required for my model.
The command I used to set the fan profile to full is raw 0x30 0x45 0x01 0x02
This ensures that the in-built fan control doesn’t try to override our custom ones.
Then you need to find a command that changes the speed of your CPU fans.
For me, this is ipmitool raw 0x30 0x91 0x5A 0x3 0x10 0xFF
where 0xFF is the speed of the fan
in hex, between 0 and 255 inclusive.
Now we have all the tools we need to automatically control our fan speed. We want to get the max temperature from all zones and convert this to a value between 0 and 1 0, being the lowest target temp, and 1 being the highest. We then want to scale our fan speed between two values based on this number. To do this, I have used python. I will not explain the script in detail but it is pasted at the bottom of this article.
Once I had my script made up, I set it to run on system startup and voila, quiet fans!