Hardware Health

Watch the physical health of your servers from Monitor → Hardware (keyboard shortcut g h): SMART data from disks, ECC memory errors, temperatures, fans, power supplies and network cards, plus hardware events from the kernel log and the BMC. Available since LogTide 1.7.0, open source.

Prefer a walkthrough? Follow the step-by-step tutorial Monitor a home server's disks, RAM and fans with LogTide.

Overview

Hardware Health is early warning, not prediction. It reads the signals that hardware gives out before it fails (reallocated sectors, corrected memory errors, a fan slowing down, a PCIe link retraining) and turns them into a status per host and per component, with an incident and a notification when something gets worse.

A small agent runs on each server and sends two things to your LogTide project:

  • Metrics named hw.*, sent as OTLP gauges to POST /v1/otlp/metrics.
  • Events from the kernel log and the BMC event log, sent as logs with service hardware.

LogTide registers each host the first time it sees hw.* metrics from it, evaluates it every two minutes and shows the result on Monitor → Hardware. Nothing else is needed: the agent uses the same project API key as your logs.

Disks

HDD, SATA SSD and NVMe: SMART status and attributes, NVMe spare and media errors, wear, temperature.

Memory

Corrected and uncorrected ECC errors per memory controller, read from the kernel EDAC subsystem.

CPU and cooling

CPU temperature against its limits, thermal throttling, and fan speeds from the motherboard or the BMC.

Power and network

PSU status and voltages from the BMC, link flaps and error counters on physical network cards.

What It Can and Cannot See

Keep your backups

SMART does not catch every failing disk. Studies of large disk fleets (Google, Backblaze) found that roughly a third of drives that fail show no SMART warning beforehand. A green status here means no known warning signs, not that the hardware is guaranteed healthy.

  • Bare metal, homelab and on-premises servers are the target. Disks, board sensors, EDAC and a BMC are all visible there.
  • Virtual machines and most cloud instances expose no hardware sensors. The agent detects virtualization and reports it. Such hosts get a VM badge and the status No sensors instead of a health status, and the host page explains that sensors are not available. Run the agent on the hypervisor host, not inside the guests.
  • A host that goes completely dark shows as stale. If no hw.* data point arrives for more than 10 minutes, the host is marked stale. A stale host is shown but does not open an incident. To be told when a machine dies or loses power, pair it with a heartbeat monitor from Uptime that the server pings on a schedule.
  • Not covered in this release: RAID controller tools (MegaCLI, storcli), UPS (NUT), Redfish, per-host custom thresholds, and Windows or macOS hosts.

Requirements

  • LogTide 1.7.0 or later (self-hosted or Cloud) and a project API key.
  • A Linux host. The agent is a single Python 3 script with no dependencies.
  • smartmontools for disk data. Included in the Docker image.
  • ipmitool and a BMC (iDRAC, iLO, IPMI) for PSU, voltage and sensor data from the board. Optional, included in the Docker image.
  • The EDAC kernel modules loaded for ECC memory counters (/sys/devices/system/edac/mc must exist). Needs ECC RAM and a supporting platform.
  • Root or a privileged container, because SMART, IPMI and /dev/kmsg need it. See Permissions.

Each collector is independent. A host without a BMC still reports disks, memory and temperatures; the missing collector is listed as unavailable on the host page.

Install the Agent

Create a project API key first (Project settings → API keys). Use a dedicated key for hardware agents so you can rotate it separately. The examples use the LogTide Cloud API URL; for a self-hosted instance set LOGTIDE_URL to your own API base URL.

The agent lives in its own repository, logtide-dev/logtide-hw-agent (MIT license), and is versioned separately from LogTide. Agent 1.x works with LogTide 1.7.0 and later. The Docker image is logtide/hw-agent.

Docker Compose

If the host that runs LogTide is the machine you want to monitor, enable the hardware profile of the LogTide compose file. Put the key in .env and start the profile:

# docker/.env
HW_AGENT_API_KEY=lp_your_ingestion_key_here

docker compose --profile hardware up -d

If HW_AGENT_API_KEY is empty, FLUENT_BIT_API_KEY is used. With neither set, every request is rejected with 401 while the container still looks healthy. The service is called hw-agent, runs privileged, and talks to the backend over the compose network. Use HW_AGENT_IMAGE to pin a different image.

