feat(monitoring): collect homelab UPS metrics

This commit is contained in:
Ryan Yin
2026-07-24 12:44:17 +08:00
parent 45f15ec1a0
commit 3550c6af2a
4 changed files with 174 additions and 0 deletions
@@ -71,6 +71,22 @@
}
];
}
{
job_name = "nut-exporter-homelab-ups";
scrape_interval = "30s";
metrics_path = "/ups_metrics";
params.ups = [ "homelab" ];
static_configs = [
{
targets = [ "${myvars.networking.hostsAddr.kubevirt-shushou.ipv4}:9199" ];
labels.type = "app";
labels.app = "nut";
labels.host = "kubevirt-shushou";
labels.env = "homelab";
labels.cluster = "homelab";
}
];
}
{
job_name = "postgres-exporter";
scrape_interval = "30s";
+51
View File
@@ -0,0 +1,51 @@
{ myvars, ... }:
let
hostAddress = myvars.networking.hostsAddr.kubevirt-shushou.ipv4;
in
{
power.ups = {
enable = true;
mode = "standalone";
# Metrics only. Coordinated shutdown of all homelab hosts is a separate feature.
upsmon = {
enable = false;
settings.POWERDOWNFLAG = null;
};
upsd.listen = [
{
address = "127.0.0.1";
port = 3493;
}
];
ups.homelab = {
driver = "nutdrv_qx";
port = "auto";
description = "Homelab UPS";
directives = [
"vendorid = 0665"
"productid = 5161"
];
};
};
services.prometheus.exporters.nut = {
enable = true;
listenAddress = hostAddress;
port = 9199;
nutServer = "127.0.0.1";
# The NixOS module omits --nut.vars_enable when nutVariables is empty, but the exporter needs
# an explicitly empty value to export every numeric NUT variable.
extraFlags = [ "--nut.vars_enable=" ];
};
systemd.services.prometheus-nut-exporter = {
after = [
"upsd.service"
"upsdrv.service"
];
};
}
@@ -0,0 +1,44 @@
{
nut = {
enable = true;
mode = "standalone";
upsmonEnable = false;
killPowerEnable = false;
upsdListen = [
{
address = "127.0.0.1";
port = 3493;
}
];
driver = "nutdrv_qx";
port = "auto";
vendorId = true;
productId = true;
};
exporter = {
enable = true;
listenAddress = "192.168.5.182";
port = 9199;
nutServer = "127.0.0.1";
exportsAllNumericVariables = true;
startsAfterNut = true;
requiresNut = false;
};
victoriametricsJobCount = 1;
victoriametrics = {
job_name = "nut-exporter-homelab-ups";
scrape_interval = "30s";
metrics_path = "/ups_metrics";
params.ups = [ "homelab" ];
target = "192.168.5.182:9199";
labels = {
type = "app";
app = "nut";
host = "kubevirt-shushou";
env = "homelab";
cluster = "homelab";
};
};
}
@@ -0,0 +1,63 @@
{
lib,
outputs,
...
}:
let
shushou = outputs.nixosConfigurations.kubevirt-shushou.config;
aquamarine = outputs.nixosConfigurations.aquamarine.config;
ups = shushou.power.ups.ups.homelab or { };
exporter = shushou.services.prometheus.exporters.nut;
exporterService =
shushou.systemd.services.prometheus-nut-exporter or {
after = [ ];
requires = [ ];
};
scrapeJobs = builtins.filter (
job: (job.job_name or "") == "nut-exporter-homelab-ups"
) aquamarine.services.victoriametrics.prometheusConfig.scrape_configs;
scrapeJob = if builtins.length scrapeJobs == 1 then builtins.head scrapeJobs else null;
in
{
nut = {
enable = shushou.power.ups.enable;
mode = shushou.power.ups.mode;
upsmonEnable = shushou.power.ups.upsmon.enable;
killPowerEnable = shushou.systemd.services.ups-killpower.enable or false;
upsdListen = shushou.power.ups.upsd.listen;
driver = ups.driver or null;
port = ups.port or null;
vendorId = builtins.elem "vendorid = 0665" (ups.directives or [ ]);
productId = builtins.elem "productid = 5161" (ups.directives or [ ]);
};
exporter = {
enable = exporter.enable;
listenAddress = exporter.listenAddress;
port = exporter.port;
nutServer = exporter.nutServer;
exportsAllNumericVariables = builtins.elem "--nut.vars_enable=" exporter.extraFlags;
startsAfterNut =
builtins.elem "upsd.service" exporterService.after
&& builtins.elem "upsdrv.service" exporterService.after;
requiresNut =
builtins.elem "upsd.service" exporterService.requires
&& builtins.elem "upsdrv.service" exporterService.requires;
};
victoriametricsJobCount = builtins.length scrapeJobs;
victoriametrics =
if scrapeJob == null then
null
else
{
inherit (scrapeJob)
job_name
scrape_interval
metrics_path
params
;
target = builtins.head (builtins.head scrapeJob.static_configs).targets;
labels = (builtins.head scrapeJob.static_configs).labels;
};
}