Merge pull request #36909 from WilliButz/prometheus-exporters

nixos/prometheus-exporters: rewrite and restructure
This commit is contained in:
Robin Gloster 2018-03-22 15:23:44 +01:00 committed by GitHub
commit 60a6c63155
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 845 additions and 933 deletions

View file

@ -353,7 +353,12 @@ following incompatible changes:</para>
Use <literal>withOnlyInstalledCommunityModules</literal> for modules that should not be enabled directly, e.g <literal>lib_ldap</literal>.
</para>
</listitem>
<listitem>
<para>
All prometheus exporter modules are now defined as submodules.
The exporters are configured using <literal>services.prometheus.exporters</literal>.
</para>
</listitem>
</itemizedlist>
</section>

View file

@ -398,16 +398,7 @@
./services/monitoring/osquery.nix
./services/monitoring/prometheus/default.nix
./services/monitoring/prometheus/alertmanager.nix
./services/monitoring/prometheus/blackbox-exporter.nix
./services/monitoring/prometheus/collectd-exporter.nix
./services/monitoring/prometheus/fritzbox-exporter.nix
./services/monitoring/prometheus/json-exporter.nix
./services/monitoring/prometheus/minio-exporter.nix
./services/monitoring/prometheus/nginx-exporter.nix
./services/monitoring/prometheus/node-exporter.nix
./services/monitoring/prometheus/snmp-exporter.nix
./services/monitoring/prometheus/unifi-exporter.nix
./services/monitoring/prometheus/varnish-exporter.nix
./services/monitoring/prometheus/exporters.nix
./services/monitoring/riemann.nix
./services/monitoring/riemann-dash.nix
./services/monitoring/riemann-tools.nix

View file

