From b22a75bf006a7c00f33d891ab4fb9049b0c591b8 Mon Sep 17 00:00:00 2001 From: WilliButz Date: Mon, 29 Jul 2019 20:06:41 +0200 Subject: [PATCH 1/3] prometheus-mail-exporter: init at 2019-07-14 --- .../monitoring/prometheus/mail-exporter.nix | 30 ++++++ .../prometheus/mail-exporter_deps.nix | 92 +++++++++++++++++++ pkgs/top-level/all-packages.nix | 1 + 3 files changed, 123 insertions(+) create mode 100644 pkgs/servers/monitoring/prometheus/mail-exporter.nix create mode 100644 pkgs/servers/monitoring/prometheus/mail-exporter_deps.nix diff --git a/pkgs/servers/monitoring/prometheus/mail-exporter.nix b/pkgs/servers/monitoring/prometheus/mail-exporter.nix new file mode 100644 index 00000000000..129c2b33372 --- /dev/null +++ b/pkgs/servers/monitoring/prometheus/mail-exporter.nix @@ -0,0 +1,30 @@ +{ stdenv, buildGoPackage, fetchFromGitHub }: + +buildGoPackage rec { + name = "mailexporter-${version}"; + version = "2019-07-14"; + + goPackagePath = "github.com/cherti/mailexporter"; + + src = fetchFromGitHub { + rev = "c60d1970abbedb15e70d6fc858f7fd76fa061ffe"; + owner = "cherti"; + repo = "mailexporter"; + sha256 = "0wlw7jvmhgvg1r2bsifxm2d0vj0iqhplnx6n446625sslvddx3vn"; + }; + + goDeps = ./mail-exporter_deps.nix; + + postInstall = '' + install -D -m 0444 -t $bin/share/man/man1 $src/man/mailexporter.1 + install -D -m 0444 -t $bin/share/man/man5 $src/man/mailexporter.conf.5 + ''; + + meta = with stdenv.lib; { + description = "Export Prometheus-style metrics about mail server functionality"; + homepage = "https://github.com/cherti/mailexporter"; + license = licenses.gpl3; + maintainers = with maintainers; [ willibutz ]; + platforms = platforms.linux; + }; +} diff --git a/pkgs/servers/monitoring/prometheus/mail-exporter_deps.nix b/pkgs/servers/monitoring/prometheus/mail-exporter_deps.nix new file mode 100644 index 00000000000..221f179940b --- /dev/null +++ b/pkgs/servers/monitoring/prometheus/mail-exporter_deps.nix @@ -0,0 +1,92 @@ +[ + { + goPackagePath = "github.com/beorn7/perks"; + fetch = { + type = "git"; + url = "https://github.com/beorn7/perks"; + rev = "4b2b341e8d7715fae06375aa633dbb6e91b3fb46"; + sha256 = "1i1nz1f6g55xi2y3aiaz5kqfgvknarbfl4f0sx4nyyb4s7xb1z9x"; + }; + } + { + goPackagePath = "github.com/golang/protobuf"; + fetch = { + type = "git"; + url = "https://github.com/golang/protobuf"; + rev = "6c65a5562fc06764971b7c5d05c76c75e84bdbf7"; + sha256 = "1k1wb4zr0qbwgpvz9q5ws9zhlal8hq7dmq62pwxxriksayl6hzym"; + }; + } + { + goPackagePath = "github.com/matttproud/golang_protobuf_extensions"; + fetch = { + type = "git"; + url = "https://github.com/matttproud/golang_protobuf_extensions"; + rev = "c182affec369e30f25d3eb8cd8a478dee585ae7d"; + sha256 = "1xqsf9vpcrd4hp95rl6kgmjvkv1df4aicfw4l5vfcxcwxknfx2xs"; + }; + } + { + goPackagePath = "github.com/prometheus/client_golang"; + fetch = { + type = "git"; + url = "https://github.com/prometheus/client_golang"; + rev = "a6c69798cccecfd43070693e4416838767f73e18"; + sha256 = "0s6xprvkdyfvmx4540454972fn3gvrzy7fyv0yq42h32nw3l7p75"; + }; + } + { + goPackagePath = "github.com/prometheus/client_model"; + fetch = { + type = "git"; + url = "https://github.com/prometheus/client_model"; + rev = "fd36f4220a901265f90734c3183c5f0c91daa0b8"; + sha256 = "1bs5d72k361llflgl94c22n0w53j30rsfh84smgk8mbjbcmjsaa5"; + }; + } + { + goPackagePath = "github.com/prometheus/common"; + fetch = { + type = "git"; + url = "https://github.com/prometheus/common"; + rev = "31bed53e4047fd6c510e43a941f90cb31be0972a"; + sha256 = "1q16br348117ffycxdwsldb0i39p34miclfa8z93k6vjwnrqbh2l"; + }; + } + { + goPackagePath = "github.com/prometheus/procfs"; + fetch = { + type = "git"; + url = "https://github.com/prometheus/procfs"; + rev = "8f55e607908ea781ad9d08521730d73e047d9ac4"; + sha256 = "023581b68mz89yhgnk4w08ch05ix60v0hv9jlqz65w43s4j7g4vb"; + }; + } + { + goPackagePath = "golang.org/x/sys"; + fetch = { + type = "git"; + url = "https://go.googlesource.com/sys"; + rev = "04f50cda93cbb67f2afa353c52f342100e80e625"; + sha256 = "0hmfsz9y1ingwsn482hlzzmzs7kr3cklm0ana0mbdk70isw2bxnw"; + }; + } + { + goPackagePath = "gopkg.in/fsnotify.v1"; + fetch = { + type = "git"; + url = "https://gopkg.in/fsnotify.v1"; + rev = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9"; + sha256 = "07va9crci0ijlivbb7q57d2rz9h27zgn2fsm60spjsqpdbvyrx4g"; + }; + } + { + goPackagePath = "gopkg.in/yaml.v2"; + fetch = { + type = "git"; + url = "https://gopkg.in/yaml.v2"; + rev = "51d6538a90f86fe93ac480b35f37b2be17fef232"; + sha256 = "01wj12jzsdqlnidpyjssmj0r4yavlqy7dwrg7adqd8dicjc4ncsa"; + }; + } +] diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index f91d7e8fbb8..3bd0d214432 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -14787,6 +14787,7 @@ in prometheus-fritzbox-exporter = callPackage ../servers/monitoring/prometheus/fritzbox-exporter.nix { }; prometheus-haproxy-exporter = callPackage ../servers/monitoring/prometheus/haproxy-exporter.nix { }; prometheus-json-exporter = callPackage ../servers/monitoring/prometheus/json-exporter.nix { }; + prometheus-mail-exporter = callPackage ../servers/monitoring/prometheus/mail-exporter.nix { }; prometheus-mesos-exporter = callPackage ../servers/monitoring/prometheus/mesos-exporter.nix { }; prometheus-minio-exporter = callPackage ../servers/monitoring/prometheus/minio-exporter { }; prometheus-mysqld-exporter = callPackage ../servers/monitoring/prometheus/mysqld-exporter.nix { }; From 5818c73d95f6406dc027a31ff10dae5b88d09e32 Mon Sep 17 00:00:00 2001 From: WilliButz Date: Tue, 30 Jul 2019 00:34:45 +0200 Subject: [PATCH 2/3] nixos/prometheus-exporters: add mail exporter module --- .../monitoring/prometheus/exporters.nix | 11 +- .../monitoring/prometheus/exporters/mail.nix | 156 ++++++++++++++++++ 2 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 nixos/modules/services/monitoring/prometheus/exporters/mail.nix diff --git a/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixos/modules/services/monitoring/prometheus/exporters.nix index 802281e7164..03f3da75b14 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters.nix @@ -28,6 +28,7 @@ let "dovecot" "fritzbox" "json" + "mail" "minio" "nginx" "node" @@ -162,13 +163,19 @@ in }; config = mkMerge ([{ - assertions = [{ + 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! ''; - }]; + } { + assertion = (cfg.mail.configFile == null) != (cfg.mail.configuration == {}); + message = '' + Please specify either 'services.prometheus.exporters.mail.configuration' + or 'services.prometheus.exporters.mail.configFile'. + ''; + } ]; }] ++ [(mkIf config.services.minio.enable { services.prometheus.exporters.minio.minioAddress = mkDefault "http://localhost:9000"; services.prometheus.exporters.minio.minioAccessKey = mkDefault config.services.minio.accessKey; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/mail.nix b/nixos/modules/services/monitoring/prometheus/exporters/mail.nix new file mode 100644 index 00000000000..a1b46140d3e --- /dev/null +++ b/nixos/modules/services/monitoring/prometheus/exporters/mail.nix @@ -0,0 +1,156 @@ +{ config, lib, pkgs, options }: + +with lib; + +let + cfg = config.services.prometheus.exporters.mail; + + configurationFile = pkgs.writeText "prometheus-mail-exporter.conf" (builtins.toJSON ( + # removes the _module attribute, null values and converts attrNames to lowercase + mapAttrs' (name: value: + if name == "servers" + then nameValuePair (toLower name) + ((map (srv: (mapAttrs' (n: v: nameValuePair (toLower n) v) + (filterAttrs (n: v: !(n == "_module" || v == null)) srv) + ))) value) + else nameValuePair (toLower name) value + ) (filterAttrs (n: _: !(n == "_module")) cfg.configuration) + )); + + serverOptions.options = { + name = mkOption { + type = types.str; + description = '' + Value for label 'configname' which will be added to all metrics. + ''; + }; + server = mkOption { + type = types.str; + description = '' + Hostname of the server that should be probed. + ''; + }; + port = mkOption { + type = types.int; + example = 587; + description = '' + Port to use for SMTP. + ''; + }; + from = mkOption { + type = types.str; + example = "exporteruser@domain.tld"; + description = '' + Content of 'From' Header for probing mails. + ''; + }; + to = mkOption { + type = types.str; + example = "exporteruser@domain.tld"; + description = '' + Content of 'To' Header for probing mails. + ''; + }; + detectionDir = mkOption { + type = types.path; + example = "/var/spool/mail/exporteruser/new"; + description = '' + Directory in which new mails for the exporter user are placed. + Note that this needs to exist when the exporter starts. + ''; + }; + login = mkOption { + type = types.nullOr types.str; + default = null; + example = "exporteruser@domain.tld"; + description = '' + Username to use for SMTP authentication. + ''; + }; + passphrase = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Password to use for SMTP authentication. + ''; + }; + }; + + exporterOptions.options = { + monitoringInterval = mkOption { + type = types.str; + example = "10s"; + description = '' + Time interval between two probe attempts. + ''; + }; + mailCheckTimeout = mkOption { + type = types.str; + description = '' + Timeout until mails are considered "didn't make it". + ''; + }; + disableFileDelition = mkOption { + type = types.bool; + default = false; + description = '' + Disables the exporter's function to delete probing mails. + ''; + }; + servers = mkOption { + type = types.listOf (types.submodule serverOptions); + default = []; + example = literalExample '' + [ { + name = "testserver"; + server = "smtp.domain.tld"; + port = 587; + from = "exporteruser@domain.tld"; + to = "exporteruser@domain.tld"; + detectionDir = "/path/to/Maildir/new"; + } ] + ''; + description = '' + List of servers that should be probed. + ''; + }; + }; +in +{ + port = 9225; + extraOpts = { + configFile = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + Specify the mailexporter configuration file to use. + ''; + }; + configuration = mkOption { + type = types.submodule exporterOptions; + default = {}; + description = '' + Specify the mailexporter configuration file to use. + ''; + }; + telemetryPath = mkOption { + type = types.str; + default = "/metrics"; + description = '' + Path under which to expose metrics. + ''; + }; + }; + serviceOpts = { + serviceConfig = { + ExecStart = '' + ${pkgs.prometheus-mail-exporter}/bin/mailexporter \ + --web.listen-address ${cfg.listenAddress}:${toString cfg.port} \ + --config.file ${ + if cfg.configuration != {} then configurationFile else cfg.configFile + } \ + ${concatStringsSep " \\\n " cfg.extraFlags} + ''; + }; + }; +} From deedad80c7a32ee837a23929396501dcee15fa29 Mon Sep 17 00:00:00 2001 From: WilliButz Date: Tue, 30 Jul 2019 00:43:34 +0200 Subject: [PATCH 3/3] nixos/tests/prometheus-exporters: add mail exporter --- nixos/tests/prometheus-exporters.nix | 42 ++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/nixos/tests/prometheus-exporters.nix b/nixos/tests/prometheus-exporters.nix index 2286d70be28..533054a4686 100644 --- a/nixos/tests/prometheus-exporters.nix +++ b/nixos/tests/prometheus-exporters.nix @@ -188,6 +188,48 @@ let ''; }; + mail = { + exporterConfig = { + enable = true; + user = "mailexporter"; + configuration = { + monitoringInterval = "2s"; + mailCheckTimeout = "10s"; + servers = [ { + name = "testserver"; + server = "localhost"; + port = 25; + from = "mailexporter@localhost"; + to = "mailexporter@localhost"; + detectionDir = "/var/spool/mail/mailexporter/new"; + } ]; + }; + }; + metricProvider = { + services.postfix.enable = true; + systemd.services.prometheus-mail-exporter = { + after = [ "postfix.service" ]; + requires = [ "postfix.service" ]; + preStart = '' + mkdir -p 0600 mailexporter/new + ''; + serviceConfig = { + ProtectHome = true; + ReadOnlyPaths = "/"; + ReadWritePaths = "/var/spool/mail"; + WorkingDirectory = "/var/spool/mail"; + }; + }; + users.users.mailexporter.isSystemUser = true; + }; + exporterTest = '' + waitForUnit("postfix.service") + waitForUnit("prometheus-mail-exporter.service") + waitForOpenPort(9225) + waitUntilSucceeds("curl -sSf http://localhost:9225/metrics | grep -q 'mail_deliver_success{configname=\"testserver\"} 1'") + ''; + }; + nginx = { exporterConfig = { enable = true;