Dell SC200
fan control & monitoring.
Control enclosure fans from Linux using temperature curves. Manage multiple enclosures with one daemon, discover serial devices, and monitor cooling in Grafana.
Install sc200
curl -fsSL https://sc200.merkulov.me/install.sh | sudo bashLinux amd64 or arm64 with systemd. Requires curl, GNU tar, sha256sum, and standard account-management tools.
Prometheus metrics. Grafana dashboard.
Track sensor temperatures, measured fan RPM, requested fan speeds, telemetry freshness, and fallback status per enclosure. Scrape /metrics on port 9700 and import the included dashboard.

Discover your enclosures
Interactive setup finds supported enclosures and writes their serial paths and sensor indices. To preview configuration for a known port, stop the daemon and run:
sudo sc200 discover --port /dev/ttyS0 --profile safeAdd --write to save new devices. Existing enclosure settings are preserved. Prefer stable /dev/serial/by-id/… paths when available.
Choose a starting profile
- Safe
- The default: a 20% minimum, a curve from 20% at 25°C to 100% at 45°C, and 100% fallback speed.
- Quiet
- A 10% minimum, a curve from 10% at 25°C to 20% at 45°C, and 15% fallback speed. Select with
--profile quiet.
Both profiles request 100% at the 45°C critical threshold. Profiles generate editable YAML for new devices; tune the values and verify temperatures under sustained load.
Configuration
Edit /etc/sc200/config.yaml and restart the service to apply changes. Defaults below match the Safe profile; Quiet changes min_speed, safe_speed, and curve. In YAML, temperatures and percentages are numbers without unit suffixes; durations use strings such as 10s.
| Field | Default | Purpose |
|---|---|---|
dry_run | false | Read telemetry and log control decisions without writing fan speeds. |
http.listen | 127.0.0.1:9700 | Bind address for Prometheus metrics and health endpoints. Keep loopback unless network access is restricted; endpoints have no authentication. |
shutdown_timeout | 5s | Cleanup deadline supplied to the HTTP server and service manager; serial cleanup can take longer. |
enclosures | Required | List of independently controlled enclosures. At least one must be enabled. |
| Field | Default | Purpose |
|---|---|---|
id | Required | Unique enclosure identifier used in logs, health responses, and metric labels. |
enabled | true | Enable control for this enclosure. Disabled entries are still validated. |
port | Required | Absolute serial-device path. Prefer a stable /dev/serial/by-id/… path. |
baud | 38400 | Serial baud rate; must match the enclosure console. |
poll_interval | 10s | Normal delay between telemetry and control iterations. |
command_timeout | 2s | Time budget for a serial operation. Must be shorter than poll_interval. |
stale_after | 30s | Telemetry age that triggers fallback and reconnection. Must exceed poll_interval + command_timeout. |
refresh_interval | 30s | Resend the current fan target after this interval, even if unchanged. |
reconnect_min | 1s | Initial retry delay after a connection or control failure. |
reconnect_max | 30s | Maximum retry delay; retries double from reconnect_min up to this limit. |
recovery_samples | 3 | Consecutive valid samples required to recover healthy control. Uses safe_speed during recovery. |
min_speed | 20% | Minimum normal fan target. Curve points and safe_speed must be at least this value. |
safe_speed | 100% | Fallback requested on startup, recovery, telemetry faults, or control errors when communication permits. |
critical_temperature | 45°C | Any installed, available sensor at this threshold requests 100% fan speed, including sensors outside required_sensors. |
hysteresis | 2°C | Temperature margin applied when evaluating speed reductions. Increases use the current temperature. |
cooldown | 30s | How long an eligible lower target must stay stable before reducing speed. Increases and emergencies do not wait. |
required_sensors | Auto | Sensor indices used for normal control, taking the hottest reading. If omitted, remembers all initially installed sensors. Discovery writes explicit indices. |
curve | Safe profile | Ordered temperature/speed points, interpolated linearly and rounded up. At least two points; temperatures increase and speeds cannot decrease. |
curve[].temperature | 25, 30, 35, 40, 45°C | Temperature at each curve point. Fractional values are allowed. |
curve[].speed | 20, 30, 50, 75, 100% | Requested fan percentage at each curve point, from min_speed to 100. |