@ -240,5 +240,11 @@ with lib;
# Xen
(mkRenamedOptionModule [ "virtualisation" "xen" "qemu-package" ] [ "virtualisation" "xen" "package-qemu" ])
];
] ++ (flip map [ "blackboxExporter" "collectdExporter" "fritzboxExporter"
"jsonExporter" "minioExporter" "nginxExporter" "nodeExporter"
"snmpExporter" "unifiExporter" "varnishExporter" ]
(opt: mkRemovedOptionModule [ "services" "prometheus" "${opt}" ] ''
The prometheus exporters are now configured using `services.prometheus.exporters'.
See the 18.03 release notes for more information.
'' ));
}

View file

@ -1,68 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.prometheus.blackboxExporter;
in {
options = {
services.prometheus.blackboxExporter = {
enable = mkEnableOption "prometheus blackbox exporter";
configFile = mkOption {
type = types.path;
description = ''
Path to configuration file.
'';
};
port = mkOption {
type = types.int;
default = 9115;
description = ''
Port to listen on.
'';
};
extraFlags = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Extra commandline options when launching the blackbox exporter.
'';
};
openFirewall = mkOption {
type = types.bool;
default = false;
description = ''
Open port in firewall for incoming connections.
'';
};
};
};
config = mkIf cfg.enable {
networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port;
systemd.services.prometheus-blackbox-exporter = {
description = "Prometheus exporter for blackbox probes";
unitConfig.Documentation = "https://github.com/prometheus/blackbox_exporter";
wantedBy = [ "multi-user.target" ];
serviceConfig = {
User = "nobody";
Restart = "always";
PrivateTmp = true;
WorkingDirectory = /tmp;
AmbientCapabilities = [ "CAP_NET_RAW" ]; # for ping probes
ExecStart = ''
${pkgs.prometheus-blackbox-exporter}/bin/blackbox_exporter \
--web.listen-address :${toString cfg.port} \
--config.file ${cfg.configFile} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
};
};
};
}

View file

@ -1,128 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.prometheus.collectdExporter;
collectSettingsArgs = if (cfg.collectdBinary.enable) then ''
-collectd.listen-address ${optionalString (cfg.collectdBinary.listenAddress != null) cfg.collectdBinary.listenAddress}:${toString cfg.collectdBinary.port} \
-collectd.security-level ${cfg.collectdBinary.securityLevel} \
'' else "";
in {
options = {
services.prometheus.collectdExporter = {
enable = mkEnableOption "prometheus collectd exporter";
port = mkOption {
type = types.int;
default = 9103;
description = ''
Port to listen on.
This is used for scraping as well as the to receive collectd data via the write_http plugin.
'';
};
listenAddress = mkOption {
type = types.nullOr types.str;
default = null;
example = "0.0.0.0";
description = ''
Address to listen on for web interface, telemetry and collectd JSON data.
'';
};
collectdBinary = {
enable = mkEnableOption "collectd binary protocol receiver";
authFile = mkOption {
default = null;
type = types.nullOr types.path;
description = "File mapping user names to pre-shared keys (passwords).";
};
port = mkOption {
type = types.int;
default = 25826;
description = ''Network address on which to accept collectd binary network packets.'';
};
listenAddress = mkOption {
type = types.nullOr types.str;
default = null;
example = "0.0.0.0";
description = ''
Address to listen on for binary network packets.
'';
};
securityLevel = mkOption {
type = types.enum ["None" "Sign" "Encrypt"];
default = "None";
description = ''
Minimum required security level for accepted packets.
'';
};
};
extraFlags = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Extra commandline options when launching the collectd exporter.
'';
};
logFormat = mkOption {
type = types.str;
default = "logger:stderr";
example = "logger:syslog?appname=bob&local=7 or logger:stdout?json=true";
description = ''
Set the log target and format.
'';
};
logLevel = mkOption {
type = types.enum ["debug" "info" "warn" "error" "fatal"];
default = "info";
description = ''
Only log messages with the given severity or above.
'';
};
openFirewall = mkOption {
type = types.bool;
default = false;
description = ''
Open port in firewall for incoming connections.
'';
};
};
};
config = mkIf cfg.enable {
networking.firewall.allowedTCPPorts = (optional cfg.openFirewall cfg.port) ++
(optional (cfg.openFirewall && cfg.collectdBinary.enable) cfg.collectdBinary.port);
systemd.services.prometheus-collectd-exporter = {
description = "Prometheus exporter for Collectd metrics";
unitConfig.Documentation = "https://github.com/prometheus/collectd_exporter";
wantedBy = [ "multi-user.target" ];
serviceConfig = {
DynamicUser = true;
Restart = "always";
PrivateTmp = true;
WorkingDirectory = /tmp;
ExecStart = ''
${pkgs.prometheus-collectd-exporter}/bin/collectd_exporter \
-log.format ${cfg.logFormat} \
-log.level ${cfg.logLevel} \
-web.listen-address ${optionalString (cfg.listenAddress != null) cfg.listenAddress}:${toString cfg.port} \
${collectSettingsArgs} \
${concatStringsSep " " cfg.extraFlags}
'';
};
};
};
}

View file

@ -0,0 +1,172 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.prometheus.exporters;
# each attribute in `exporterOpts` is expected to have specified:
# - port (types.int): port on which the exporter listens
# - serviceOpts (types.attrs): config that is merged with the
# default definition of the exporter's
# systemd service
# - extraOpts (types.attrs): extra configuration options to
# configure the exporter with, which
# are appended to the default options
#
# Note that `extraOpts` is optional, but a script for the exporter's
# systemd service must be provided by specifying either
# `serviceOpts.script` or `serviceOpts.serviceConfig.ExecStart`
exporterOpts = {
blackbox = import ./exporters/blackbox.nix { inherit config lib pkgs; };
collectd = import ./exporters/collectd.nix { inherit config lib pkgs; };
fritzbox = import ./exporters/fritzbox.nix { inherit config lib pkgs; };
json = import ./exporters/json.nix { inherit config lib pkgs; };
minio = import ./exporters/minio.nix { inherit config lib pkgs; };
nginx = import ./exporters/nginx.nix { inherit config lib pkgs; };
node = import ./exporters/node.nix { inherit config lib pkgs; };
postfix = import ./exporters/postfix.nix { inherit config lib pkgs; };
snmp = import ./exporters/snmp.nix { inherit config lib pkgs; };
unifi = import ./exporters/unifi.nix { inherit config lib pkgs; };
varnish = import ./exporters/varnish.nix { inherit config lib pkgs; };
};
mkExporterOpts = ({ name, port }: {
enable = mkEnableOption "the prometheus ${name} exporter";
port = mkOption {
type = types.int;
default = port;
description = ''
Port to listen on.
'';
};
listenAddress = mkOption {
type = types.str;
default = "0.0.0.0";
description = ''
Address to listen on.
'';
};
extraFlags = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Extra commandline options to pass to the ${name} exporter.
'';
};
openFirewall = mkOption {
type = types.bool;
default = false;
description = ''
Open port in firewall for incoming connections.
'';
};
firewallFilter = mkOption {
type = types.str;
default = "-p tcp -m tcp --dport ${toString port}";
example = literalExample ''
"-i eth0 -p tcp -m tcp --dport ${toString port}"
'';
description = ''
Specify a filter for iptables to use when
<option>services.prometheus.exporters.${name}.openFirewall</option>
is true. It is used as `ip46tables -I INPUT <option>firewallFilter</option> -j ACCEPT`.
'';
};
user = mkOption {
type = types.str;
default = "nobody";
description = ''
User name under which the ${name} exporter shall be run.
Has no effect when <option>systemd.services.prometheus-${name}-exporter.serviceConfig.DynamicUser</option> is true.
'';
};
group = mkOption {
type = types.str;
default = "nobody";
description = ''
Group under which the ${name} exporter shall be run.
Has no effect when <option>systemd.services.prometheus-${name}-exporter.serviceConfig.DynamicUser</option> is true.
'';
};
});
mkSubModule = { name, port, extraOpts, serviceOpts }: {
${name} = mkOption {
type = types.submodule {
options = (mkExporterOpts {
inherit name port;
} // extraOpts);
};
internal = true;
default = {};
};
};
mkSubModules = (foldl' (a: b: a//b) {}
(mapAttrsToList (name: opts: mkSubModule {
inherit name;
inherit (opts) port serviceOpts;
extraOpts = opts.extraOpts or {};
}) exporterOpts)
);
mkExporterConf = { name, conf, serviceOpts }:
mkIf conf.enable {
networking.firewall.extraCommands = mkIf conf.openFirewall ''
ip46tables -I INPUT ${conf.firewallFilter} -j ACCEPT
'';
systemd.services."prometheus-${name}-exporter" = mkMerge ([{
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
Restart = mkDefault "always";
PrivateTmp = mkDefault true;
WorkingDirectory = mkDefault /tmp;
} // mkIf (!(serviceOpts.serviceConfig.DynamicUser or false)) {
User = conf.user;
Group = conf.group;
};
} serviceOpts ]);
};
in
{
options.services.prometheus.exporters = mkOption {
type = types.submodule {
options = (mkSubModules);
};
description = "Prometheus exporter configuration";
default = {};
example = literalExample ''
{
node = {
enable = true;
enabledCollectors = [ "systemd" ];
};
varnish.enable = true;
}
'';
};
config = mkMerge ([{
assertions = [{
assertion = (cfg.snmp.configurationPath == null) != (cfg.snmp.configuration == null);
message = ''
Please ensure you have either `services.prometheus.exporters.snmp.configuration'
or `services.prometheus.exporters.snmp.configurationPath' set!
'';
}];
}] ++ [(mkIf config.services.minio.enable {
services.prometheus.exporters.minio.minioAddress = mkDefault "http://localhost:9000";
services.prometheus.exporters.minio.minioAccessKey = mkDefault config.services.minio.accessKey;
services.prometheus.exporters.minio.minioAccessSecret = mkDefault config.services.minio.secretKey;
})] ++ (mapAttrsToList (name: conf:
mkExporterConf {
inherit name;
inherit (conf) serviceOpts;
conf = cfg.${name};
}) exporterOpts)
);
meta.doc = ./exporters.xml;
}

View file

@ -0,0 +1,135 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="module-services-prometheus-exporters">
<title>Prometheus exporters</title>
<para>Prometheus exporters provide metrics for the <link xlink:href="https://prometheus.io">prometheus monitoring system</link>.</para>
<section><title>Configuration</title>
<para>One of the most common exporters is the <link xlink:href="https://github.com/prometheus/node_exporter">node exporter</link>, it provides hardware and OS metrics from the host it's running on. The exporter could be configured as follows:
<programlisting>
services.promtheus.exporters.node = {
enable = true;
enabledCollectors = [
"logind"
"systemd"
];
disabledCollectors = [
"textfile"
];
openFirewall = true;
firewallFilter = "-i br0 -p tcp -m tcp --dport 9100";
};
</programlisting>
It should now serve all metrics from the collectors
that are explicitly enabled and the ones that are
<link xlink:href="https://github.com/prometheus/node_exporter#enabled-by-default">enabled by default</link>, via http under <literal>/metrics</literal>. In this example the firewall should just
allow incoming connections to the exporter's port on the bridge interface <literal>br0</literal>
(this would have to be configured seperately of course).
For more information about configuration see <literal>man configuration.nix</literal> or
search through the <link xlink:href="https://nixos.org/nixos/options.html#prometheus.exporters">available options</link>.
</para>
</section>
<section><title>Adding a new exporter</title>
<para>To add a new exporter, it has to be packaged first (see <literal>nixpkgs/pkgs/servers/monitoring/prometheus/</literal> for examples), then a module can be added. The postfix exporter is used in this example:</para>
<itemizedlist>
<listitem>
<para>
Some default options for all exporters are provided by
<literal>nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix</literal>:
</para>
</listitem>
<listitem override='none'>
<itemizedlist>
<listitem><para><literal>enable</literal></para></listitem>
<listitem><para><literal>port</literal></para></listitem>
<listitem><para><literal>listenAddress</literal></para></listitem>
<listitem><para><literal>extraFlags</literal></para></listitem>
<listitem><para><literal>openFirewall</literal></para></listitem>
<listitem><para><literal>firewallFilter</literal></para></listitem>
<listitem><para><literal>user</literal></para></listitem>
<listitem><para><literal>group</literal></para></listitem>
</itemizedlist>
</listitem>
<listitem>
<para>As there is already a package available, the module can now be added.
This is accomplished by adding a new file to the
<literal>nixos/modules/services/monitoring/prometheus/exporters/</literal> directory,
which will be called postfix.nix and contains all exporter specific options
and configuration:
<programlisting>
# nixpgs/nixos/modules/services/prometheus/exporters/postfix.nix
{ config, lib, pkgs }:
with lib;
let
# for convenience we define cfg here
cfg = config.services.prometheus.exporters.postfix;
in
{
port = 9154; # The postfix exporter listens on this port by default
# `extraOpts` is an attribute set which contains additional options
# (and optional overrides for default options).
# Note that this attribute is optional.
extraOpts = {
telemetryPath = mkOption {
type = types.str;
default = "/metrics";
description = ''
Path under which to expose metrics.
'';
};
logfilePath = mkOption {
type = types.path;
default = /var/log/postfix_exporter_input.log;
example = /var/log/mail.log;
description = ''
Path where Postfix writes log entries.
This file will be truncated by this exporter!
'';
};
showqPath = mkOption {
type = types.path;
default = /var/spool/postfix/public/showq;
example = /var/lib/postfix/queue/public/showq;
description = ''
Path at which Postfix places its showq socket.
'';
};
};
# `serviceOpts` is an attribute set which contains configuration
# for the exporter's systemd service. One of
# `serviceOpts.script` and `serviceOpts.serviceConfig.ExecStart`
# has to be specified here. This will be merged with the default
# service confiuration.
serviceOpts = {
serviceConfig = {
ExecStart = ''
${pkgs.prometheus-postfix-exporter}/bin/postfix_exporter \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
--web.telemetry-path ${cfg.telemetryPath} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
}
</programlisting>
</para>
</listitem>
<listitem>
<para>
This should already be enough for the postfix exporter. Additionally one could
now add assertions and conditional default values. This can be done in the
'meta-module' that combines all exporter definitions and generates the submodules:
<literal>nixpkgs/nixos/modules/services/prometheus/exporters.nix</literal>
</para>
</listitem>
</itemizedlist>
</section>
</chapter>

View file

@ -0,0 +1,31 @@
{ config, lib, pkgs }:
with lib;
let
cfg = config.services.prometheus.exporters.blackbox;
in
{
port = 9115;
extraOpts = {
configFile = mkOption {
type = types.path;
description = ''
Path to configuration file.
'';
};
};
serviceOpts = {
serviceConfig = {
AmbientCapabilities = [ "CAP_NET_RAW" ]; # for ping probes
DynamicUser = true;
ExecStart = ''
${pkgs.prometheus-blackbox-exporter}/bin/blackbox_exporter \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
--config.file ${cfg.configFile} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
};
};
}

View file

@ -0,0 +1,78 @@
{ config, lib, pkgs }:
with lib;
let
cfg = config.services.prometheus.exporters.collectd;
in
{
port = 9103;
extraOpts = {
collectdBinary = {
enable = mkEnableOption "collectd binary protocol receiver";
authFile = mkOption {
default = null;
type = types.nullOr types.path;
description = "File mapping user names to pre-shared keys (passwords).";
};
port = mkOption {
type = types.int;
default = 25826;
description = ''Network address on which to accept collectd binary network packets.'';
};
listenAddress = mkOption {
type = types.str;
default = "0.0.0.0";
description = ''
Address to listen on for binary network packets.
'';
};
securityLevel = mkOption {
type = types.enum ["None" "Sign" "Encrypt"];
default = "None";
description = ''
Minimum required security level for accepted packets.
'';
};
};
logFormat = mkOption {
type = types.str;
default = "logger:stderr";
example = "logger:syslog?appname=bob&local=7 or logger:stdout?json=true";
description = ''
Set the log target and format.
'';
};
logLevel = mkOption {
type = types.enum ["debug" "info" "warn" "error" "fatal"];
default = "info";
description = ''
Only log messages with the given severity or above.
'';
};
};
serviceOpts = let
collectSettingsArgs = if (cfg.collectdBinary.enable) then ''
-collectd.listen-address ${cfg.collectdBinary.listenAddress}:${toString cfg.collectdBinary.port} \
-collectd.security-level ${cfg.collectdBinary.securityLevel} \
'' else "";
in {
serviceConfig = {
DynamicUser = true;
ExecStart = ''
${pkgs.prometheus-collectd-exporter}/bin/collectd_exporter \
-log.format ${cfg.logFormat} \
-log.level ${cfg.logLevel} \
-web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
${collectSettingsArgs} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
}

View file

@ -0,0 +1,39 @@
{ config, lib, pkgs }:
with lib;
let
cfg = config.services.prometheus.exporters.fritzbox;
in
{
port = 9133;
extraOpts = {
gatewayAddress = mkOption {
type = types.str;
default = "fritz.box";
description = ''
The hostname or IP of the FRITZ!Box.
'';
};
gatewayPort = mkOption {
type = types.int;
default = 49000;
description = ''
The port of the FRITZ!Box UPnP service.
'';
};
};
serviceOpts = {
serviceConfig = {
DynamicUser = true;
ExecStart = ''
${pkgs.prometheus-fritzbox-exporter}/bin/fritzbox_exporter \
-listen-address ${cfg.listenAddress}:${toString cfg.port} \
-gateway-address ${cfg.gatewayAddress} \
-gateway-port ${toString cfg.gatewayPort} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
}

View file

@ -0,0 +1,36 @@
{ config, lib, pkgs }:
with lib;
let
cfg = config.services.prometheus.exporters.json;
in
{
port = 7979;
extraOpts = {
url = mkOption {
type = types.str;
description = ''
URL to scrape JSON from.
'';
};
configFile = mkOption {
type = types.path;
description = ''
Path to configuration file.
'';
};
listenAddress = {}; # not used
};
serviceOpts = {
serviceConfig = {
DynamicUser = true;
ExecStart = ''
${pkgs.prometheus-json-exporter}/bin/prometheus-json-exporter \
--port ${toString cfg.port} \
${cfg.url} ${cfg.configFile} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
}

View file

@ -0,0 +1,65 @@
{ config, lib, pkgs }:
with lib;
let
cfg = config.services.prometheus.exporters.minio;
in
{
port = 9290;
extraOpts = {
minioAddress = mkOption {
type = types.str;
example = "https://10.0.0.1:9000";
description = ''
The URL of the minio server.
Use HTTPS if Minio accepts secure connections only.
By default this connects to the local minio server if enabled.
'';
};
minioAccessKey = mkOption {
type = types.str;
example = "yourMinioAccessKey";
description = ''
The value of the Minio access key.
It is required in order to connect to the server.
By default this uses the one from the local minio server if enabled
and <literal>config.services.minio.accessKey</literal>.
'';
};
minioAccessSecret = mkOption {
type = types.str;
description = ''
The value of the Minio access secret.
It is required in order to connect to the server.
By default this uses the one from the local minio server if enabled
and <literal>config.services.minio.secretKey</literal>.
'';
};
minioBucketStats = mkOption {
type = types.bool;
default = false;
description = ''
Collect statistics about the buckets and files in buckets.
It requires more computation, use it carefully in case of large buckets..
'';
};
};
serviceOpts = {
serviceConfig = {
DynamicUser = true;
ExecStart = ''
${pkgs.prometheus-minio-exporter}/bin/minio-exporter \
-web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
-minio.server ${cfg.minioAddress} \
-minio.access-key ${cfg.minioAccessKey} \
-minio.access-secret ${cfg.minioAccessSecret} \
${optionalString cfg.minioBucketStats "-minio.bucket-stats"} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
}

View file

@ -0,0 +1,31 @@
{ config, lib, pkgs }:
with lib;
let
cfg = config.services.prometheus.exporters.nginx;
in
{
port = 9113;
extraOpts = {
scrapeUri = mkOption {
type = types.string;
default = "http://localhost/nginx_status";
description = ''
Address to access the nginx status page.
Can be enabled with services.nginx.statusPage = true.
'';
};
};
serviceOpts = {
serviceConfig = {
DynamicUser = true;
ExecStart = ''
${pkgs.prometheus-nginx-exporter}/bin/nginx_exporter \
-nginx.scrape_uri '${cfg.scrapeUri}' \
-telemetry.address ${cfg.listenAddress}:${toString cfg.port} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
}

View file

@ -0,0 +1,39 @@
{ config, lib, pkgs }:
with lib;
let
cfg = config.services.prometheus.exporters.node;
in
{
port = 9100;
extraOpts = {
enabledCollectors = mkOption {
type = types.listOf types.string;
default = [];
example = ''[ "systemd" ]'';
description = ''
Collectors to enable. The collectors listed here are enabled in addition to the default ones.
'';
};
disabledCollectors = mkOption {
type = types.listOf types.str;
default = [];
example = ''[ "timex" ]'';
description = ''
Collectors to disable which are enabled by default.
'';
};
};
serviceOpts = {
serviceConfig = {
ExecStart = ''
${pkgs.prometheus-node-exporter}/bin/node_exporter \
${concatMapStringsSep " " (x: "--collector." + x) cfg.enabledCollectors} \
${concatMapStringsSep " " (x: "--no-collector." + x) cfg.disabledCollectors} \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
}

View file

@ -0,0 +1,46 @@
{ config, lib, pkgs }:
with lib;
let
cfg = config.services.prometheus.exporters.postfix;
in
{
port = 9154;
extraOpts = {
telemetryPath = mkOption {
type = types.str;
default = "/metrics";
description = ''
Path under which to expose metrics.
'';
};
logfilePath = mkOption {
type = types.path;
default = "/var/log/postfix_exporter_input.log";
example = "/var/log/mail.log";
description = ''
Path where Postfix writes log entries.
This file will be truncated by this exporter!
'';
};
showqPath = mkOption {
type = types.path;
default = "/var/spool/postfix/public/showq";
example = "/var/lib/postfix/queue/public/showq";
description = ''
Path where Postfix places it's showq socket.
'';
};
};
serviceOpts = {
serviceConfig = {
ExecStart = ''
${pkgs.prometheus-postfix-exporter}/bin/postfix_exporter \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
--web.telemetry-path ${cfg.telemetryPath} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
}

View file

@ -0,0 +1,71 @@
{ config, lib, pkgs }:
with lib;
let
cfg = config.services.prometheus.exporters.snmp;
in
{
port = 9116;
extraOpts = {
configurationPath = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
Path to a snmp exporter configuration file. Mutually exclusive with 'configuration' option.
'';
example = "./snmp.yml";
};
configuration = mkOption {
type = types.nullOr types.attrs;
default = {};
description = ''
Snmp exporter configuration as nix attribute set. Mutually exclusive with 'configurationPath' option.
'';
example = ''
{
"default" = {
"version" = 2;
"auth" = {
"community" = "public";
};
};
};
'';
};
logFormat = mkOption {
type = types.str;
default = "logger:stderr";
description = ''
Set the log target and format.
'';
};
logLevel = mkOption {
type = types.enum ["debug" "info" "warn" "error" "fatal"];
default = "info";
description = ''
Only log messages with the given severity or above.
'';
};
};
serviceOpts = let
configFile = if cfg.configurationPath != null
then cfg.configurationPath
else "${pkgs.writeText "snmp-eporter-conf.yml" (builtins.toJSON cfg.configuration)}";
in {
serviceConfig = {
DynamicUser = true;
ExecStart = ''
${pkgs.prometheus-snmp-exporter.bin}/bin/snmp_exporter \
-config.file ${configFile} \
-log.format ${cfg.logFormat} \
-log.level ${cfg.logLevel} \
-web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
}

View file

@ -0,0 +1,67 @@
{ config, lib, pkgs }:
with lib;
let
cfg = config.services.prometheus.exporters.unifi;
in
{
port = 9130;
extraOpts = {
unifiAddress = mkOption {
type = types.str;
example = "https://10.0.0.1:8443";
description = ''
URL of the UniFi Controller API.
'';
};
unifiInsecure = mkOption {
type = types.bool;
default = false;
description = ''
If enabled skip the verification of the TLS certificate of the UniFi Controller API.
Use with caution.
'';
};
unifiUsername = mkOption {
type = types.str;
example = "ReadOnlyUser";
description = ''
username for authentication against UniFi Controller API.
'';
};
unifiPassword = mkOption {
type = types.str;
description = ''
Password for authentication against UniFi Controller API.
'';
};
unifiTimeout = mkOption {
type = types.str;
default = "5s";
example = "2m";
description = ''
Timeout including unit for UniFi Controller API requests.
'';
};
};
serviceOpts = {
serviceConfig = {
DynamicUser = true;
ExecStart = ''
${pkgs.prometheus-unifi-exporter}/bin/unifi_exporter \
-telemetry.addr ${cfg.listenAddress}:${toString cfg.port} \
-unifi.addr ${cfg.unifiAddress} \
-unifi.username ${cfg.unifiUsername} \
-unifi.password ${cfg.unifiPassword} \
-unifi.timeout ${cfg.unifiTimeout} \
${optionalString cfg.unifiInsecure "-unifi.insecure" } \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
}

View file

@ -0,0 +1,21 @@
{ config, lib, pkgs }:
with lib;
let
cfg = config.services.prometheus.exporters.varnish;
in
{
port = 9131;
serviceOpts = {
path = [ pkgs.varnish ];
serviceConfig = {
DynamicUser = true;
ExecStart = ''
${pkgs.prometheus-varnish-exporter}/bin/prometheus_varnish_exporter \
-web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
}

View file

@ -1,76 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.prometheus.fritzboxExporter;
in {
options = {
services.prometheus.fritzboxExporter = {
enable = mkEnableOption "prometheus fritzbox exporter";
port = mkOption {
type = types.int;
default = 9133;
description = ''
Port to listen on.
'';
};
gatewayAddress = mkOption {
type = types.str;
default = "fritz.box";
description = ''
The hostname or IP of the FRITZ!Box.
'';
};
gatewayPort = mkOption {
type = types.int;
default = 49000;
description = ''
The port of the FRITZ!Box UPnP service.
'';
};
extraFlags = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Extra commandline options when launching the fritzbox exporter.
'';
};
openFirewall = mkOption {
type = types.bool;
default = false;
description = ''
Open port in firewall for incoming connections.
'';
};
};
};
config = mkIf cfg.enable {
networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port;
systemd.services.prometheus-fritzbox-exporter = {
description = "Prometheus exporter for FRITZ!Box via UPnP";
unitConfig.Documentation = "https://github.com/ndecker/fritzbox_exporter";
wantedBy = [ "multi-user.target" ];
serviceConfig = {
User = "nobody";
Restart = "always";
PrivateTmp = true;
WorkingDirectory = /tmp;
ExecStart = ''
${pkgs.prometheus-fritzbox-exporter}/bin/fritzbox_exporter \
-listen-address :${toString cfg.port} \
-gateway-address ${cfg.gatewayAddress} \
-gateway-port ${toString cfg.gatewayPort} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
};
}

View file

@ -1,74 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.prometheus.jsonExporter;
in {
options = {
services.prometheus.jsonExporter = {
enable = mkEnableOption "prometheus JSON exporter";
url = mkOption {
type = types.str;
description = ''
URL to scrape JSON from.
'';
};
configFile = mkOption {
type = types.path;
description = ''
Path to configuration file.
'';
};
port = mkOption {
type = types.int;
default = 7979;
description = ''
Port to listen on.
'';
};
extraFlags = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Extra commandline options when launching the JSON exporter.
'';
};
openFirewall = mkOption {
type = types.bool;
default = false;
description = ''
Open port in firewall for incoming connections.
'';
};
};
};
config = mkIf cfg.enable {
networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port;
systemd.services.prometheus-json-exporter = {
description = "Prometheus exporter for JSON over HTTP";
unitConfig.Documentation = "https://github.com/kawamuray/prometheus-json-exporter";
wantedBy = [ "multi-user.target" ];
serviceConfig = {
User = "nobody";
Restart = "always";
PrivateTmp = true;
WorkingDirectory = /tmp;
ExecStart = ''
${pkgs.prometheus-json-exporter}/bin/prometheus-json-exporter \
--port ${toString cfg.port} \
${cfg.url} ${cfg.configFile} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
};
};
};
}

View file

@ -1,117 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.prometheus.minioExporter;
in {
options = {
services.prometheus.minioExporter = {
enable = mkEnableOption "prometheus minio exporter";
port = mkOption {
type = types.int;
default = 9290;
description = ''
Port to listen on.
'';
};
listenAddress = mkOption {
type = types.nullOr types.str;
default = null;
example = "0.0.0.0";
description = ''
Address to listen on for web interface and telemetry.
'';
};
minioAddress = mkOption {
type = types.str;
example = "https://10.0.0.1:9000";
default = if config.services.minio.enable then "http://localhost:9000" else null;
description = ''
The URL of the minio server.
Use HTTPS if Minio accepts secure connections only.
By default this connects to the local minio server if enabled.
'';
};
minioAccessKey = mkOption ({
type = types.str;
example = "BKIKJAA5BMMU2RHO6IBB";
description = ''
The value of the Minio access key.
It is required in order to connect to the server.
By default this uses the one from the local minio server if enabled
and <literal>config.services.minio.accessKey</literal>.
'';
} // optionalAttrs (config.services.minio.enable && config.services.minio.accessKey != "") {
default = config.services.minio.accessKey;
});
minioAccessSecret = mkOption ({
type = types.str;
description = ''
The calue of the Minio access secret.
It is required in order to connect to the server.
By default this uses the one from the local minio server if enabled
and <literal>config.services.minio.secretKey</literal>.
'';
} // optionalAttrs (config.services.minio.enable && config.services.minio.secretKey != "") {
default = config.services.minio.secretKey;
});
minioBucketStats = mkOption {
type = types.bool;
default = false;
description = ''
Collect statistics about the buckets and files in buckets.
It requires more computation, use it carefully in case of large buckets..
'';
};
extraFlags = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Extra commandline options when launching the minio exporter.
'';
};
openFirewall = mkOption {
type = types.bool;
default = false;
description = ''
Open port in firewall for incoming connections.
'';
};
};
};
config = mkIf cfg.enable {
networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port;
systemd.services.prometheus-minio-exporter = {
description = "Prometheus exporter for Minio server metrics";
unitConfig.Documentation = "https://github.com/joe-pll/minio-exporter";
wantedBy = [ "multi-user.target" ];
after = optional config.services.minio.enable "minio.service";
serviceConfig = {
DynamicUser = true;
Restart = "always";
PrivateTmp = true;
WorkingDirectory = /tmp;
ExecStart = ''
${pkgs.prometheus-minio-exporter}/bin/minio-exporter \
-web.listen-address ${optionalString (cfg.listenAddress != null) cfg.listenAddress}:${toString cfg.port} \
-minio.server ${cfg.minioAddress} \
-minio.access-key ${cfg.minioAccessKey} \
-minio.access-secret ${cfg.minioAccessSecret} \
${optionalString cfg.minioBucketStats "-minio.bucket-stats"} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
};
}

View file

@ -1,78 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.prometheus.nginxExporter;
in {
options = {
services.prometheus.nginxExporter = {
enable = mkEnableOption "prometheus nginx exporter";
port = mkOption {
type = types.int;
default = 9113;
description = ''
Port to listen on.
'';
};
listenAddress = mkOption {
type = types.string;
default = "0.0.0.0";
description = ''
Address to listen on.
'';
};
scrapeUri = mkOption {
type = types.string;
default = "http://localhost/nginx_status";
description = ''
Address to access the nginx status page.
Can be enabled with services.nginx.statusPage = true.
'';
};
extraFlags = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Extra commandline options when launching the nginx exporter.
'';
};
openFirewall = mkOption {
type = types.bool;
default = false;
description = ''
Open port in firewall for incoming connections.
'';
};
};
};
config = mkIf cfg.enable {
networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port;
systemd.services.prometheus-nginx-exporter = {
after = [ "network.target" "nginx.service" ];
description = "Prometheus exporter for nginx metrics";
unitConfig.Documentation = "https://github.com/discordianfish/nginx_exporter";
wantedBy = [ "multi-user.target" ];
serviceConfig = {
User = "nobody";
Restart = "always";
PrivateTmp = true;
WorkingDirectory = /tmp;
ExecStart = ''
${pkgs.prometheus-nginx-exporter}/bin/nginx_exporter \
-nginx.scrape_uri '${cfg.scrapeUri}' \
-telemetry.address ${cfg.listenAddress}:${toString cfg.port} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
};
};
};
}

View file

@ -1,87 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.prometheus.nodeExporter;
in {
options = {
services.prometheus.nodeExporter = {
enable = mkEnableOption "prometheus node exporter";
port = mkOption {
type = types.int;
default = 9100;
description = ''
Port to listen on.
'';
};
listenAddress = mkOption {
type = types.string;
default = "0.0.0.0";
description = ''
Address to listen on.
'';
};
enabledCollectors = mkOption {
type = types.listOf types.string;
default = [];
example = ''[ "systemd" ]'';
description = ''
Collectors to enable. The collectors listed here are enabled in addition to the default ones.
'';
};
disabledCollectors = mkOption {
type = types.listOf types.str;
default = [];
example = ''[ "timex" ]'';
description = ''
Collectors to disable which are enabled by default.
'';
};
extraFlags = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Extra commandline options when launching the node exporter.
'';
};
openFirewall = mkOption {
type = types.bool;
default = false;
description = ''
Open port in firewall for incoming connections.
'';
};
};
};
config = mkIf cfg.enable {
networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port;
systemd.services.prometheus-node-exporter = {
description = "Prometheus exporter for machine metrics";
unitConfig.Documentation = "https://github.com/prometheus/node_exporter";
wantedBy = [ "multi-user.target" ];
script = ''
exec ${pkgs.prometheus-node-exporter}/bin/node_exporter \
${concatMapStringsSep " " (x: "--collector." + x) cfg.enabledCollectors} \
${concatMapStringsSep " " (x: "--no-collector." + x) cfg.disabledCollectors} \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
serviceConfig = {
User = "nobody";
Restart = "always";
PrivateTmp = true;
WorkingDirectory = /tmp;
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
};
};
};
}

View file

@ -1,127 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.prometheus.snmpExporter;
mkConfigFile = pkgs.writeText "snmp.yml" (if cfg.configurationPath == null then builtins.toJSON cfg.configuration else builtins.readFile cfg.configurationPath);
in {
options = {
services.prometheus.snmpExporter = {
enable = mkEnableOption "Prometheus snmp exporter";
user = mkOption {
type = types.str;
default = "nobody";
description = ''
User name under which snmp exporter shall be run.
'';
};
group = mkOption {
type = types.str;
default = "nogroup";
description = ''
Group under which snmp exporter shall be run.
'';
};
port = mkOption {
type = types.int;
default = 9116;
description = ''
Port to listen on.
'';
};
listenAddress = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Address to listen on for web interface and telemetry.
'';
};
configurationPath = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
Path to a snmp exporter configuration file. Mutually exclusive with 'configuration' option.
'';
example = "./snmp.yml";
};
configuration = mkOption {
type = types.nullOr types.attrs;
default = {};
description = ''
Snmp exporter configuration as nix attribute set. Mutually exclusive with 'configurationPath' option.
'';
example = ''
{
"default" = {
"version" = 2;
"auth" = {
"community" = "public";
};
};
};
'';
};
logFormat = mkOption {
type = types.str;
default = "logger:stderr";
description = ''
Set the log target and format.
'';
};
logLevel = mkOption {
type = types.enum ["debug" "info" "warn" "error" "fatal"];
default = "info";
description = ''
Only log messages with the given severity or above.
'';
};
openFirewall = mkOption {
type = types.bool;
default = false;
description = ''
Open port in firewall for incoming connections.
'';
};
};
};
config = mkIf cfg.enable {
networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port;
assertions = singleton
{
assertion = (cfg.configurationPath == null) != (cfg.configuration == null);
message = "Please ensure you have either 'configuration' or 'configurationPath' set!";
};
systemd.services.prometheus-snmp-exporter = {
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
script = ''
${pkgs.prometheus-snmp-exporter.bin}/bin/snmp_exporter \
-config.file ${mkConfigFile} \
-log.format ${cfg.logFormat} \
-log.level ${cfg.logLevel} \
-web.listen-address ${optionalString (cfg.listenAddress != null) cfg.listenAddress}:${toString cfg.port}
'';
serviceConfig = {
User = cfg.user;
Group = cfg.group;
Restart = "always";
PrivateTmp = true;
WorkingDirectory = "/tmp";
};
};
};
}

View file

@ -1,105 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.prometheus.unifiExporter;
in {
options = {
services.prometheus.unifiExporter = {
enable = mkEnableOption "prometheus unifi exporter";
port = mkOption {
type = types.int;
default = 9130;
description = ''
Port to listen on.
'';
};
unifiAddress = mkOption {
type = types.str;
example = "https://10.0.0.1:8443";
description = ''
URL of the UniFi Controller API.
'';
};
unifiInsecure = mkOption {
type = types.bool;
default = false;
description = ''
If enabled skip the verification of the TLS certificate of the UniFi Controller API.
Use with caution.
'';
};
unifiUsername = mkOption {
type = types.str;
example = "ReadOnlyUser";
description = ''
username for authentication against UniFi Controller API.
'';
};
unifiPassword = mkOption {
type = types.str;
description = ''
Password for authentication against UniFi Controller API.
'';
};
unifiTimeout = mkOption {
type = types.str;
default = "5s";
example = "2m";
description = ''
Timeout including unit for UniFi Controller API requests.
'';
};
extraFlags = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Extra commandline options when launching the unifi exporter.
'';
};
openFirewall = mkOption {
type = types.bool;
default = false;
description = ''
Open port in firewall for incoming connections.
'';
};
};
};
config = mkIf cfg.enable {
networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port;
systemd.services.prometheus-unifi-exporter = {
description = "Prometheus exporter for UniFi Controller metrics";
unitConfig.Documentation = "https://github.com/mdlayher/unifi_exporter";
wantedBy = [ "multi-user.target" ];
after = optional config.services.unifi.enable "unifi.service";
serviceConfig = {
User = "nobody";
Restart = "always";
PrivateTmp = true;
WorkingDirectory = /tmp;
ExecStart = ''
${pkgs.prometheus-unifi-exporter}/bin/unifi_exporter \
-telemetry.addr :${toString cfg.port} \
-unifi.addr ${cfg.unifiAddress} \
-unifi.username ${cfg.unifiUsername} \
-unifi.password ${cfg.unifiPassword} \
-unifi.timeout ${cfg.unifiTimeout} \
${optionalString cfg.unifiInsecure "-unifi.insecure" } \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
};
}

View file

@ -1,61 +0,0 @@
{ config, pkgs, lib, ... }:
# Shamelessly cribbed from nginx-exporter.nix. ~ C.
with lib;
let
cfg = config.services.prometheus.varnishExporter;
in {
options = {
services.prometheus.varnishExporter = {
enable = mkEnableOption "prometheus Varnish exporter";
port = mkOption {
type = types.int;
default = 9131;
description = ''
Port to listen on.
'';
};
extraFlags = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Extra commandline options when launching the Varnish exporter.
'';
};
openFirewall = mkOption {
type = types.bool;
default = false;
description = ''
Open port in firewall for incoming connections.
'';
};
};
};
config = mkIf cfg.enable {
networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port;
systemd.services.prometheus-varnish-exporter = {
description = "Prometheus exporter for Varnish metrics";
unitConfig.Documentation = "https://github.com/jonnenauha/prometheus_varnish_exporter";
wantedBy = [ "multi-user.target" ];
path = [ pkgs.varnish ];
script = ''
exec ${pkgs.prometheus-varnish-exporter}/bin/prometheus_varnish_exporter \
-web.listen-address :${toString cfg.port} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
serviceConfig = {
User = "nobody";
Restart = "always";
PrivateTmp = true;
WorkingDirectory = /tmp;
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
};
};
};
}