Problema

En muchos homelabs los discos duros se alojan en cajas externas (USB‑DAS, NAS caseros, etc.) sin una ventilación adecuada. Con el tiempo la temperatura de los HDDs supera los 45‑50 °C, lo que reduce la vida útil y provoca throttling. El síntoma típico es un incremento constante de los valores de temperatura reportados por smartctl, ruido de los discos y, en casos extremos, errores de I/O. La solución no es simplemente comprar un nuevo chasis; se necesita un método reproducible para monitorizar la temperatura, avisar cuando supera umbrales seguros y actuar añadiendo ventilación o ajustando la carga.

Causa

  1. Flujo de aire insuficiente: Las cajas USB‑DAS suelen ser compactas y carecen de ventiladores internos. Cuando se apilan varios discos, el calor se acumula.
  2. Ubicación del chasis: Colocar la caja en un armario cerrado o cerca de otros equipos genera un micro‑clima caliente.
  3. Carga de I/O constante: Servicios como Plex, Sonarr o qBittorrent mantienen los discos activos, aumentando la generación de calor.
  4. Firmware de los discos: Algunos HDDs (p.ej., WD Red Pro) elevan la temperatura de operación bajo carga pesada y no reducen la velocidad del ventilador interno.
  5. Falta de alertas: Sin un agente de monitoreo, el administrador solo nota el problema cuando el disco falla.

Solución

Una solución modular basada en Docker permite escalar y reutilizarla en cualquier homelab:

  1. Instalar smartmontools dentro de un contenedor ligero.
  2. Crear un script Bash que consulte smartctl -A /dev/sdX para extraer el atributo Temperature_Celsius.
  3. Definir umbrales (p.ej., warning = 45 °C, critical = 55 °C).
  4. Publicar métricas a Prometheus (o a cualquier endpoint HTTP) usando node_exporter o textfile collector.
  5. Configurar alertas en Uptime Kuma, Grafana o Beszel para que envíen notificaciones por Telegram/Discord.
  6. Automatizar la ventilación: conectar ventiladores de 12 V a un controlador PWM (por ejemplo, un controlador basado en Raspberry Pi GPIO) y exponer una API que el script invoque cuando la temperatura cruce el umbral crítico.
  7. Desplegar todo con Docker‑Compose para que el stack sea reproducible y fácil de versionar.

Arquitectura resumida

[Docker host] ──► smartctl container ──► Prometheus (scrape) ──► Grafana alerting
                     │
                     └─► Bash monitor ──► HTTP API del controlador PWM

Cuándo aplicar esta solución

  • Síntomas: lecturas de smartctl > 45 °C, discos que se calientan al tacto, caídas de rendimiento bajo carga.
  • Entornos: cualquier homelab con discos externos, NAS DIY o servidores de medios que ejecuten contenedores Docker.
  • No aplicable: cuando los discos ya están en racks con refrigeración activa certificada o cuando se usa SSD exclusivamente (los SSD también pueden monitorizarse, pero el patrón de sobrecalentamiento es distinto).

Código

#!/usr/bin/env bash
# monitor_hdd_temp.sh
# Requiere smartmontools y curl
# Configuración de umbrales
WARN=45
CRIT=55
API_URL="http://192.168.1.100:5000/fan"   # endpoint del controlador PWM

# Lista de discos a monitorizar (ajustar según el host)
DISKS=(/dev/sda /dev/sdb)

for DEV in "${DISKS[@]}"; do
    TEMP=$(smartctl -A "$DEV" | awk '/Temperature_Celsius/ {print $10}')
    if [[ -z "$TEMP" ]]; then
        echo "No se pudo leer temperatura de $DEV"
        continue
    fi

    if (( TEMP >= CRIT )); then
        curl -s -X POST "$API_URL" -d '{"speed":100}'
        echo "$(date) - $DEV: $TEMP°C (CRITICAL) → fans max"
    elif (( TEMP >= WARN )); then
        curl -s -X POST "$API_URL" -d '{"speed":60}'
        echo "$(date) - $DEV: $TEMP°C (WARNING) → fans medium"
    else
        curl -s -X POST "$API_URL" -d '{"speed":20}'
        echo "$(date) - $DEV: $TEMP°C (OK) → fans low"
    fi
done

Guarda el script en ./monitor_hdd_temp.sh, hazlo ejecutable (chmod +x) y añádelo a docker-compose.yml como un servicio de tipo cron (por ejemplo, usando crazymax/cron).

version: "3.8"
services:
  hdd-monitor:
    image: alpine:latest
    container_name: hdd-monitor
    volumes:
      - /dev:/dev   # acceso a los discos
      - ./monitor_hdd_temp.sh:/usr/local/bin/monitor_hdd_temp.sh:ro
    entrypoint: ["crond", "-f", "-L", "/dev/stdout"]
    environment:
      - CRON_SCHEDULE=*/5 * * * * /usr/local/bin/monitor_hdd_temp.sh

Verificación

  1. Comprobar salida del script: docker logs hdd-monitor debe mostrar la temperatura y la velocidad enviada al controlador.
  2. Validar API del controlador: usar curl http://192.168.1.100:5000/fan/status y confirmar que el PWM refleja el último valor.
  3. Observar la temperatura: ejecutar smartctl -A /dev/sda antes y después de forzar una carga (p.ej., copiar un archivo grande) y verificar que la velocidad del ventilador aumenta.
  4. Revisar alertas: generar una condición crítica (elevar la temperatura manualmente con stress) y confirmar que Uptime Kuma envía la notificación configurada.

Notas adicionales

  • Controlador PWM: una placa basada en Raspberry Pi con pigpio permite cambiar el duty cycle mediante una petición HTTP simple. Existen proyectos como rpi-fan-controller que ya exponen /fan como endpoint.
  • Persistencia de datos: el contenedor necesita acceso directo a /dev; asegúrate de que el host no tenga políticas de seguridad que lo bloqueen.
  • Escalabilidad: si gestionas más de 8 discos, considera agruparlos en grupos lógicos y crear métricas por grupo en Prometheus para evitar sobresaturar el endpoint.
  • Seguridad: protege el endpoint del controlador con token o autenticación básica, especialmente si la red no está aislada.
  • Alternativas: si prefieres no usar PWM, simplemente coloca ventiladores USB alimentados por un hub con control de velocidad por software (p.ej., fancontrol de lm-sensors).

Con este enfoque tienes una cadena completa: detección → alerta → acción automática. La arquitectura basada en contenedores permite replicar la solución en cualquier servidor homelab, manteniendo los discos en rangos seguros y prolongando su vida útil sin necesidad de invertir en chasis costosos.