adam d41e3838d5 Add per-enclosure temperature metrics + Home Assistant MQTT publisher
- enclosure: fetch SES element descriptor page (0x07) and label temp/fan/
  psu/voltage elements with human-readable names
- temps service + /api/temps: per-enclosure hotspot (max across SES sensors
  and housed drive temps) plus named SES sensor list
- mqtt_publisher: paho-mqtt with HA discovery (device per enclosure, hotspot
  + per-sensor entities), LWT availability, opt-in via MQTT_HOST
- secrets: OpenBao KV v2 reader; MQTT creds sourced from secret/home_assistant
  with env fallback
- compose/requirements/README updated
2026-06-16 04:45:32 +00:00

JBOD Monitor

REST API for monitoring drive health in JBOD enclosures on Linux.

Auto-discovers SES enclosures via sysfs, maps drives to physical slots, and exposes SMART health data.

Prerequisites

  • Linux with SAS/SATA JBODs connected via HBA
  • smartmontools — for smartctl (SMART data)
  • sg3-utils — for sg_ses (SES enclosure data)
  • Python 3.11+
# Debian/Ubuntu
apt install smartmontools sg3-utils

# RHEL/Fedora
dnf install smartmontools sg3_utils

Install

pip install -r requirements.txt

Run

The API needs root access for smartctl to query drives:

sudo uvicorn main:app --host 0.0.0.0 --port 8000

API Endpoints

Endpoint Description
GET /api/health Service health + tool availability
GET /api/enclosures List all discovered SES enclosures
GET /api/enclosures/{id}/drives List drive slots for an enclosure
GET /api/drives/{device} SMART detail for a block device
GET /api/overview Aggregate enclosure + drive health
GET /api/temps Per-enclosure temperatures: named SES sensors + hotspot
GET /docs Interactive API docs (Swagger UI)

Home Assistant (MQTT)

The monitor can publish per-enclosure temperatures to Home Assistant over MQTT using HA discovery — no HA YAML required. Each enclosure becomes a device with:

  • a Hotspot sensor — the hottest reading across all SES temperature sensors and the drives housed in that enclosure (drive temps are usually the real hotspot); drive_max_c and drive_temp_count are exposed as attributes.
  • one sensor per named SES temperature element (e.g. Temp Inlet, Temp Outlet), labelled from the SES element descriptor page.

Publishing is opt-in: set MQTT_HOST to enable it.

Variable Default Description
MQTT_HOST (unset) Broker host. Unset → MQTT disabled.
MQTT_PORT 1883 Broker port
MQTT_USERNAME / MQTT_PASSWORD (unset) Broker credentials (fallback if OpenBao unused/unavailable)
MQTT_DISCOVERY_PREFIX homeassistant HA discovery topic prefix
MQTT_BASE_TOPIC jbod-monitor State/availability topic root
MQTT_PUBLISH_INTERVAL 60 Seconds between publishes
MQTT_NODE_ID (hostname) Stable id for this monitor (disambiguates multiple hosts)
MQTT_CLIENT_ID jbod-monitor-<node> MQTT client id

Credentials via OpenBao

Broker credentials are sourced from OpenBao at startup rather than stored in plaintext (matching the homelab runtime-secret pattern). Set MQTT_SECRET_PATH to a KV v2 path holding username/password; the app reads <OPENBAO_ADDR>/v1/<OPENBAO_MOUNT>/data/<MQTT_SECRET_PATH> with the token from OPENBAO_TOKEN_FILE (or OPENBAO_TOKEN). If the read fails, it falls back to the MQTT_USERNAME/MQTT_PASSWORD env vars.

Variable Default Description
MQTT_SECRET_PATH (unset) KV v2 path holding the broker creds (e.g. home_assistant). Unset → use env creds.
MQTT_SECRET_USER_KEY username Key within the secret for the broker username
MQTT_SECRET_PASS_KEY password Key within the secret for the broker password
OPENBAO_ADDR https://vault.adamksmith.xyz OpenBao API base URL
OPENBAO_MOUNT secret KV v2 mount point
OPENBAO_TOKEN_FILE (unset) Path to a file containing the OpenBao token (preferred; mount read-only)
OPENBAO_TOKEN (unset) OpenBao token (used if no token file)

The deployed compose reads the broker user/pass from secret/home_assistant (keys mqtt_user/mqtt_pass) using the read-only claude-read token mounted at /run/secrets/openbao-token.

Topics (defaults):

homeassistant/sensor/<node>_enc<id>/hotspot/config   # retained discovery
homeassistant/sensor/<node>_enc<id>/temp<n>/config    # retained discovery
jbod-monitor/<node>/status                            # online | offline (LWT)
jbod-monitor/<node>/enclosure/<id>/state              # {"hotspot_c":42.0, "sensor_0":28.5, ...}

Availability is tracked via an MQTT LWT, so entities show unavailable in HA if the monitor stops.

Description
REST API for monitoring drive health in JBOD enclosures on Linux
Readme 380 KiB
Languages
Python 58.8%
JavaScript 39.6%
Dockerfile 0.9%
Shell 0.4%
HTML 0.3%