feat: implement nixos-exporter
Prometheus exporter for NixOS-specific metrics including: - Generation collector: count, current, booted, age, config mismatch - Flake collector: input age, input info, revision behind Includes NixOS module, flake packaging, and documentation. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
122
module.nix
Normal file
122
module.nix
Normal file
@@ -0,0 +1,122 @@
|
||||
{ self }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.exporters.nixos;
|
||||
in
|
||||
{
|
||||
options.services.prometheus.exporters.nixos = {
|
||||
enable = lib.mkEnableOption "NixOS Prometheus exporter";
|
||||
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 9971;
|
||||
description = "Port to listen on.";
|
||||
};
|
||||
|
||||
listenAddress = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "0.0.0.0";
|
||||
description = "Address to listen on.";
|
||||
};
|
||||
|
||||
flake = {
|
||||
enable = lib.mkEnableOption "flake collector";
|
||||
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = ''
|
||||
Flake URL for revision comparison.
|
||||
Required if flake collector is enabled.
|
||||
'';
|
||||
};
|
||||
|
||||
checkInterval = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "1h";
|
||||
description = "Interval between remote flake checks.";
|
||||
};
|
||||
};
|
||||
|
||||
openFirewall = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Open the firewall for the exporter port.";
|
||||
};
|
||||
|
||||
user = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "nixos-exporter";
|
||||
description = "User to run the exporter as.";
|
||||
};
|
||||
|
||||
group = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "nixos-exporter";
|
||||
description = "Group to run the exporter as.";
|
||||
};
|
||||
|
||||
package = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = self.packages.${pkgs.system}.default;
|
||||
description = "The nixos-exporter package to use.";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.flake.enable -> cfg.flake.url != "";
|
||||
message = "services.prometheus.exporters.nixos.flake.url must be set when flake collector is enabled";
|
||||
}
|
||||
];
|
||||
|
||||
users.users.${cfg.user} = {
|
||||
isSystemUser = true;
|
||||
group = cfg.group;
|
||||
description = "NixOS exporter user";
|
||||
};
|
||||
|
||||
users.groups.${cfg.group} = { };
|
||||
|
||||
systemd.services.prometheus-nixos-exporter = {
|
||||
description = "Prometheus NixOS Exporter";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
ExecStart = lib.concatStringsSep " " ([
|
||||
"${cfg.package}/bin/nixos-exporter"
|
||||
"--listen=${cfg.listenAddress}:${toString cfg.port}"
|
||||
] ++ lib.optionals cfg.flake.enable [
|
||||
"--collector.flake"
|
||||
"--flake.url=${cfg.flake.url}"
|
||||
"--flake.check-interval=${cfg.flake.checkInterval}"
|
||||
]);
|
||||
Restart = "on-failure";
|
||||
RestartSec = "5s";
|
||||
|
||||
# Hardening
|
||||
NoNewPrivileges = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
LockPersonality = true;
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ cfg.port ];
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user