Standalone Docker

For every other server, run the agent as a single container and point it at your LogTide API with your own URL and key:

docker run -d --name logtide-hw-agent --restart unless-stopped --privileged \
  -e LOGTIDE_URL=https://api.logtide.dev \
  -e LOGTIDE_API_KEY=lp_your_key \
  -e HOST_ROOT=/host \
  -v /sys:/host/sys:ro \
  -v /proc:/host/proc:ro \
  -v /etc/hostname:/host/etc/hostname:ro \
  -v logtide-hw-agent-state:/var/lib/logtide-hw-agent \
  logtide/hw-agent:latest

The mounts and --privileged are explained under Permissions.

systemd

Without Docker, run the single-file agent as a systemd service. The example is for Debian and Ubuntu; install ipmitool only on servers with a BMC.

sudo apt install -y python3 smartmontools ipmitool
sudo install -d /opt/logtide-hw-agent /etc/logtide
sudo curl -fsSL https://raw.githubusercontent.com/logtide-dev/logtide-hw-agent/main/logtide_hw_agent.py \
  -o /opt/logtide-hw-agent/logtide_hw_agent.py
sudo curl -fsSL https://raw.githubusercontent.com/logtide-dev/logtide-hw-agent/main/logtide-hw-agent.service \
  -o /etc/systemd/system/logtide-hw-agent.service
sudo tee /etc/logtide/hw-agent.env >/dev/null <<'ENV'
LOGTIDE_URL=https://api.logtide.dev
LOGTIDE_API_KEY=lp_your_key
ENV
sudo chmod 600 /etc/logtide/hw-agent.env
sudo systemctl daemon-reload
sudo systemctl enable --now logtide-hw-agent

The service runs as root and keeps its state in /var/lib/logtide-hw-agent. Read its log with journalctl -u logtide-hw-agent -f.

Verify

Before leaving the agent running, do a dry run. It collects once, prints the payloads and sends nothing, so you can see which collectors work on this machine:

# Docker
docker run --rm --privileged -e HOST_ROOT=/host -e LOGTIDE_HW_DRY_RUN=1 \
  -v /sys:/host/sys:ro -v /proc:/host/proc:ro -v /etc/hostname:/host/etc/hostname:ro \
  logtide/hw-agent:latest --once

# systemd
sudo sh -c 'set -a; . /etc/logtide/hw-agent.env; LOGTIDE_HW_DRY_RUN=1 python3 /opt/logtide-hw-agent/logtide_hw_agent.py --once'

Without LOGTIDE_HW_DRY_RUN, --once collects, sends one real batch and exits with code 1 if delivery failed. That is the quickest way to test the URL and the key. Then open Monitor → Hardware: the host appears within a minute or two.

Configuration

The agent is configured with environment variables.

Variable Default Description
LOGTIDE_URLrequiredBase URL of the LogTide API, for example http://backend:8080.
LOGTIDE_API_KEYrequiredProject API key, sent as X-API-Key.
LOGTIDE_HOSTNAME$HOST_ROOT/etc/hostname, else the system hostnameValue of host.name, the name shown in Monitor → Hardware.
HOST_ROOTemptyPrefix for /sys, /proc and /etc reads. Set to /host in the container.
LOGTIDE_HW_INTERVAL60Seconds between collections (minimum 5).
LOGTIDE_HW_COLLECTORSallComma-separated list of smart,edac,hwmon,thermal,ipmi,sel,net,kmsg. Use it to switch collectors off.
LOGTIDE_HW_STATE_DIR/var/lib/logtide-hw-agentWhere the last BMC event id is stored.
LOGTIDE_HW_DRY_RUNoff1 prints payloads to stdout instead of sending them.
LOGTIDE_HW_KMSG_PATH/dev/kmsgKernel log device. Only useful for testing.

The command line flag --once runs one collection, sends it and exits. In the compose stack the agent reads HW_AGENT_API_KEY and HW_AGENT_IMAGE from .env.

Permissions

