Dankserver's node-exporter has been dead since a reboot: `podman ps -a` showed
it `Exited (143)` and Prometheus' `node-dankserver` job has been scraping
nothing. It ran only from `dankserver/compose.yaml`, which is the failure mode
this repository's boot-persistence rule exists for (rootless Podman does not
restart bare containers after the stop that shutdown performs), and the compose
form bound the wildcard address — the unauthenticated-metrics-API-on-every-
interface posture already removed on Dankclaw.
- dankserver/observability/quadlet/node-exporter.container — mirrors the
Dankclaw unit, listening on exactly 127.0.0.1:9100 (host-local probes) and
192.168.0.235:9100 (Prometheus on Dankclaw), with Restart=always and
WantedBy=default.target.
- the compose service is deleted: one owner per container name.
- deploy_observability now installs from "$TARGET/observability/quadlet"; it
hardcoded the Dankclaw path, so a Dankserver unit could not be installed by
the shared dispatcher at all.
- planner: "node-exporter" joins the Dankserver service set, with a path rule
for dankserver/observability/**; the dispatcher's allowlist gains
dankserver:node-exporter.
Seams cover the silent halves: both listen addresses present and the wildcard
absent, the compose service gone, the allowlist entry present, and the planner
mapping the path to the service.
59 lines
2.5 KiB
INI
59 lines
2.5 KiB
INI
# Quadlet unit: node-exporter (rootless, boot-persistent) — DANKSERVER.
|
|
#
|
|
# Install path on dankserver: ~/.config/containers/systemd/node-exporter.container
|
|
# Unit name: node-exporter.service (container name: node-exporter)
|
|
#
|
|
# WHY THIS FILE EXISTS. Until 2026-09-16 the Dankserver node-exporter ran only
|
|
# from `dankserver/compose.yaml` (the "Observability" block, `restart:
|
|
# unless-stopped`). Rootless Podman does not restart bare containers after the
|
|
# explicit stop that shutdown performs, so it died at a reboot and stayed dead:
|
|
# `podman ps -a` showed it `Exited (143)` and Prometheus' `node-dankserver` job
|
|
# had been scraping nothing since. The compose entry also bound the default
|
|
# wildcard address, which is the unauthenticated-metrics-API-on-every-interface
|
|
# posture that was already removed on Dankclaw. This unit replaces both: one
|
|
# owner per container name (the compose service is deleted), explicit listen
|
|
# addresses, and a generator-provided boot path.
|
|
#
|
|
# HOST NAMESPACE. Networking and PID in the host's namespaces: the collectors
|
|
# report the host's own interfaces, connections, processes and cgroups. The
|
|
# host's /proc, /sys and / are mounted read-only under /host and /rootfs, and
|
|
# node_exporter writes nothing.
|
|
#
|
|
# LISTEN ADDRESSES. Exactly two:
|
|
# - 127.0.0.1:9100 for host-local probes
|
|
# - 192.168.0.235:9100 for Prometheus, which scrapes this host from Dankclaw
|
|
# (shared/prometheus/prometheus.yml, job "node-dankserver"). It cannot use
|
|
# loopback across hosts, and node_exporter has no authentication, so the
|
|
# wildcard bind stays off the table. This is the same deliberate LAN
|
|
# listener posture the observability runbook documents.
|
|
#
|
|
# MIRROR. Keep this file in step with dankclaw/observability/quadlet/
|
|
# node-exporter.container; only the Description and the LAN address differ.
|
|
|
|
[Unit]
|
|
Description=Prometheus node exporter (Dankserver host metrics)
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
|
|
[Container]
|
|
ContainerName=node-exporter
|
|
Image=docker.io/prom/node-exporter:latest
|
|
Network=host
|
|
PodmanArgs=--pid=host
|
|
Exec=--path.procfs=/host/proc --path.sysfs=/host/sys --path.rootfs=/rootfs --web.listen-address=127.0.0.1:9100 --web.listen-address=192.168.0.235:9100
|
|
Volume=/proc:/host/proc:ro
|
|
Volume=/sys:/host/sys:ro
|
|
Volume=/:/rootfs:ro
|
|
HealthCmd=wget --spider -q http://localhost:9100/metrics
|
|
HealthInterval=30s
|
|
HealthTimeout=10s
|
|
HealthRetries=3
|
|
HealthStartPeriod=30s
|
|
|
|
[Service]
|
|
Restart=always
|
|
RestartSec=10
|
|
|
|
[Install]
|
|
WantedBy=default.target
|