smartctl_exporter turns S.M.A.R.T. data into Prometheus metrics, and refuses to fix what smartctl gets wrong
Export smartctl statistics to prometheus
At a glance
- What is it?
- prometheus-community/smartctl_exporter is a Go exporter that polls smartctl on a schedule and publishes drive health attributes as Prometheus metrics, with device auto scanning, include and exclude filters, a power mode check, TLS and basic authentication, and container images for amd64 and arm64. Its stated policy is that it does not modify the data in flight, so a wrong number is a smartmontools bug, not an exporter bug.
- Who is it for?
- Use smartctl_exporter if you run Prometheus and want disk health attributes, reallocated sector counts and temperature as metrics rather than as a page of smartctl output. Do not use it to work around a smartctl parsing bug, because the project explicitly refuses those fixes, and note that it needs smartmontools 7.0 or newer for the JSON output it depends on.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 9 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A pull based exporter for drive health, not a disk dashboard
smartctl_exporter exports smartctl statistics to Prometheus. That is the whole product, and the design follows directly from what smartctl gives you.
The dependency is smartmontools 7.0 or newer, and the reason is specific: the JSON export was released in 7.0. The exporter shells out to the smartctl binary, reads its JSON, and turns the S.M.A.R.T. attributes into Prometheus metrics. The path to the binary is configurable and defaults to /usr/sbin/smartctl.
The data flow is worth being precise about, because the project documents it carefully. The exporter polls smartctl on an interval, which defaults to 60 seconds, and separately rescans for new or disappeared devices every 10 minutes. It publishes on a metrics endpoint, by default /metrics, listening on port 9633.
The important property is that the exporter does not modify the data in flight. The documentation states that the smartctl_exporter should not modify the data in flight, and that if the data is missing from smartctl it should not be in smartctl_exporter, and if the data from smartctl is incorrect it should be reported upstream to smartmontools. Requests for the exporter to fix incorrect data where smartctl is reporting incorrect data will be closed.
That is an unusual and clarifying position for an exporter to take, and it is the main thing to understand before you adopt it. It is a translator, not a corrector.
The audience is operators running Prometheus who want disk health visible next to everything else, rather than in a terminal or a separate disk monitoring web interface.
The flags decide whether you scan or you list
The command line surface is the configuration, and the most important decision is whether the exporter discovers drives itself or you tell it what to watch.
If no --smartctl.device flags are used, the exporter scans the system for available devices. Scanning is also the default when no devices are specified, and it can be turned on explicitly with --smartctl.scan. When devices are configured explicitly, the documentation says no rescanning takes place, and there is a second condition: if the rescan interval is smaller than one second, no rescanning takes place either.
So the default behaviour is discovery with a periodic rescan, and pinning a device list switches off the rescan path entirely. That trade matters in a virtualised or containerised environment where disks come and go, and in a storage chassis where a controller rebuild changes the device path.
The explicit form supports a device type after a semicolon, for example /dev/bus/0;megaraid,1, and the flag is repeatable. Two regexp flags filter what automatic scanning picks up: --smartctl.device-exclude and --smartctl.device-include, which the help text describes as mutually exclusive to one another.
There is also a device type setting for the scan itself, --smartctl.scan-device-type, which is repeatable, and the help notes that a special by-id value forces predictable device names. That is a small detail with a large effect in fleets, where /dev/sdX ordering is not stable.
The remaining flags are operational. --smartctl.powermode-check controls whether the power mode is checked before fetching data, with a default of standby, which matters for spinning disks that are spun down. --smartctl.interval is the poll interval and --smartctl.rescan is the device rescan interval. On the web side there is --web.telemetry-path, --web.listen-address, and --web.systemd-socket for systemd socket activation on Linux, plus logging flags for level and format.
Scanning, filtering and the by-id device name problem
The device filter logic has its own file in the repository, device_filter.go, with a matching test file, which tells you it is treated as a first class piece of behaviour rather than an afterthought.
The mechanics are described in the flags. Automatic scanning finds candidate devices, the include and exclude regexps decide which of them are kept, and the scan device type setting decides what the exporter asks smartctl to scan. The by-id special value is worth dwelling on, because it is the difference between a metric that identifies a disk and a metric that identifies a slot.
On a machine with several disks, the kernel device names can be reassigned across reboots or when a controller re-enumerates the bus. If the exporter labels the series by /dev/sda, then a metric history can silently start referring to a different physical disk, and a dashboard that has been tracking a failing drive for six months can end up pointing at a healthy one. Forcing by-id names makes the series label follow the disk rather than the enumeration order.
The same reasoning explains the semicolon syntax for explicit devices. A RAID controller exposes many logical drives behind one device, so the exporter needs to say which one it wants, and the megaraid example in the help text is exactly that case.
The troubleshooting section also documents how to get data out for a bug report. There is a collection script, scripts/collect-smartctl-json.sh, which exports all drives to a smartctl-data directory created in the current directory, and the project asks for redacted JSON files to be contributed as pull requests for unique drives and edge cases. The repository includes a redact_fake_json.py helper, which suggests the redaction is a scripted step rather than a manual one.
The rest of the source tree is small and legible for a Go project: main.go for the command line wiring, smartctl.go for the mapping from attributes to metrics, metrics.go for the metric definitions, smartctlinfo.go for device discovery, readjson.go and gjsonext.go for parsing, and a systemd/ directory for the socket activation pieces.
The data in flight rule, and the table that tells you where a bug lives
The troubleshooting section is the most useful part of this documentation, because it defines the boundary between the exporter and smartmontools instead of blurring it.
The rule is stated three times in slightly different ways. The exporter should not modify the data in flight. If the data is missing from smartctl, it should not be in smartctl_exporter. If the data from smartctl is incorrect, it should be reported upstream to smartmontools.
Then there is a table that turns the rule into a diagnostic. It crosses the state of the smartctl output, valid, missing, or invalid and incorrect, with the state of the exporter output. The cells read: all good for valid data from both, an issue for smartctl_exporter when the exporter reports missing or invalid data from valid smartctl output, report upstream to smartmontools when smartctl is missing or invalid, and a combined case when the exporter is invalid and smartctl is missing.
The grey area is spelled out too. When invalid or missing data from smartctl causes multiple invalid or incorrect values in the exporter, which can happen if the data is used in a calculation for other data, that has to be researched case by case.
This matters operationally because drive health metrics are alerting inputs. A pipeline that rounds or guesses a reallocated sector count produces alerts that are wrong in both directions, and the specific direction that matters is a disk that is failing and not alerting. The documentation also points at how to trace a metric back to its source: the S.M.A.R.T. attributes are mapped in smartctl.go, each mapping function carries the metric name as its first parameter, and metrics.go shows how the exporter displays the information. The text says this sounds technical but is crucial for understanding how data flows from smartctl to the exporter to Prometheus, which is the right way to think about an exporter that refuses to massage its input.
The container runs as root and needs privileged, and that is not an accident
The example Docker Compose file is minimal, and the two settings in it that would raise an eyebrow are the two that matter.
version: "3"
services:
smartctl-exporter:
image: prometheuscommunity/smartctl-exporter
privileged: true
user: root
ports:
- "9633:9633"The image is prometheuscommunity/smartctl-exporter from Quay, the port is 9633, and the service is marked privileged and runs as root. Both of those are there for the same reason: smartctl talks to disks directly, and on most systems that means raw device access, which a container cannot do without elevated privileges. The exporter is not doing anything unusual with those privileges, it is passing them through so the smartctl call can succeed.
That is a real trade-off for anyone deploying this. A privileged container with raw device access is a significant privilege on a host, and the alternative is to grant specific device access to a less privileged container, which the compose example does not do.
The Dockerfile itself is more restrained. It is based on alpine:3, it installs smartmontools with apk, it copies the statically built binary from the build directory, it exposes port 9633, and it ends with USER nobody. So the final image runs the exporter process as an unprivileged user, which is the right default. The privileged flag in the compose example is a property of the container configuration rather than of the image, and the image can be run with a more careful device mapping by anyone who needs to.
The Makefile shows how the images are produced, with DOCKER_ARCHS defaulting to amd64 and arm64, the Docker repository defaulting to prometheuscommunity, and the image name set to smartctl-exporter. The Go module targets Go 1.26.0, and the runtime dependencies are the Prometheus client library, kingpin for the command line, the exporter toolkit for the web configuration, and gjson for parsing the smartctl JSON.
TLS and basic authentication through the shared exporter toolkit
The exporter supports TLS and basic authentication, and the mechanism is the shared one used across Prometheus exporters rather than something built here.
You pass a configuration file with --web.config.file, and the format of that file is described in the exporter-toolkit repository, which is a dependency of this project at version 0.20.0. The same toolkit also provides the web configuration types that the other flags reference.
Two details are worth noting. First, the configuration file path defaults to empty, so the metrics endpoint is unauthenticated and unencrypted unless you supply one. Second, the listening address flag is repeatable, with examples given for a plain host and port, for an IPv6 loopback address, and for a vsock address, which points at virtual machine workloads rather than physical hosts.
The telemetry path flag is separate from the listen address, and it defaults to /metrics, so the exporter can be bound to an internal interface and served on a path that suits your reverse proxy.
The systemd socket activation option is Linux only, and it exists so the exporter can be started by systemd as a socket-activated unit rather than binding a port itself. There is a systemd/ directory in the repository holding those units.
The logging flags are the last piece of the operational surface. --log.level takes one of debug, info, warn or error, and --log.format selects logfmt or json, which is what you want when the logs are shipped into a structured pipeline rather than read by a person on a terminal.
Apache 2.0, a community project, and a steady release line
The licence is Apache 2.0, and the project sits in the prometheus-community organisation, with the maintainers listed in a MAINTAINERS.md file at the root and a SECURITY.md file alongside it.
The release history shows a project that ships steadily. The tags are v0.15.0 from 2026-09-01, v0.14.0 from 2025-04-22 and v0.13.0 from 2024-12-20, and the v0.15.0 tag carries a release note naming the version and the date, which is the pattern of a project that tags with the changelog entry already written. The repository is not archived and the last push was on 2026-10-14.
The gap between v0.13.0 in December 2024 and v0.14.0 in April 2025 is four months, and the one between v0.14.0 and v0.15.0 is longer, which is normal for an exporter that only needs to be cut when smartmontools output changes or a new metric is wanted.
The feature request policy in the README is worth knowing before you file anything. The project asks for additional metrics to be requested by describing the metric and attaching an exported smartctl JSON file, and it says that if you need more you should get in touch. In other words, the acceptance bar for a new metric is a real sample of the output that shows the attribute is present and useful.
That policy is consistent with the rest of the project. A new metric is a permanent addition to somebody's Prometheus schema, and the maintainers are asking for evidence from real devices, which is exactly what the collection script and the redacted JSON contribution flow are for.
Editorial conclusion
Use smartctl_exporter if you run Prometheus and want disk health attributes, reallocated sector counts and temperature as metrics rather than as a page of smartctl output. Do not use it to work around a smartctl parsing bug, because the project explicitly refuses those fixes, and note that it needs smartmontools 7.0 or newer for the JSON output it depends on. Before deploying, confirm smartctl runs on your hardware, decide between automatic scanning and an explicit device list since mixing them disables rescanning, and set --web.config.file if the metrics endpoint should not be open to the network.
Frequently asked questions
What does smartctl_exporter do and who is it for?
It exports smartctl statistics to Prometheus, turning drive health attributes into metrics on a /metrics endpoint. It is meant for operators who already run Prometheus and want disk health next to their other metrics rather than in a separate monitoring tool.
What are the requirements for smartctl_exporter?
smartmontools 7.0 or newer, because the exporter relies on the JSON output that was released in 7.0. The path to the smartctl binary defaults to /usr/sbin/smartctl and is configurable with the smartctl.path flag.
Should I use automatic device scanning or explicit devices in smartctl_exporter?
With no device flags the exporter scans the system and rescans for new or disappeared devices every 10 minutes by default. If you configure devices explicitly, no rescanning takes place, and rescanning is also disabled if the rescan interval is under one second.
Does smartctl_exporter fix bad data from smartctl?
No, by policy. The documentation says the exporter should not modify the data in flight, that missing data in smartctl should not appear in the exporter, and that requests to fix incorrect data where smartctl reports incorrect data will be closed. Such issues are reported upstream to smartmontools.
How do I enable TLS and basic authentication in smartctl_exporter?
Pass a configuration file with the web.config.file flag, whose format is defined in the prometheus/exporter-toolkit repository. The exporter supports TLS and basic authentication, and the metrics endpoint is unauthenticated by default.
Why does the smartctl_exporter Docker Compose example run privileged and as root?
Because smartctl needs raw access to the disks, which a container cannot get without elevated privileges. The image itself ends with USER nobody, so the privilege comes from the container configuration in the compose example rather than from the image.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/prometheus-community-smartctl-exporter)Was this useful?