The agent runs as root because SMART queries, /dev/kmsg and /dev/ipmi0 need raw device access. It only reads: it does not write to disks, change fan settings or modify the BMC. In the container, the setup is:

  • /sys and /proc are mounted read-only under /host and read through HOST_ROOT. The container's own /sys/class/net only shows the container's network namespace, so NIC counters would be wrong without the host mount.
  • --privileged gives the container the host's /dev (SATA and NVMe disks, /dev/kmsg, /dev/ipmi0) and the capabilities smartctl needs.
  • The /etc/hostname mount makes the host name match the real host instead of the container id. You can set LOGTIDE_HOSTNAME instead.
  • The state volume keeps the BMC event log position across restarts, so old events are not sent again.

Without --privileged you need --cap-add SYS_RAWIO --cap-add SYS_ADMIN --cap-add SYSLOG plus one --device per disk (/dev/sda, /dev/nvme0), --device /dev/kmsg, and --device /dev/ipmi0 if present. This is more fragile, because seccomp and AppArmor profiles vary between distributions, and privileged is the tested path.

What Is Collected

Every data point carries the attributes host.name, hw.type and hw.id (the device, sensor or controller it belongs to). All metrics are gauges. For disks, hw.id is the drive's serial number (or its /dev/disk/by-id name when there is none), not sda, so a drive keeps its history when the kernel renames it after a reboot; the current kernel name is in the device attribute. Counters such as error totals are sent as the raw cumulative value, and LogTide works on the growth over a window, so a reboot that resets a counter does not look like an improvement or a spike.

Metric Unit Extra attributes Source
hw.host.info1hw.virtual, hw.vendor, hw.model, os.kernel, agent.versionDMI, /proc
hw.agent.collector.status1 / 0collector: smart, edac, hwmon, ipmi, net, thermal, kmsg, selAgent
hw.physical_disk.smart_status1 ok / 0 faileddevice, model, serial, protocol (ata, nvme, scsi)smartctl
hw.physical_disk.smartraw valuesmart_attribute: reallocated_sector_count, current_pending_sector, offline_uncorrectable, reported_uncorrect, udma_crc_error_count, command_timeout, reallocated_event_count, power_on_hourssmartctl (ATA)
hw.physical_disk.endurance_utilization%-NVMe percentage used, ATA wear attributes
hw.physical_disk.available_spare%-NVMe
hw.physical_disk.available_spare_threshold%-NVMe
hw.physical_disk.media_errorscount-NVMe
hw.physical_disk.critical_warningbitmask-NVMe
hw.temperatureCelsensor; hw.type is cpu, physical_disk, memory, board, gpu or otherhwmon, smartctl, ipmitool
hw.temperature.limitCelsensor, limit_type (high, critical)hwmon, ipmitool
hw.fan.speedrpmsensorhwmon, ipmitool
hw.fan.speed.limitrpmsensor, limit_type (low.critical)ipmitool
hw.voltageVsensorhwmon, ipmitool
hw.voltage.limitVsensor, limit_type (low.critical, high.critical, low, high)hwmon, ipmitool
hw.power_supply.status1 / 0sensoripmitool
hw.memory.errorscount (cumulative)error_type (corrected, uncorrected); hw.id is the memory controller or DIMM labelEDAC
hw.memory.sizeBy-/proc/meminfo
hw.cpu.throttle_countcount (cumulative)throttle_type (core, package)sysfs thermal_throttle
hw.network.errorscount (cumulative)direction (receive, transmit), error_type (errors, crc, dropped)sysfs, physical NICs only
hw.network.carrier_changescount (cumulative)-sysfs
hw.network.up1 / 0speed_mbpssysfs

The metrics are ordinary OTLP metrics, so you can also chart them in the Metrics Explorer or with a metric_chart panel on a custom dashboard.

Health Rules

Each host has six components: Disks, Memory, CPU, Cooling, Power and Network. A component is ok, warning, critical or unknown (no data). The host status is the worst of its components, or stale when the host stopped reporting. Every finding on the host page names the component, the device and the value that crossed the threshold.

