1{
2 config,
3 lib,
4 pkgs,
5 options,
6 ...
7}:
8
9let
10 cfg = config.services.prometheus.exporters.wireguard;
11 inherit (lib)
12 mkOption
13 types
14 mkRenamedOptionModule
15 mkEnableOption
16 optionalString
17 escapeShellArg
18 concatStringsSep
19 concatMapStringsSep
20 ;
21in
22{
23 port = 9586;
24 imports = [
25 (mkRenamedOptionModule [ "addr" ] [ "listenAddress" ])
26 {
27 options.warnings = options.warnings;
28 options.assertions = options.assertions;
29 }
30 ];
31 extraOpts = {
32 verbose = mkEnableOption "verbose logging mode for prometheus-wireguard-exporter";
33
34 wireguardConfig = mkOption {
35 type = with types; nullOr (either path str);
36 default = null;
37
38 description = ''
39 Path to the Wireguard Config to
40 [add the peer's name to the stats of a peer](https://github.com/MindFlavor/prometheus_wireguard_exporter/tree/2.0.0#usage).
41
42 Please note that `networking.wg-quick` is required for this feature
43 as `networking.wireguard` uses
44 {manpage}`wg(8)`
45 to set the peers up.
46 '';
47 };
48
49 interfaces = mkOption {
50 type = types.listOf types.str;
51 default = [ ];
52 description = ''
53 Specifies the interface(s) passed to the wg show <interface> dump parameter.
54 By default all interfaces are used.
55 '';
56 };
57
58 singleSubnetPerField = mkOption {
59 type = types.bool;
60 default = false;
61 description = ''
62 By default, all allowed IPs and subnets are comma-separated in the
63 `allowed_ips` field. With this option enabled,
64 a single IP and subnet will be listed in fields like `allowed_ip_0`,
65 `allowed_ip_1` and so on.
66 '';
67 };
68
69 withRemoteIp = mkOption {
70 type = types.bool;
71 default = false;
72 description = ''
73 Whether or not the remote IP of a WireGuard peer should be exposed via prometheus.
74 '';
75 };
76
77 latestHandshakeDelay = mkOption {
78 type = types.bool;
79 default = false;
80 description = ''
81 Adds the `wireguard_latest_handshake_delay_seconds` metric that automatically calculates the seconds passed since the last handshake.
82 '';
83 };
84
85 prependSudo = mkOption {
86 type = types.bool;
87 default = false;
88 description = ''
89 Whether or no to prepend sudo to wg commands.
90 '';
91 };
92 };
93 serviceOpts = {
94 path = [ pkgs.wireguard-tools ];
95
96 serviceConfig = {
97 AmbientCapabilities = [ "CAP_NET_ADMIN" ];
98 CapabilityBoundingSet = [ "CAP_NET_ADMIN" ];
99 ExecStart = ''
100 ${pkgs.prometheus-wireguard-exporter}/bin/prometheus_wireguard_exporter \
101 -p ${toString cfg.port} \
102 -l ${cfg.listenAddress} \
103 ${optionalString cfg.verbose "-v true"} \
104 ${optionalString cfg.singleSubnetPerField "-s true"} \
105 ${optionalString cfg.withRemoteIp "-r true"} \
106 ${optionalString cfg.latestHandshakeDelay "-d true"} \
107 ${optionalString cfg.prependSudo "-a true"} \
108 ${optionalString (cfg.wireguardConfig != null) "-n ${escapeShellArg cfg.wireguardConfig}"} \
109 ${concatMapStringsSep " " (i: "-i ${i}") cfg.interfaces} \
110 ${concatStringsSep " " cfg.extraFlags}
111 '';
112 RestrictAddressFamilies = [
113 # Need AF_NETLINK to collect data
114 "AF_NETLINK"
115 ];
116 };
117 };
118}