The docs-fact census wave re-read the live hosts and re-keyed every page it could: runtime/payload identities, ports, sizes, ledger figures, unit state, and the retirement banners that drifted as the fleet moved. The wave was interrupted mid-run, so this commit carries only what passed the integrity gates: every touched page parses (front matter or H1+status convention intact, balanced fences, no truncated tables, trailing newline), the docs_completeness and link-integrity seams are green, and bats is 384/384. Numbers that this session proved on live hosts are keyed to the measured value, not the page's earlier claim.
4.6 KiB
type, description, tags, timestamp
| type | description | tags | timestamp | |
|---|---|---|---|---|
| reference | Node-Exporter exposes host metrics (CPU, RAM, disk, network) to Prometheus. |
|
2026-09-11 |
Node-Exporter
Node-Exporter exposes host metrics (CPU, RAM, disk, network) to Prometheus. One instance runs per host, each in its own container.
Hosts: Dankclaw (unit) + Dankserver (unit) — Docs: https://prometheus.io/docs/guides/node-exporter
Both hosts run the same shape as a Quadlet unit: dankclaw/observability/quadlet/node-exporter.container and dankserver/observability/quadlet/node-exporter.container (the compose-only Dankserver copy died for a day and a half before anyone noticed, so it became a unit on 2026-09-16). Both report generated + active on the host and bind their own two addresses (systemctl --user is-enabled|is-active node-exporter, ss -ltnp on dankserver, 2026-10-18); tests/observability_quadlet.bats:419 pins the Dankserver side to a unit, not compose.
Facts
| Item | Value |
|---|---|
| Image | prom/node-exporter:latest |
| Listen addresses | 127.0.0.1:9100 and 192.168.0.143:9100 (Dankclaw, ss -ltnp 2026-10-18; Dankserver binds 127.0.0.1:9100 + 192.168.0.235:9100) |
| Network | Network=host + --pid=host (dankclaw/observability/quadlet/node-exporter.container:37-38) |
| Unit | dankclaw/observability/quadlet/node-exporter.container → node-exporter.service |
| Paths | --path.procfs=/host/proc --path.sysfs=/host/sys --path.rootfs=/rootfs (node-exporter.container:39) |
| Auth | none — it is an unauthenticated metrics endpoint by design |
Why it is the one LAN listener
Every other observability service publishes a port on loopback. This one runs in the host network namespace instead, and netavark DNATs only published ports — so a bridge container cannot reach a host-netns bind at the host's LAN address, and the exporter has to be reachable at an address the consumers can actually dial:
- Prometheus runs in a container on
dankclaw_defaultand scrapeshost.containers.internal:9100(shared/prometheus/prometheus.yml:37-39) — the gateway address netavark delivers a bridge container's host-bound dial to. It does not scrape192.168.0.143:9100; that address is refused by construction from this container, the same rule that sendsfrank-dragoonandfrank-zealotto the gateway.node-dankserveris a different machine, so its LAN address is used (prometheus.yml:41-43). - The homepage status timer runs on the host and probes
127.0.0.1:9100(shared/homepage/services.json:220).
The unit therefore binds exactly those two addresses with two --web.listen-address flags (node-exporter.container:39) — never the wildcard: ss -ltnp (2026-10-18) shows 127.0.0.1:9100 and 192.168.0.143:9100 and nothing else. The LAN bind stays in the unit because LAN machines scrape it directly and the seam test pins it, not because this Prometheus needs it. It has no authentication, so it is never vhosted and never published beyond the LAN.
Mounts
| Container path | Host path |
|---|---|
/host/proc |
/proc (read-only) |
/host/sys |
/sys (read-only) |
/rootfs |
/ (read-only) |
The mount paths and the --path.* flags are a pair: changing one without the other gives an exporter that starts cleanly and reports nothing.
Prometheus Targets
| Host | Target |
|---|---|
| Dankclaw | host.containers.internal:9100 (same-host bridge container → the gateway, prometheus.yml:39; live target http://host.containers.internal:9100/metrics is up, curl -s http://127.0.0.1:9090/api/v1/targets 2026-10-18) |
| Dankserver | 192.168.0.235:9100 |
The scrape jobs live in shared/prometheus/prometheus.yml; see Prometheus. The tests/observability_quadlet.bats seam pins both halves: the unit's two --web.listen-address values (:103-104) and the node-dankclaw target string "host.containers.internal:9100" (:108-131), so the exporter and its only Prometheus consumer cannot drift apart.
Gotchas
- Host networking is required (or a published port); the deploy's health wait probes
127.0.0.1:9100/metrics(scripts/deploy-remote.sh:536) and the unit'sHealthCmdthe same address from inside the host namespace (node-exporter.container:43). - The
/proc,/sysand root mounts must be read-only. - Each host's instance reflects only its own host; do not try to share one.
- Collectors are the image defaults — no per-collector tuning and no textfile collector for custom metrics.
See Also
- Prometheus — the scraper
- Observability — the full stack, including what is still unconfigured