Monitor LSI / Broadcom SAS Host Bus Adapters (HBAs) directly from Unraid — temperature, PHY health, attached drives, SMART, the firmware event log, and real-time performance graphs — across four controller generations, with the correct backend auto-detected per card. An optional, opt-in firmware/BIOS update tab is available for users who need it.
Inspired by DevlinDelFuego for the SAS2308 / 9207-8i. This was a project I had been working on for a while with a similar capability but extends it to SAS3 (9300) and SAS3.5 tri-mode (9400) controllers and multi-controller systems since I have SAS3 HBAs. I wanted something that had metrics and firmware/bios flashing capability so I had a bunch of scripts but didn't know how to tie it together cleanly until I saw Devlin's program.
The plugin detects the controller generation and uses the right tool automatically:
| Generation | Chipsets | Cards (examples) | Backend |
|---|---|---|---|
| SAS2 (6 Gb/s) | SAS2004 / 2008 / 2108 / 2116 / 2208 / 2308 | 9207-8i, 9211-8i, IBM M1015, Dell H200/H310 | lsiutil (bundled) |
| SAS3 (12 Gb/s) | SAS3004 / 3008 / 3108 / 3216 / 3224 / 3316 | 9300-8i, 9305-16i, 9361-8i | storcli (system-installed) |
| SAS3.5 / tri-mode | SAS3408 / 3416 / 3508 / 3516 / 3616 / 3808 / 3816 | 9400-16i, 9400-8i, 9500 series | storcli (system-installed) |
| SAS4 / tri-mode (24 Gb/s) | SAS4016 / 4024 / 4116 | 9600-16i, 9600-24i, eHBA 9600 series | storcli2 (system-installed) |
Multiple controllers are shown side by side. Both SAS and SATA drives are supported.
SAS3 and later need a Broadcom CLI installed on the system — proprietary, so none of them are bundled here. SAS3 / SAS3.5 use
storcli; SAS4 / 9600 cards useStorCLI2, which is a different program rather than a newer version of the same one — the classicstorclicannot see a 9600 at all and reports zero controllers next to one. The storcli plugin by dkaser (search "storcli" in Community Applications) ships both. SAS2 cards use the bundledlsiutiland need nothing extra.9600-series support has not been run against real hardware in this repo. It was ported from techanonymous's
Unraid-HBAviewer-sas4fork (MIT), whose author verified it on their own 9600-24i — that is not the same claim as this repo having tested it. See issue #19.Per that verification, on a 9600-24i in eHBA personality the kernel registers no SAS transport class at all, which constrains three things:
- Locate and the Array Map are unavailable. Both key on SAS addresses, which the card does not publish to the kernel.
- The Performance tab's link-error series reads as unmeasured, not zero. That poll only touches instant sources, and the counters are not among them there. PHY Health does show them — it can afford to ask the controller.
- The Event Log needs Broadcom's full StorCLI2. The Lite build that the dkaser plugin ships answers that command with "Un-supported command", and the tab says so rather than showing an empty table that would read like a healthy log. See Installation for the optional full build.
- Overview — per-controller temperature gauge with a configurable alert
threshold, plus a real health rollup (goes yellow/red on high temp, a
failed drive, or PHY errors — not just heat). Shows chip, firmware, BIOS,
driver version, IT/IR mode, connected-drive count, and PCIe info. Pre-P20
SAS2 firmware is flagged; cards with no onboard sensor show
N/A · no sensorinstead of erroring. - HBA Health — five independent indicators (thermal, link integrity, topology, host link, controller read) with a worst-of rollup and a reason string naming the offending PHY. An indicator that cannot be measured reads grey/unknown, never green — a collector that times out or a card that is pulled must not look healthy.
- PHY Health — per-PHY link state, negotiated speed, attached SAS address,
and error counters (invalid DWords, disparity, loss-of-sync, reset) — read
from the controller (lsiutil) or from Linux
sysfs(mpt3sas) on SAS3/3.5. Set a baseline per controller and every counter is then shown as a delta and an errors/hour rate, so "40,000 invalid DWords two months ago" stops looking like "40,000 last night". The baseline lives on/bootand survives reboots; a reboot or driver reload invalidates it rather than reporting a negative delta. - Top offenders — above the PHY table, the PHYs with the highest error rate
since the baseline, each named by the drive it serves (enclosure/slot, or
/dev/sdXon SAS2). PHYs with no baseline are excluded rather than ranked at zero — zero would read as "measured and clean" when it means "never measured". - Attached Drives —
/devname, what Unraid calls the disk (Parity,Disk 1,Cache), enclosure/slot, HBA port, model, serial, state, size, SAS address, link speed, firmware, and a per-drive SMART button. The/devname and the Unraid slot appear on the PHY and SMART tables too, so a row here can be matched against the Main page without trackingsdXby eye. - Array Map — a grid of the physical bays, arranged the way they sit in
the chassis, so a problem drive is a place you can walk to rather than a slot
number. You place each drive once — drag it into its bay, or click the drive
then the bay — and the layout is saved to
/boot; lock it when you are done so a stray click cannot undo it. Copy map puts the layout on your clipboard so it can live somewhere other than the flash drive, Restore map rebuilds it from that text, and Undo covers a mistaken Clear or resize. Colour is the signal: bays stay neutral until something needs attention, a temperature bar makes a hot row visible without reading every number, empty bays are drawn as empty bays, and a disk being rebuilt into parity shows as such. Nothing on the machine knows your chassis layout — on a direct-attach backplane the enclosure/slot addressing is invented by the controller — so this is the one thing the plugin cannot work out for you. - Locate a drive — blink one drive's activity light from the Drives table or a bay on the Array Map, so a row becomes a bay you can walk to. Needs no SES, no enclosure processor and no GPIO — it works by reading the drive twice a second, so anything with a tray light can be found, including plain HBAs on dumb backplanes. Stops itself after five minutes so a forgotten blink cannot keep a disk awake indefinitely.
- SMART tab — health, temperature, grown defects, pending sectors, and power-on hours for every drive, collected in the background so it never blocks the UI and (on SAS) never spins up a standby drive. The collection is kept until you press Refresh rather than expiring on a timer — reading every drive takes ~1 s each and the numbers change over weeks — and every screen that shows it states how old it is.
- Event Log — the firmware event log, archived to
/bootso history survives reboots and firmware ring-buffer wrap, with copy-to-clipboard for support tickets. - Enclosure / topology — an enclosure summary per controller (direct-attach vs expander/backplane).
- Dashboard tile — at-a-glance temperature and health on the Unraid dashboard (Unraid 7.2+).
- Notifications (opt-in, off by default) — sends one Unraid notification each time a controller's health status changes, and never repeats while it stays the same. Delivery follows your existing Unraid notification settings.
- Diagnostic bundle — one button collects the raw
storcli/lsiutiloutput, the sysfs state and the plugin's own parsed JSON into a single archive for a bug report. Anonymised by default with one length-preserving map for the whole bundle, so serials, WWNs, SAS addresses and the hostname are replaced while models, sizes, firmware versions, temperatures and error counters stay real. Your flash GUID, licence key and share names are never collected at all. - Export / API — a read-only JSON snapshot of every controller
(
/plugins/hbaviewer/export.php) plus the same data in Prometheus text format (?format=prometheus), for Homepage-style widgets and dashboards. Both are session-gated, so an unauthenticated Prometheus scraper cannot poll them — see HOWTO.md. - Performance graphs (real-time, in-browser) — live per-controller
throughput, IOPS, %util, latency, PHY error-rate, and temperature, sampled
~2 s from
/proc/diskstatsandsysfs(zero-dependency — no sampler daemon, no flash writes; history lives in the browser and resets on reload). - Firmware / BIOS Update (advanced, opt-in, off by default) — an assisted flash page that detects the card + running firmware, runs a read-only per-card sanity check, takes your model-correct image, and flashes that one card behind hard guardrails with a live log. See the safety section below.
All monitoring data is read directly from the HBA (storcli / lsiutil),
Linux sysfs, and smartctl — no agents, no polling daemons, no external calls.
⚠ Flashing HBA firmware can permanently brick your controller. This feature is off by default and is for users who already know how to flash an LSI/Broadcom HBA from a console. If you are not sure, do not enable it.
HBAviewer is otherwise strictly read-only. The optional Firmware/BIOS Update tab is assisted, not automatic: it detects the card and runs the tools, but you supply the model-correct firmware image and (if not already installed) the flash tool.
Enabling it: Settings → Advanced — Firmware Flashing → tick Enable firmware/BIOS flashing → Save. A red Firmware/BIOS Update button then appears at the bottom of that same Settings page, and is the only way in — the Monitor does not link to it. Reaching the one screen that writes to hardware means coming back past the warning that explains what it costs to get wrong.
How a flash works, per card:
- Verify — a read-only listing scoped to that one card (
storcli /cN showorsasNflash -c N -list) confirms the tool sees the exact card you're about to flash. - Choose the image — the exact firmware
.bin/.romfor your model (optionally a BIOS.rom). There is no upload button: you copy the files into/boot/config/plugins/hbaviewer/flashyourself and the page offers what it finds there. Thesas2flash/sas3flashbinary goes in the same folder if it isn't already inPATH. - Confirm & flash — tick the acknowledgement, type
FLASH, and flash. A live log streams; on success it prompts you to reboot.
A dual-controller board is one card, and is flashed as one. A SAS9300-16i is
a single board carrying two SAS3008 controllers, so the page shows it as one
entry — Controller /c0, /c1 — and the flash writes both in sequence from
the one image you selected. Only that card's own controllers are written, never
every controller in the box. If the second write fails after the first
succeeded, the page raises a distinct partial flash banner telling you not to
reboot and to re-run the flash for the whole card; see
HOWTO.md.
Tools used (auto-detected in PATH, or drop them in the flash folder — none
are bundled):
| Generation | Chip | Flash tool |
|---|---|---|
| SAS2 (9200/9211/2308) | SAS2xxx |
sas2flash |
| SAS3 (9300/9305) | SAS30xx/SAS31xx |
sas3flash |
| SAS3.5 / 9400 tri-mode | SAS34xx/SAS35xx |
storcli /cN download |
Guardrails (all enforced server-side, not just in the browser):
- Opt-in toggle gates the whole feature (default off).
- The Unraid array must be STOPPED — the flash is refused otherwise.
- Read-only verify first, scoped to the target card, so you flash the card you actually confirmed — not another HBA in the box.
- The controllers you name must be one of this server's cards, re-derived from the live hardware at flash time — half of a dual-IOC board is refused, and so is any list that is not a card.
- Explicit acknowledgement checkbox and a typed
FLASHconfirmation. - Single-flight lock — one flash at a time, never auto-retried.
- Filenames are sanitised and confined to the fixed flash folder.
Caveats — read these:
- Bricking is a real, unavoidable risk if the image doesn't match the card. Double-check the model/chip against the image before you flash.
- The flash tools are proprietary and per-generation — not shipped with the
plugin. Install them (e.g. via a storcli/flash plugin) or copy them into
/boot/config/plugins/hbaviewer/flashyourself. - Some SAS2 cards need a specific
sas2flashbuild (e.g. a 9207-8i wants the P14 tool). Use the right one; the plugin won't second-guess it. - storcli 94xx flashing semantics vary by firmware package (a downrev may need
noverchk); the log is shown verbatim — treat it as best-effort. - Linux flashers update the BIOS region but cannot erase it.
- Stop any Unassigned Devices on the HBA as well before flashing.
| Document | What it covers |
|---|---|
| HOWTO.md | Task-oriented guide — install, first run, finding the drive behind a failing PHY, mapping your drive bays, baselines, the export endpoint, generating a bug-report bundle, and troubleshooting. |
| ARCHITECTURE.md | How the plugin is built — backend selection, the parse layer, request lifecycle, caching, the mutating paths, and the test strategy. Read this before changing code. |
source/.../CONTEXT.md |
Module vocabulary — the short definitions the code assumes you already know. |
- Unraid 6.12 or newer (7.2+ for the dashboard tile)
- A supported LSI / Broadcom SAS controller (see the table above)
- For SAS3 / SAS3.5 cards:
storcliinstalled — easiest via the dkaser/unraid-storcli plugin (search "storcli" in Community Applications) - For SAS4 / 9600 cards:
StorCLI2installed — a different program fromstorcli, not a newer one. The same dkaser plugin ships it, but only its Lite build; the firmware Event Log needs Broadcom's full StorCLI2, which is optional and installed by hand — see Installation. smartctl(ships with Unraid) for the SMART features- The
lsiutilbinary for SAS2 cards is bundled in the.txz— nothing extra is downloaded
-
In the Unraid web UI go to Plugins → Install Plugin
-
Paste the plugin URL:
https://raw.githubusercontent.com/FugginOld/Unraid-HBAviewer/main/hbaviewer.plg -
Click Install
If you have a SAS3 or newer card, install the Broadcom CLI it needs — search
"storcli" in Community Applications and install
dkaser's storcli plugin; it ships
both storcli and storcli2 and puts them on PATH, which is all this plugin
needs — it probes for whichever one can actually read your card rather than
guessing from the name.
That covers every tab on a SAS4 / 9600 card except the firmware Event
Log, because the storcli2 build the dkaser plugin ships is the
feature-reduced Lite one. If you want the Event Log too, install Broadcom's
full StorCLI2 as well — it cannot be redistributed here (proprietary) or
fetched automatically (its download page is JavaScript-driven behind bot
protection, with no stable direct URL), so you fetch the archive yourself:
-
Download StorCLI2 from Broadcom and copy the
.ziponto the server — any share will do. -
On the server (Unraid terminal or SSH — not your desktop), run:
bash /usr/local/emhttp/plugins/hbaviewer/scripts/install_storcli2.sh /path/to/StorCLI2.zip
It unpacks the archive (a
.deb,.rpmor a bare binary work too), checks the binary really is StorCLI2, copies it to/boot/config/plugins/hbaviewer/tools/so it survives a reboot, and adds three lines to/boot/config/gothat restore it at boot —/optis RAM here and the flash is FAT32, so it cannot keep the execute bit. It backsgoup first, is safe to re-run, and takes--no-goif you would rather do that part yourself.Settings → HBA Connection → Firmware Event Log shows these same steps and whether the full build is currently installed.
After installation, find the monitor under Tools → HBAviewer → HBA Monitor.
Tools
└── HBAviewer
└── HBA Monitor (tabs: Overview · HBA Health · PHY Health · Drives
· Array Map · SMART · Event Log · Performance)
User Utilities
└── HBAviewer (full settings page)
└── HBAviewer Firmware (Firmware/BIOS Update*)
*opt-in, off by default; the page and its menu entry
only exist once it is enabled
Dashboard
└── HBA Temperature tile (Unraid 7.2+)
Open User Utilities → HBAviewer. The settings page opens instantly and shows
the detected Access Method (StorCLI2, storcli or lsiutil) so you can
confirm the right backend is in use before opening the Monitor.
| Setting | Default | Description |
|---|---|---|
| Access Method | (auto) | Read-only. Shows which backend is in use — StorCLI2 (SAS4), storcli (SAS3/3.5) or lsiutil (SAS2) — and warns if a card is found but the tool it needs isn't installed. |
| lsiutil Port (fallback) | 1 | SAS2 only — every card lsiutil lists is read automatically, so this normally does nothing. It names the one port to fall back to if that list cannot be read. Only shown if SAS2 cards are detected. |
| Alert Threshold | 80 °C | The badge turns red (ALERT) at or above this temperature. |
| Show PCIe Info | On | PCIe width/speed row in the Overview. |
| Show PHY Health | On | PHY tab. |
| Show Attached Drives | On | Drives tab. |
| Show Event Log | On | Event Log tab. |
| Show Performance | On | Performance tab — real-time throughput / IOPS / %util / latency / PHY-error-rate / temperature graphs (in-browser, resets on reload). |
| Enable notifications | Off | Sends an Unraid notification when a controller's health status changes (checked every 10 minutes). One notification per change, never a repeat while it persists. |
| Enable firmware/BIOS flashing | Off | Advanced. Unlocks the Firmware/BIOS Update page and the button that reaches it. Read the firmware section before enabling — flashing can brick a card. |
The drive bay map deliberately has no row on this page. Its grid size and its lock live with the map itself (the Array Map tab), because a layout is something you build while looking at it, not a number you set on one page and go check on another. They are still persisted the same way everything else here is.
Save your settings, then click Open HBAviewer Monitor. The Monitor page opens immediately with a "Loading HBA information" banner and reads the hardware in the background — the first read can take up to a minute on slow controllers, and the page fills in automatically when it's ready (no blank hang, no timeout).
git clone https://github.com/FugginOld/Unraid-HBAviewer.git
cd Unraid-HBAviewer
# Fetch the lsiutil binary and build the .txz (see build.sh for details)
bash build.sh
# build.sh prints the MD5 and version to update in hbaviewer.plgThe bundled hbaviewer.x86_64 is the original lsiutil v1.70 compiled for Linux
x86-64. storcli is not bundled — SAS3/3.5 cards use the copy installed on
your system. build.sh also fetches Chart.js (the Performance tab's charting
library, MIT) into the plugin dir; like the lsiutil binary it isn't committed
to the repo. The Performance tab degrades gracefully with a message if it's absent.
The shell parsers and PHP helpers have a golden-file test suite that needs no hardware:
bash tests/run.shIt runs the parser goldens plus the PHP unit tests (using a local php, or the
php:8.2-cli Docker image if php isn't installed), and needs GNU awk.
CI additionally syntax-checks every language the plugin ships — php -l,
bash -n, node --check — and runs ShellCheck, PHPStan and actionlint on top.
Fixtures are real controller output wherever possible — captured with the
scripts/capture*.sh helpers or contributed by reporters on the issue tracker,
with identifiers masked length-preservingly so column alignment (which the
parsers key on) survives. A fixture that was modelled by hand rather than
captured has caused a real bug here before, so treat fixtures as evidence
rather than as editable test data.
- DevlinDelFuego — Unraid-LSIUtil — the original Unraid plugin this repo (Unraid-HBAviewer) is inspired on.
- Thomas Lovell — LSIUtil — the
lsiutilbinary that makes the SAS2 path possible. - Broadcom —
storcli(SAS3 / SAS3.5),StorCLI2(SAS4 / 9600) and the originallsiutilsource. - dkaser — unraid-storcli — the easiest way to get either Broadcom CLI onto Unraid.
- techanonymous — Unraid-HBAviewer-sas4
(MIT, commit
882f88c) — the SAS4 / 9600-series backend and its StorCLI2 installer, verified against real 9600 hardware and ported into this repo.
Thanks to the early users (in no particular order) @jac2424, @PaliKinG3, @iassis, @t0ffemannen to help fix and troubleshoot the early release bugs.
MIT — see LICENSE for details.