refactor(nut): merge prometheus exporter into nut role

- exporter gated by nut_prometheus_exporter_enabled
- env-file config (correct NUT_EXPORTER_* vars + --web.listen-address)
- remove standalone nut_exporter role
This commit is contained in:
Clément Désiles
2026-09-05 17:24:12 +02:00
parent 12b81919c3
commit 5218fa2714
14 changed files with 88 additions and 151 deletions
+24 -3
View File
@@ -82,7 +82,28 @@ journalctl -u nut-monitor -u nut-server -u 'nut-driver@*' -f
- udev rules shipped by the `nut` package grant USB device access to the `nut`
group only.
## Companion role
## Prometheus exporter
See [`nut_exporter`](../nut_exporter/README.md) to expose Prometheus metrics
based on the same upsd instance.
Optionally exposes UPS metrics for Prometheus via `prometheus-nut-exporter`
(AUR, Arch-only). Enable it:
```yaml
nut_prometheus_exporter_enabled: true
```
The exporter reuses `nut_monitor_password`, binds to
`{{ nut_prometheus_exporter_listen_address }}` (default `127.0.0.1:9199`) and
serves UPS metrics on `/ups_metrics`. Pair it with a Prometheus scrape job:
```yaml
prometheus_scrape_configs:
- job_name: 'nut'
metrics_path: /ups_metrics
static_configs:
- targets: ['127.0.0.1:9199']
```
```bash
systemctl status prometheus-nut-exporter
curl -s 'http://127.0.0.1:9199/ups_metrics' | head
```
+9 -2
View File
@@ -5,7 +5,7 @@
# UPS definition
# --------------
# Logical name of the UPS as referenced everywhere (ups.conf section, upsmon
# MONITOR line, nut_exporter ?ups= query parameter).
# MONITOR line, exporter ?ups= query parameter).
nut_ups_name: eaton
# Human-readable description (shown in upsc output).
@@ -33,7 +33,7 @@ nut_ups_maxretry: 3
nut_upsd_listen:
- { addr: "127.0.0.1", port: 3493 }
# Local monitor user used by upsmon and nut_exporter. Password must be set.
# Local monitor user used by upsmon and the Prometheus exporter. Password must be set.
nut_monitor_user: monitor
# nut_monitor_password: "" # Intentionally undefined - role will fail if not set
@@ -66,3 +66,10 @@ nut_notify_script_path: /usr/local/bin/ups-notify
# ONLINE notification can report total outage duration. Lives under /run so it
# is cleared on reboot (stale outage state is meaningless after a reboot).
nut_outage_state_file: /run/ups-notify-outage
# Prometheus exporter (optional)
# ------------------------------
nut_prometheus_exporter_enabled: false
nut_prometheus_exporter_listen_address: "127.0.0.1:9199"
nut_prometheus_exporter_nut_server: "127.0.0.1:3493"
nut_prometheus_exporter_nut_user: "{{ nut_monitor_user }}"
+9
View File
@@ -13,3 +13,12 @@
ansible.builtin.systemd:
name: nut-monitor.service
state: restarted
- name: Reload systemd
ansible.builtin.systemd:
daemon_reload: true
- name: Restart NUT exporter
ansible.builtin.systemd:
name: "{{ nut_prometheus_exporter_service }}"
state: restarted
+32
View File
@@ -0,0 +1,32 @@
---
# Prometheus NUT exporter (optional, gated by nut_prometheus_exporter_enabled).
# Installs prometheus-nut-exporter (AUR) and points it at the local upsd via
# the unit's EnvironmentFile (/etc/conf.d/prometheus-nut-exporter).
- name: Install prometheus-nut-exporter (AUR via paru)
ansible.builtin.command: "paru -S --noconfirm --needed {{ nut_prometheus_exporter_package }}"
register: _nut_prometheus_exporter_install
changed_when: "'there is nothing to do' not in _nut_prometheus_exporter_install.stdout | lower"
when: ansible_facts['os_family'] == 'Archlinux'
- name: Remove legacy exporter systemd override
ansible.builtin.file:
path: "/etc/systemd/system/{{ nut_prometheus_exporter_service }}.service.d"
state: absent
notify: Reload systemd
- name: Deploy exporter environment file
ansible.builtin.template:
src: nut-exporter-env.conf.j2
dest: "{{ nut_prometheus_exporter_env_file }}"
owner: root
group: root
mode: "0600"
notify: Restart NUT exporter
- name: Enable and start exporter
ansible.builtin.systemd:
name: "{{ nut_prometheus_exporter_service }}"
enabled: true
state: started
daemon_reload: true
+4
View File
@@ -95,3 +95,7 @@
enabled: true
state: started
loop: "{{ nut_services }}"
- name: Deploy Prometheus NUT exporter
ansible.builtin.include_tasks: exporter.yml
when: nut_prometheus_exporter_enabled | bool
@@ -0,0 +1,5 @@
# Managed by Ansible - DO NOT EDIT MANUALLY
# EnvironmentFile for prometheus-nut-exporter (read by the systemd unit via
# $NUT_EXPORTER_ARGS). The password has no flag, so it is passed as an env var.
NUT_EXPORTER_ARGS="--web.listen-address={{ nut_prometheus_exporter_listen_address }} --nut.server={{ nut_prometheus_exporter_nut_server.split(':')[0] }} --nut.serverport={{ nut_prometheus_exporter_nut_server.split(':')[1] }} --nut.username={{ nut_prometheus_exporter_nut_user }}"
NUT_EXPORTER_PASSWORD="{{ nut_monitor_password }}"
+5
View File
@@ -7,3 +7,8 @@ nut_services:
- nut-driver-enumerator.service
- nut-server.service
- nut-monitor.service
# Prometheus exporter (AUR)
nut_prometheus_exporter_package: prometheus-nut-exporter
nut_prometheus_exporter_service: prometheus-nut-exporter
nut_prometheus_exporter_env_file: /etc/conf.d/prometheus-nut-exporter