Component Warning Critical
DisksAny reallocated sector, pending sector or reported uncorrectable error. NVMe media errors grew in 7 days. UDMA CRC errors grew in 24 hours (usually a bad cable). Endurance used at 80% or more. Temperature at 55 C or more for HDD and SATA SSD, 70 C or more for NVMe.SMART overall status failed. Offline uncorrectable sectors above 0. NVMe critical warning set. NVMe available spare below its threshold. Endurance used at 95% or more. Reallocated sectors grew by 10 or more in 7 days. Temperature at 65 C or more for HDD and SATA SSD, 80 C or more for NVMe.
MemoryCorrected ECC errors grew in the last 24 hours.Any uncorrected ECC error since boot or in the last 7 days. Corrected errors grew by 100 or more in 24 hours (a DIMM degrading fast).
CPUTemperature at or above the sensor's high limit. Thermal throttle count grew in 24 hours.Temperature at or above the sensor's critical limit. When a sensor reports no limits, 85 C and 95 C are used.
CoolingA board, memory or other (non-CPU, non-disk) temperature sensor at or above its own high limit.A fan below its low-critical limit, or at 0 rpm after reporting a higher speed in the last 24 hours. A board, memory or other temperature sensor at or above its own critical limit.
PowerA voltage outside its low or high limit.A power supply reporting failure. A voltage outside its low-critical or high-critical limit.
NetworkCRC errors grew in 24 hours. 5 or more carrier changes (link flaps) in 24 hours. 100 or more errors in 24 hours.-

Two more checks raise a component to warning so that a silent failure is not shown as healthy:

  • Missing device. A disk, power supply, fan or network interface that reported in the last 24 hours and is gone from the latest data (disk.missing, power.psu_missing, cooling.fan_missing, network.interface_missing). A dead drive often disappears instead of reporting an error.
  • Collector down. A collector now reports 0 although its component had data in the last 24 hours (agent.collector_down), for example because smartctl started failing. The host page names the collector.
  • Only physical network interfaces are evaluated. Bridges, VLANs, VPNs and container interfaces are ignored.
  • Rules that look at growth need history. Right after you install the agent, growth-based findings can take up to 24 hours (or 7 days for the 7-day rules) to become meaningful.
  • The thresholds are fixed in this release and shared by the backend and the UI. Per-host custom thresholds are not available yet.

Hardware Events

Besides metrics, the agent forwards hardware events as logs:

  • Kernel log. The agent tails /dev/kmsg from the moment it starts (no replay of old messages) and keeps only lines that look like hardware problems: disk I/O errors, ATA link resets, EDAC and machine check messages, PCIe AER errors, thermal throttling, NIC link changes.
  • BMC System Event Log. New entries from ipmitool sel elist are forwarded once. The agent remembers the last entry it sent in its state directory.

Each event is a log with service hardware, the host name as hostname, and metadata hw.event.source (kmsg or sel) and hw.event.type (disk, memory, cpu, pcie, power, thermal, network or other). Kernel lines are at least warnings: priority 0 to 2 is critical, 3 is error, anything else is warning. BMC entries are warnings, and critical when the event mentions an uncorrectable error, a failure or a predictive failure. When the BMC logs that a condition cleared (a Deasserted entry), the event is sent at info level, with hw.sel.direction set to deasserted, and no detection rule fires on it. BMC events also carry hw.sel.id and hw.sel.timestamp. The host page lists the host's events from the last 7 days, newest first, and you can search them in the log explorer by service hardware.

Hardware Health Detection Pack

The Hardware Health Pack is a bundle of 21 Sigma rules, in the new hardware pack category, that match hardware problems in kernel and BMC messages. Open Alerts, choose Detection packs and enable it like any other pack. Its detections show up in the recent detections on the Alerts page.

The rules match on the message text, case-insensitively and whatever the service name, so they fire on agent events and on plain kernel lines that reach LogTide some other way. If you already ship kernel logs through syslog, journald or Fluent Bit, the pack works without the agent; you just do not get the metrics and the host page. The rules carry no MITRE ATT&CK tags, because hardware faults are not attacks.

