main
1{
2 den,
3 lib,
4 ...
5}: {
6 den.aspects.services.node-exporter = {
7 settings.host = {host, ...}: {
8 address = lib.mkOption {
9 type = lib.types.str;
10 default = let
11 tsIp = host.address.ipv4.tailscale;
12 in
13 if tsIp != null
14 then tsIp
15 else "127.0.0.1";
16 };
17 port = lib.mkOption {
18 type = lib.types.port;
19 default = 9100;
20 };
21 enabledCollectors = lib.mkOption {
22 type = lib.types.listOf lib.types.str;
23 default = [
24 ];
25 };
26 disabledCollectors = lib.mkOption {
27 type = lib.types.listOf lib.types.str;
28 default = [
29 ];
30 };
31 };
32
33 tailscaleGrant = {host, ...}: [
34 {
35 src = let
36 vmIPsList = lib.pipe den.hosts [
37 lib.attrValues
38 lib.mergeAttrsList
39 (lib.filterAttrs (_: {hasAspect, ...}: hasAspect den.aspects.services.victoriametrics))
40 (lib.mapAttrsToList (
41 _: {address, ...}: let
42 v4 = address.ipv4.tailscale;
43 v6 = address.ipv6.tailscale;
44 in
45 lib.optionals (v4 != null) [v4] ++ lib.optionals (v6 != null) [v6]
46 ))
47 lib.concatLists
48 ];
49 in
50 if vmIPsList != []
51 then vmIPsList
52 else ["autogroup:member"];
53 ip = ["tcp:${toString host.settings.services.node-exporter.port}"];
54 }
55 ];
56
57 nixos = {
58 config,
59 host,
60 ...
61 }: let
62 cfg = host.settings.services.node-exporter;
63
64 defaultMountPointsExclude = "^/(dev|proc|run/credentials/.+|sys|var/lib/docker/.+|var/lib/containers/storage/.+)($|/)";
65
66 preservationMountPoints =
67 if !(host.hasAspect den.aspects.disk.preservation)
68 then []
69 else let
70 bindMounts = entries:
71 map (e: e.directory or e.file)
72 (lib.filter (e: (e.how or "bindmount") == "bindmount") entries);
73 stateMountPoints = state:
74 bindMounts (state.directories ++ state.files)
75 ++ lib.concatMap (user: bindMounts (user.directories ++ user.files)) (lib.attrValues state.users);
76 in
77 lib.filter
78 (path: builtins.match "${defaultMountPointsExclude}.*" path == null)
79 (lib.unique (
80 lib.concatMap
81 (prefix: [prefix] ++ stateMountPoints config.preservation.preserveAt.${prefix})
82 (lib.attrNames config.preservation.preserveAt)
83 ));
84
85 mountPointsExclude = lib.concatStringsSep "|" (
86 [defaultMountPointsExclude]
87 ++ map (path: "^${lib.escapeRegex path}($|/)") preservationMountPoints
88 );
89 in {
90 services.prometheus.exporters.node = {
91 enable = true;
92 listenAddress = cfg.address;
93 inherit (cfg) port enabledCollectors disabledCollectors;
94 extraFlags = ["--collector.filesystem.mount-points-exclude=${mountPointsExclude}"];
95 };
96
97 systemd.services.prometheus-node-exporter = {
98 wants = lib.optional (cfg.address == host.address.ipv4.tailscale) "tailscale-wait-online.service";
99 after = lib.optional (cfg.address == host.address.ipv4.tailscale) "tailscale-wait-online.service";
100 };
101 };
102 };
103}