The hottest fan controller for your server
An intelligent fan controller for Dell PowerEdge servers with simple threshold-based control, hysteresis to prevent oscillation, and a workload hints API for proactive cooling.
- Multi-source Monitoring β CPU temps via IPMI, GPU temps via nvidia-smi
- Simple Threshold Control β Set CPU and GPU temperature thresholds, fans increase when exceeded
- Hysteresis β Configurable cooldown delay prevents fan oscillation at threshold boundaries
- Workload Hints API β External scripts can signal upcoming load for proactive cooling
- Web Dashboard β Real-time temps, fan speeds, and threshold visualization
- Constant Idle Speed β Quiet operation when temps are below thresholds
# Clone the repo
git clone https://github.com/sethpjohnson/only-fan-controller
cd only-fan-controller
# Copy and edit config
cp config.example.yaml config.yaml
nano config.yaml
# Run with docker-compose
docker-compose up -ddocker run -d \
--name only-fan-controller \
--restart unless-stopped \
--gpus all \
-e NVIDIA_VISIBLE_DEVICES=all \
-p 8086:8086 \
-v ./config.yaml:/etc/only-fan-controller/config.yaml:ro \
-v ./data:/var/lib/only-fan-controller \
only-fan-controller:latest- Idle State: Fans run at
idle_speed(default 20%) when both CPU and GPU are below their thresholds - Threshold Exceeded: When CPU >
cpu_thresholdOR GPU >gpu_threshold, fans increase bystep_sizeper 5Β°C over - Cooldown: Fans only ramp down after staying below thresholds for
cooldown_delayseconds (prevents oscillation) - Workload Hints: External scripts can set a minimum fan speed floor via the API
Access the dashboard at http://your-server:8086/dashboard/
Shows:
- CPU temperatures (all cores)
- GPU temperatures (all GPUs)
- Current fan speed and mode
- Temperature history graph with threshold lines
- Active workload hints
Returns current system state including thresholds:
{
"cpu": { "Temps": [33, 34], "Max": 34 },
"gpu": { "Devices": [{"name": "Tesla P40", "temp": 42}], "Max": 42 },
"current_speed": 20,
"zone": "idle",
"cpu_threshold": 65,
"gpu_threshold": 60,
"idle_speed": 20
}Register a workload hint for proactive cooling:
# Signal high GPU load starting (sets minimum fan speed to 45%)
curl -X POST http://localhost:8086/api/hint \
-H "Content-Type: application/json" \
-d '{
"type": "gpu_load",
"action": "start",
"intensity": "high",
"source": "whisper-transcription"
}'
# Signal work complete (removes the floor)
curl -X POST http://localhost:8086/api/hint \
-H "Content-Type: application/json" \
-d '{
"type": "gpu_load",
"action": "stop",
"source": "whisper-transcription"
}'Intensity levels:
lowβ 25% minimum fan speedmediumβ 35% minimum fan speedhighβ 45% minimum fan speed
Set a manual fan speed override:
curl -X POST http://localhost:8086/api/override \
-H "Content-Type: application/json" \
-d '{"speed": 50, "duration": 300, "reason": "testing"}'Clear manual override and return to automatic control.
Get temperature/fan history for graphing.
See config.example.yaml for all options.
fan_control:
idle_speed: 20 # Base fan speed when cool (%)
cpu_threshold: 65 # Increase fans when CPU exceeds this (Β°C)
gpu_threshold: 60 # Increase fans when GPU exceeds this (Β°C)
step_size: 10 # Fan increase per 5Β°C over threshold (%)
cooldown_delay: 60 # Seconds below threshold before ramping downfan_control:
idle_speed: 15 # Very quiet
cpu_threshold: 70 # Higher threshold for quieter operation
gpu_threshold: 65
cooldown_delay: 120 # Wait 2 minutes before ramping downfan_control:
idle_speed: 25 # Slightly higher baseline
cpu_threshold: 60 # More aggressive cooling
gpu_threshold: 55
cooldown_delay: 30 # Faster responseWrap your GPU-intensive scripts to automatically manage cooling:
#!/bin/bash
# transcribe-with-cooling.sh
CONTROLLER_URL="http://localhost:8086"
# Signal GPU work starting
curl -s -X POST "$CONTROLLER_URL/api/hint" \
-H "Content-Type: application/json" \
-d '{"type":"gpu_load","action":"start","intensity":"high","source":"whisper"}'
# Wait for fans to ramp up
sleep 3
# Do the actual work
whisper --model large-v3 "$1"
# Signal complete
curl -s -X POST "$CONTROLLER_URL/api/hint" \
-H "Content-Type: application/json" \
-d '{"type":"gpu_load","action":"stop","source":"whisper"}'All config options can be overridden via environment variables:
| Variable | Description | Default |
|---|---|---|
IDRAC_HOST |
iDRAC IP or "local" | from config |
IDRAC_USERNAME |
iDRAC username | root |
IDRAC_PASSWORD |
iDRAC password | - |
GPU_ENABLED |
Enable GPU monitoring | true |
FAN_IDLE_SPEED |
Base fan speed (%) | 20 |
FAN_CPU_THRESHOLD |
CPU temp threshold (Β°C) | 65 |
FAN_GPU_THRESHOLD |
GPU temp threshold (Β°C) | 60 |
CHECK_INTERVAL |
Seconds between checks | 10 |
API_PORT |
API/Dashboard port | 8086 |
- Copy
unraid/only-fan-controller.xmlto/boot/config/plugins/dockerMan/templates-user/ - Configure via the Unraid Docker UI
- Or use Community Applications (search "Only Fan Controller")
- Dell PowerEdge server with iDRAC (tested on R730)
- iDRAC firmware with IPMI support
- For local mode:
/dev/ipmi0device access - For remote mode: IPMI over LAN enabled in iDRAC settings
- For GPU monitoring: NVIDIA drivers and
nvidia-smi
# Build binary
go build -o only-fan-controller ./cmd/controller
# Build Docker image
docker build -t only-fan-controller .MIT
Inspired by tigerblue77/Dell_iDRAC_fan_controller_Docker