Area Rule (severity) Matches messages such as
MemoryCorrected memory error (medium), Uncorrected memory error (critical)EDAC lines with CE or UE, BMC Correctable ECC and Uncorrectable ECC
CPUMachine check exception (high), APEI corrected (medium), recoverable (high) and fatal (critical), CPU IERR (critical)mce: [Hardware Error], Machine check events logged, Hardware Error]: with an event severity, BMC IERR
DiskDisk I/O error (high), ATA command failed (high), SATA link reset or down (medium), NVMe timeout or controller down (high), Drive fault from the BMC (high)I/O error, dev, Buffer I/O error, Medium Error, failed command: READ FPDMA, hard resetting link, SATA link down, NVMe timeout and controller is down, Drive Fault
PCIeUncorrected error (high), corrected error (low), PCI parity or system error (high)AER: Uncorrected, AER: Corrected error, BMC PCI PERR and PCI SERR
ThermalCPU thermal throttling (high), critical temperature or threshold (critical)temperature above threshold, cpu clock throttled, critical temperature reached, BMC upper critical thresholds
PowerPower supply fault (high), power supply removed (high)Power supply or PSU with fail, fault or AC lost, redundancy lost, Presence detected | Deasserted
NetworkNIC link down or hang (medium), NIC link not ready (low)NIC Link is Down, Detected Tx Unit Hang, NETDEV WATCHDOG, link is not ready

BMC recoveries are logged as ... | Deasserted. Every rule skips those lines, except Power supply removed, which exists to catch a supply that is no longer present. For general Sigma usage see the security monitoring guide.

Notifications and Incidents

  • When a host gets worse (ok to warning or critical, or warning to critical), LogTide opens or updates an incident with source Hardware in the incidents inbox and sends a notification. A warning maps to medium severity, a critical to critical. There is at most one active hardware incident per host.
  • If the host improves from critical to warning, the incident drops to medium severity and no new notification is sent.
  • When the host returns to ok, the incident is resolved and a recovery notification is sent.
  • The notification uses the Hardware health event type. Choose its destinations (email, Slack, Discord, Teams, PagerDuty, webhook) under Settings → Notifications → Routing, as described in Notification Routing. Without defaults, an email goes to your organization owners and admins when SMTP is configured. Owners and admins also get an in-app notification when a host degrades.
  • Webhook destinations receive hardware.health.degraded and hardware.health.recovered events, see Webhooks. PagerDuty gets one PagerDuty incident per hardware incident, closed on recovery.
  • Mute a host on its detail page while you work on it (organization owners and admins can). A muted host is still evaluated and shown, but opens no incidents and sends no notifications. If it recovers while muted, its open incident is resolved silently.
  • Forget host resolves the host's open incident and removes the host from the list. It comes back by itself if the agent keeps sending data.
  • A stale host does not open an incident. Use a heartbeat monitor for that, see above.

Troubleshooting

No hosts appear

  1. Run the agent once in the foreground (see Verify) and read its output. It reports HTTP errors from LogTide.
  2. Check the URL and key. A 401 means the API key is wrong. The URL is the base URL of your instance, not a path.
  3. Make sure the key belongs to the project you are looking at in the project switcher.
  4. Allow a minute or two. A host is registered on the first batch and evaluated every two minutes.

A collector shows as unavailable

The host page lists every collector with its state. Unavailable means the agent could not run it (if it had been working in the last 24 hours, the host also gets an agent.collector_down warning): smart needs smartctl and privileges to open the devices, ipmi and sel need ipmitool and a BMC device, edac needs ECC memory and the EDAC modules, kmsg needs read access to /dev/kmsg. On hardware without a BMC or without ECC, unavailable is expected.

The host is detected as a virtual machine

The agent reads DMI data and reports hw.virtual. Guests see virtual disks and no sensors, so the host is listed as No sensors with a banner instead of component data. Install the agent on the hypervisor host instead.

NVMe temperatures are missing

NVMe temperatures come from SMART and from the kernel hwmon interface. If they are missing, check that smartctl -a /dev/nvme0 works as root on the host and that your smartmontools is recent enough to support -j JSON output (7.0 or newer).

IPMI permission errors

ipmitool talks to the BMC through /dev/ipmi0, which only root can open, and the ipmi_devintf and ipmi_si kernel modules must be loaded. Run sudo ipmitool sensor on the host: if that fails, the agent will fail too. In a container, make sure the device is passed through.

A host turned stale

No hw.* data for 10 minutes. Check that the agent is running and that the host and LogTide can still reach each other. Stale hosts do not notify; add a heartbeat monitor if you need to know about it.

Esc

Type to search across all documentation pages