diff options
author | Parnell Springmeyer <parnell@digitalmentat.com> | 2017-01-25 11:08:05 -0800 |
---|---|---|
committer | Parnell Springmeyer <parnell@digitalmentat.com> | 2017-01-25 11:08:05 -0800 |
commit | bae00e8aa8f3faff90e28e19cd5074b8c26d0d0e (patch) | |
tree | 56abaf30f11ad2f24b9fb7729f74c5fff50fbd93 /nixos/modules/services/monitoring | |
parent | 1f9494b752082ec3ac048e56d1c6364a2e23a675 (diff) | |
parent | 104c3db6594043dbb81005303f055b02145305a5 (diff) | |
download | nixlib-bae00e8aa8f3faff90e28e19cd5074b8c26d0d0e.tar nixlib-bae00e8aa8f3faff90e28e19cd5074b8c26d0d0e.tar.gz nixlib-bae00e8aa8f3faff90e28e19cd5074b8c26d0d0e.tar.bz2 nixlib-bae00e8aa8f3faff90e28e19cd5074b8c26d0d0e.tar.lz nixlib-bae00e8aa8f3faff90e28e19cd5074b8c26d0d0e.tar.xz nixlib-bae00e8aa8f3faff90e28e19cd5074b8c26d0d0e.tar.zst nixlib-bae00e8aa8f3faff90e28e19cd5074b8c26d0d0e.zip |
setcap-wrapper: Merging with upstream master and resolving conflicts
Diffstat (limited to 'nixos/modules/services/monitoring')
20 files changed, 1173 insertions, 24 deletions
diff --git a/nixos/modules/services/monitoring/bosun.nix b/nixos/modules/services/monitoring/bosun.nix index 9a1e790d3ab6..496838a131ba 100644 --- a/nixos/modules/services/monitoring/bosun.nix +++ b/nixos/modules/services/monitoring/bosun.nix @@ -107,7 +107,7 @@ in { }; extraConfig = mkOption { - type = types.string; + type = types.lines; default = ""; description = '' Extra configuration options for Bosun. You should describe your diff --git a/nixos/modules/services/monitoring/cadvisor.nix b/nixos/modules/services/monitoring/cadvisor.nix index a67df158be47..8ae8b12056ce 100644 --- a/nixos/modules/services/monitoring/cadvisor.nix +++ b/nixos/modules/services/monitoring/cadvisor.nix @@ -90,6 +90,7 @@ in { ${optionalString cfg.storageDriverSecure "-storage_driver_secure"} ''} ''; + TimeoutStartSec=300; }; }; diff --git a/nixos/modules/services/monitoring/collectd.nix b/nixos/modules/services/monitoring/collectd.nix index 3c3d83c66ed0..641da60e9adc 100644 --- a/nixos/modules/services/monitoring/collectd.nix +++ b/nixos/modules/services/monitoring/collectd.nix @@ -9,7 +9,7 @@ let BaseDir "${cfg.dataDir}" PIDFile "${cfg.pidFile}" AutoLoadPlugin ${if cfg.autoLoadPlugin then "true" else "false"} - Hostname ${config.networking.hostName} + Hostname "${config.networking.hostName}" LoadPlugin syslog <Plugin "syslog"> @@ -108,7 +108,8 @@ in { }; preStart = '' - mkdir -m 0700 -p ${cfg.dataDir} + mkdir -p ${cfg.dataDir} + chmod 755 ${cfg.dataDir} install -D /dev/null ${cfg.pidFile} if [ "$(id -u)" = 0 ]; then chown -R ${cfg.user} ${cfg.dataDir}; diff --git a/nixos/modules/services/monitoring/graphite.nix b/nixos/modules/services/monitoring/graphite.nix index 08fc3f04dbfc..c5352e5887da 100644 --- a/nixos/modules/services/monitoring/graphite.nix +++ b/nixos/modules/services/monitoring/graphite.nix @@ -167,7 +167,7 @@ in { CACHE_TYPE: 'filesystem' CACHE_DIR: '/tmp/graphite-api-cache' ''; - type = types.str; + type = types.lines; }; }; @@ -387,7 +387,7 @@ in { systemd.services.carbonCache = let name = "carbon-cache"; in { description = "Graphite Data Storage Backend"; wantedBy = [ "multi-user.target" ]; - after = [ "network-interfaces.target" ]; + after = [ "network.target" ]; environment = carbonEnv; serviceConfig = { ExecStart = "${pkgs.pythonPackages.twisted}/bin/twistd ${carbonOpts name}"; @@ -410,7 +410,7 @@ in { enable = cfg.carbon.enableAggregator; description = "Carbon Data Aggregator"; wantedBy = [ "multi-user.target" ]; - after = [ "network-interfaces.target" ]; + after = [ "network.target" ]; environment = carbonEnv; serviceConfig = { ExecStart = "${pkgs.pythonPackages.twisted}/bin/twistd ${carbonOpts name}"; @@ -426,7 +426,7 @@ in { systemd.services.carbonRelay = let name = "carbon-relay"; in { description = "Carbon Data Relay"; wantedBy = [ "multi-user.target" ]; - after = [ "network-interfaces.target" ]; + after = [ "network.target" ]; environment = carbonEnv; serviceConfig = { ExecStart = "${pkgs.pythonPackages.twisted}/bin/twistd ${carbonOpts name}"; @@ -448,7 +448,7 @@ in { systemd.services.graphiteWeb = { description = "Graphite Web Interface"; wantedBy = [ "multi-user.target" ]; - after = [ "network-interfaces.target" ]; + after = [ "network.target" ]; path = [ pkgs.perl ]; environment = { PYTHONPATH = let @@ -501,7 +501,7 @@ in { systemd.services.graphiteApi = { description = "Graphite Api Interface"; wantedBy = [ "multi-user.target" ]; - after = [ "network-interfaces.target" ]; + after = [ "network.target" ]; environment = { PYTHONPATH = let aenv = pkgs.python.buildEnv.override { @@ -538,7 +538,7 @@ in { systemd.services.seyren = { description = "Graphite Alerting Dashboard"; wantedBy = [ "multi-user.target" ]; - after = [ "network-interfaces.target" "mongodb.service" ]; + after = [ "network.target" "mongodb.service" ]; environment = seyrenConfig; serviceConfig = { ExecStart = "${pkgs.seyren}/bin/seyren -httpPort ${toString cfg.seyren.port}"; @@ -561,7 +561,7 @@ in { systemd.services.graphitePager = { description = "Graphite Pager Alerting Daemon"; wantedBy = [ "multi-user.target" ]; - after = [ "network-interfaces.target" "redis.service" ]; + after = [ "network.target" "redis.service" ]; environment = { REDIS_URL = cfg.pager.redisUrl; GRAPHITE_URL = cfg.pager.graphiteUrl; @@ -585,7 +585,7 @@ in { serviceConfig = { ExecStart = '' ${pkgs.pythonPackages.graphite_beacon}/bin/graphite-beacon \ - --config ${pkgs.writeText "graphite-beacon.json" (builtins.toJSON cfg.beacon.config)} + --config=${pkgs.writeText "graphite-beacon.json" (builtins.toJSON cfg.beacon.config)} ''; User = "graphite"; Group = "graphite"; diff --git a/nixos/modules/services/monitoring/monit.nix b/nixos/modules/services/monitoring/monit.nix index 704693969a35..e07ffd2e8b54 100644 --- a/nixos/modules/services/monitoring/monit.nix +++ b/nixos/modules/services/monitoring/monit.nix @@ -36,11 +36,16 @@ in ]; systemd.services.monit = { - description = "Monit system watcher"; - after = [ "network-interfaces.target" ]; + description = "Pro-active monitoring utility for unix systems"; + after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; - script = "${pkgs.monit}/bin/monit -I -c /etc/monit.conf"; - serviceConfig.Restart = "always"; + serviceConfig = { + ExecStart = "${pkgs.monit}/bin/monit -I -c /etc/monit.conf"; + ExecStop = "${pkgs.monit}/bin/monit -c /etc/monit.conf quit"; + ExecReload = "${pkgs.monit}/bin/monit -c /etc/monit.conf reload"; + KillMode = "process"; + Restart = "always"; + }; }; }; } diff --git a/nixos/modules/services/monitoring/munin.nix b/nixos/modules/services/monitoring/munin.nix index 08ba161d38bd..a80565fa280b 100644 --- a/nixos/modules/services/monitoring/munin.nix +++ b/nixos/modules/services/monitoring/munin.nix @@ -100,6 +100,7 @@ in extraConfig = mkOption { default = ""; + type = types.lines; description = '' <filename>munin-node.conf</filename> extra configuration. See <link xlink:href='http://munin-monitoring.org/wiki/munin-node.conf' /> diff --git a/nixos/modules/services/monitoring/nagios.nix b/nixos/modules/services/monitoring/nagios.nix index f2f7710de9e7..4914c5db97d2 100644 --- a/nixos/modules/services/monitoring/nagios.nix +++ b/nixos/modules/services/monitoring/nagios.nix @@ -163,7 +163,7 @@ in description = "Nagios monitoring daemon"; path = [ pkgs.nagios ]; wantedBy = [ "multi-user.target" ]; - after = [ "network-interfaces.target" ]; + after = [ "network.target" ]; serviceConfig = { User = "nagios"; diff --git a/nixos/modules/services/monitoring/prometheus/alertmanager.nix b/nixos/modules/services/monitoring/prometheus/alertmanager.nix new file mode 100644 index 000000000000..da2cd02eaa3b --- /dev/null +++ b/nixos/modules/services/monitoring/prometheus/alertmanager.nix @@ -0,0 +1,116 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.services.prometheus.alertmanager; + mkConfigFile = pkgs.writeText "alertmanager.yml" (builtins.toJSON cfg.configuration); +in { + options = { + services.prometheus.alertmanager = { + enable = mkEnableOption "Prometheus Alertmanager"; + + user = mkOption { + type = types.str; + default = "nobody"; + description = '' + User name under which Alertmanager shall be run. + ''; + }; + + group = mkOption { + type = types.str; + default = "nogroup"; + description = '' + Group under which Alertmanager shall be run. + ''; + }; + + configuration = mkOption { + type = types.attrs; + default = {}; + description = '' + Alertmanager configuration as nix attribute set. + ''; + }; + + logFormat = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + If set use a syslog logger or JSON logging. + ''; + }; + + logLevel = mkOption { + type = types.enum ["debug" "info" "warn" "error" "fatal"]; + default = "warn"; + description = '' + Only log messages with the given severity or above. + ''; + }; + + webExternalUrl = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The URL under which Alertmanager is externally reachable (for example, if Alertmanager is served via a reverse proxy). + Used for generating relative and absolute links back to Alertmanager itself. + If the URL has a path portion, it will be used to prefix all HTTP endoints served by Alertmanager. + If omitted, relevant URL components will be derived automatically. + ''; + }; + + listenAddress = mkOption { + type = types.str; + default = ""; + description = '' + Address to listen on for the web interface and API. + ''; + }; + + port = mkOption { + type = types.int; + default = 9093; + description = '' + Port to listen on for the web interface and API. + ''; + }; + + 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.alertmanager = { + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + script = '' + ${pkgs.prometheus-alertmanager.bin}/bin/alertmanager \ + -config.file ${mkConfigFile} \ + -web.listen-address ${cfg.listenAddress}:${toString cfg.port} \ + -log.level ${cfg.logLevel} \ + ${optionalString (cfg.webExternalUrl != null) ''-web.external-url ${cfg.webExternalUrl} \''} + ${optionalString (cfg.logFormat != null) "-log.format ${cfg.logFormat}"} + ''; + + serviceConfig = { + User = cfg.user; + Group = cfg.group; + Restart = "always"; + PrivateTmp = true; + WorkingDirectory = "/tmp"; + ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + }; + }; + }; +} diff --git a/nixos/modules/services/monitoring/prometheus/blackbox-exporter.nix b/nixos/modules/services/monitoring/prometheus/blackbox-exporter.nix new file mode 100644 index 000000000000..7a343299c315 --- /dev/null +++ b/nixos/modules/services/monitoring/prometheus/blackbox-exporter.nix @@ -0,0 +1,67 @@ +{ 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; + 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"; + }; + }; + }; +} diff --git a/nixos/modules/services/monitoring/prometheus/default.nix b/nixos/modules/services/monitoring/prometheus/default.nix new file mode 100644 index 000000000000..a07445ce167c --- /dev/null +++ b/nixos/modules/services/monitoring/prometheus/default.nix @@ -0,0 +1,465 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.services.prometheus; + promUser = "prometheus"; + promGroup = "prometheus"; + + # Get a submodule without any embedded metadata: + _filter = x: filterAttrs (k: v: k != "_module") x; + + # Pretty-print JSON to a file + writePrettyJSON = name: x: + pkgs.runCommand name { } '' + echo '${builtins.toJSON x}' | ${pkgs.jq}/bin/jq . > $out + ''; + + # This becomes the main config file + promConfig = { + global = cfg.globalConfig; + rule_files = cfg.ruleFiles ++ [ + (pkgs.writeText "prometheus.rules" (concatStringsSep "\n" cfg.rules)) + ]; + scrape_configs = cfg.scrapeConfigs; + }; + + generatedPrometheusYml = writePrettyJSON "prometheus.yml" promConfig; + + prometheusYml = + if cfg.configText != null then + pkgs.writeText "prometheus.yml" cfg.configText + else generatedPrometheusYml; + + cmdlineArgs = cfg.extraFlags ++ [ + "-storage.local.path=${cfg.dataDir}/metrics" + "-config.file=${prometheusYml}" + "-web.listen-address=${cfg.listenAddress}" + "-alertmanager.notification-queue-capacity=${toString cfg.alertmanagerNotificationQueueCapacity}" + "-alertmanager.timeout=${toString cfg.alertmanagerTimeout}s" + (optionalString (cfg.alertmanagerURL != []) "-alertmanager.url=${concatStringsSep "," cfg.alertmanagerURL}") + ]; + + promTypes.globalConfig = types.submodule { + options = { + scrape_interval = mkOption { + type = types.str; + default = "1m"; + description = '' + How frequently to scrape targets by default. + ''; + }; + + scrape_timeout = mkOption { + type = types.str; + default = "10s"; + description = '' + How long until a scrape request times out. + ''; + }; + + evaluation_interval = mkOption { + type = types.str; + default = "1m"; + description = '' + How frequently to evaluate rules by default. + ''; + }; + + labels = mkOption { + type = types.attrsOf types.str; + default = {}; + description = '' + The labels to add to any timeseries that this Prometheus instance + scrapes. + ''; + }; + }; + }; + + promTypes.scrape_config = types.submodule { + options = { + job_name = mkOption { + type = types.str; + description = '' + The job name assigned to scraped metrics by default. + ''; + }; + scrape_interval = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + How frequently to scrape targets from this job. Defaults to the + globally configured default. + ''; + }; + scrape_timeout = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Per-target timeout when scraping this job. Defaults to the + globally configured default. + ''; + }; + metrics_path = mkOption { + type = types.str; + default = "/metrics"; + description = '' + The HTTP resource path on which to fetch metrics from targets. + ''; + }; + scheme = mkOption { + type = types.enum ["http" "https"]; + default = "http"; + description = '' + The URL scheme with which to fetch metrics from targets. + ''; + }; + basic_auth = mkOption { + type = types.nullOr (types.submodule { + options = { + username = mkOption { + type = types.str; + description = '' + HTTP username + ''; + }; + password = mkOption { + type = types.str; + description = '' + HTTP password + ''; + }; + }; + }); + default = null; + description = '' + Optional http login credentials for metrics scraping. + ''; + }; + dns_sd_configs = mkOption { + type = types.listOf promTypes.dns_sd_config; + default = []; + apply = x: map _filter x; + description = '' + List of DNS service discovery configurations. + ''; + }; + consul_sd_configs = mkOption { + type = types.listOf promTypes.consul_sd_config; + default = []; + apply = x: map _filter x; + description = '' + List of Consul service discovery configurations. + ''; + }; + file_sd_configs = mkOption { + type = types.listOf promTypes.file_sd_config; + default = []; + apply = x: map _filter x; + description = '' + List of file service discovery configurations. + ''; + }; + static_configs = mkOption { + type = types.listOf promTypes.static_config; + default = []; + apply = x: map _filter x; + description = '' + List of labeled target groups for this job. + ''; + }; + relabel_configs = mkOption { + type = types.listOf promTypes.relabel_config; + default = []; + apply = x: map _filter x; + description = '' + List of relabel configurations. + ''; + }; + }; + }; + + promTypes.static_config = types.submodule { + options = { + targets = mkOption { + type = types.listOf types.str; + description = '' + The targets specified by the target group. + ''; + }; + labels = mkOption { + type = types.attrsOf types.str; + default = {}; + description = '' + Labels assigned to all metrics scraped from the targets. + ''; + }; + }; + }; + + promTypes.dns_sd_config = types.submodule { + options = { + names = mkOption { + type = types.listOf types.str; + description = '' + A list of DNS SRV record names to be queried. + ''; + }; + refresh_interval = mkOption { + type = types.str; + default = "30s"; + description = '' + The time after which the provided names are refreshed. + ''; + }; + }; + }; + + promTypes.consul_sd_config = types.submodule { + options = { + server = mkOption { + type = types.str; + description = "Consul server to query."; + }; + token = mkOption { + type = types.nullOr types.str; + description = "Consul token"; + }; + datacenter = mkOption { + type = types.nullOr types.str; + description = "Consul datacenter"; + }; + scheme = mkOption { + type = types.nullOr types.str; + description = "Consul scheme"; + }; + username = mkOption { + type = types.nullOr types.str; + description = "Consul username"; + }; + password = mkOption { + type = types.nullOr types.str; + description = "Consul password"; + }; + + services = mkOption { + type = types.listOf types.str; + description = '' + A list of services for which targets are retrieved. + ''; + }; + tag_separator = mkOption { + type = types.str; + default = ","; + description = '' + The string by which Consul tags are joined into the tag label. + ''; + }; + }; + }; + + promTypes.file_sd_config = types.submodule { + options = { + files = mkOption { + type = types.listOf types.str; + description = '' + Patterns for files from which target groups are extracted. Refer + to the Prometheus documentation for permitted filename patterns + and formats. + + ''; + }; + refresh_interval = mkOption { + type = types.str; + default = "30s"; + description = '' + Refresh interval to re-read the files. + ''; + }; + }; + }; + + promTypes.relabel_config = types.submodule { + options = { + source_labels = mkOption { + type = types.listOf types.str; + description = '' + The source labels select values from existing labels. Their content + is concatenated using the configured separator and matched against + the configured regular expression. + ''; + }; + separator = mkOption { + type = types.str; + default = ";"; + description = '' + Separator placed between concatenated source label values. + ''; + }; + target_label = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Label to which the resulting value is written in a replace action. + It is mandatory for replace actions. + ''; + }; + regex = mkOption { + type = types.str; + default = "(.*)"; + description = '' + Regular expression against which the extracted value is matched. + ''; + }; + replacement = mkOption { + type = types.str; + default = "$1"; + description = '' + Replacement value against which a regex replace is performed if the + regular expression matches. + ''; + }; + action = mkOption { + type = types.enum ["replace" "keep" "drop"]; + default = "replace"; + description = '' + Action to perform based on regex matching. + ''; + }; + }; + }; + +in { + options = { + services.prometheus = { + + enable = mkOption { + type = types.bool; + default = false; + description = '' + Enable the Prometheus monitoring daemon. + ''; + }; + + listenAddress = mkOption { + type = types.str; + default = "0.0.0.0:9090"; + description = '' + Address to listen on for the web interface, API, and telemetry. + ''; + }; + + dataDir = mkOption { + type = types.path; + default = "/var/lib/prometheus"; + description = '' + Directory to store Prometheus metrics data. + ''; + }; + + extraFlags = mkOption { + type = types.listOf types.str; + default = []; + description = '' + Extra commandline options when launching Prometheus. + ''; + }; + + configText = mkOption { + type = types.nullOr types.lines; + default = null; + description = '' + If non-null, this option defines the text that is written to + prometheus.yml. If null, the contents of prometheus.yml is generated + from the structured config options. + ''; + }; + + globalConfig = mkOption { + type = promTypes.globalConfig; + default = {}; + apply = _filter; + description = '' + Parameters that are valid in all configuration contexts. They + also serve as defaults for other configuration sections + ''; + }; + + rules = mkOption { + type = types.listOf types.str; + default = []; + description = '' + Alerting and/or Recording rules to evaluate at runtime. + ''; + }; + + ruleFiles = mkOption { + type = types.listOf types.path; + default = []; + description = '' + Any additional rules files to include in this configuration. + ''; + }; + + scrapeConfigs = mkOption { + type = types.listOf promTypes.scrape_config; + default = []; + apply = x: map _filter x; + description = '' + A list of scrape configurations. + ''; + }; + + alertmanagerURL = mkOption { + type = types.listOf types.str; + default = []; + description = '' + List of Alertmanager URLs to send notifications to. + ''; + }; + + alertmanagerNotificationQueueCapacity = mkOption { + type = types.int; + default = 10000; + description = '' + The capacity of the queue for pending alert manager notifications. + ''; + }; + + alertmanagerTimeout = mkOption { + type = types.int; + default = 10; + description = '' + Alert manager HTTP API timeout (in seconds). + ''; + }; + }; + }; + + config = mkIf cfg.enable { + users.extraGroups.${promGroup}.gid = config.ids.gids.prometheus; + users.extraUsers.${promUser} = { + description = "Prometheus daemon user"; + uid = config.ids.uids.prometheus; + group = promGroup; + home = cfg.dataDir; + createHome = true; + }; + systemd.services.prometheus = { + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + script = '' + #!/bin/sh + exec ${pkgs.prometheus}/bin/prometheus \ + ${concatStringsSep " \\\n " cmdlineArgs} + ''; + serviceConfig = { + User = promUser; + Restart = "always"; + WorkingDirectory = cfg.dataDir; + }; + }; + }; +} diff --git a/nixos/modules/services/monitoring/prometheus/json-exporter.nix b/nixos/modules/services/monitoring/prometheus/json-exporter.nix new file mode 100644 index 000000000000..6bc56df9834b --- /dev/null +++ b/nixos/modules/services/monitoring/prometheus/json-exporter.nix @@ -0,0 +1,74 @@ +{ 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"; + }; + }; + }; +} diff --git a/nixos/modules/services/monitoring/prometheus/nginx-exporter.nix b/nixos/modules/services/monitoring/prometheus/nginx-exporter.nix new file mode 100644 index 000000000000..1ccafee3b18b --- /dev/null +++ b/nixos/modules/services/monitoring/prometheus/nginx-exporter.nix @@ -0,0 +1,78 @@ +{ 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"; + }; + }; + }; +} diff --git a/nixos/modules/services/monitoring/prometheus/node-exporter.nix b/nixos/modules/services/monitoring/prometheus/node-exporter.nix new file mode 100644 index 000000000000..0cf0b85afb57 --- /dev/null +++ b/nixos/modules/services/monitoring/prometheus/node-exporter.nix @@ -0,0 +1,81 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.services.prometheus.nodeExporter; + cmdlineArgs = cfg.extraFlags ++ [ + "-web.listen-address=${cfg.listenAddress}" + ]; +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, additionally to the defaults. + ''; + }; + + 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 \ + ${optionalString (cfg.enabledCollectors != []) + ''-collectors.enabled ${concatStringsSep "," cfg.enabledCollectors}''} \ + -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"; + }; + }; + }; +} diff --git a/nixos/modules/services/monitoring/prometheus/snmp-exporter.nix b/nixos/modules/services/monitoring/prometheus/snmp-exporter.nix new file mode 100644 index 000000000000..fe33f8c1f04d --- /dev/null +++ b/nixos/modules/services/monitoring/prometheus/snmp-exporter.nix @@ -0,0 +1,127 @@ +{ 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"; + }; + }; + }; +} diff --git a/nixos/modules/services/monitoring/prometheus/varnish-exporter.nix b/nixos/modules/services/monitoring/prometheus/varnish-exporter.nix new file mode 100644 index 000000000000..143ebb62aeac --- /dev/null +++ b/nixos/modules/services/monitoring/prometheus/varnish-exporter.nix @@ -0,0 +1,61 @@ +{ 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"; + }; + }; + }; +} diff --git a/nixos/modules/services/monitoring/riemann-tools.nix b/nixos/modules/services/monitoring/riemann-tools.nix index ce277f09464a..de858813a762 100644 --- a/nixos/modules/services/monitoring/riemann-tools.nix +++ b/nixos/modules/services/monitoring/riemann-tools.nix @@ -50,6 +50,7 @@ in { systemd.services.riemann-health = { wantedBy = [ "multi-user.target" ]; + path = [ procps ]; serviceConfig = { User = "riemanntools"; ExecStart = "${healthLauncher}/bin/riemann-health"; diff --git a/nixos/modules/services/monitoring/smartd.nix b/nixos/modules/services/monitoring/smartd.nix index b67519b3424c..99fd5c4d3674 100644 --- a/nixos/modules/services/monitoring/smartd.nix +++ b/nixos/modules/services/monitoring/smartd.nix @@ -197,8 +197,7 @@ in devices = mkOption { default = []; example = [ { device = "/dev/sda"; } { device = "/dev/sdb"; options = "-d sat"; } ]; - type = types.listOf types.optionSet; - options = [ smartdOpts ]; + type = with types; listOf (submodule smartdOpts); description = "List of devices to monitor."; }; diff --git a/nixos/modules/services/monitoring/telegraf.nix b/nixos/modules/services/monitoring/telegraf.nix new file mode 100644 index 000000000000..49dc9d8143e6 --- /dev/null +++ b/nixos/modules/services/monitoring/telegraf.nix @@ -0,0 +1,71 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.telegraf; + + configFile = pkgs.runCommand "config.toml" { + buildInputs = [ pkgs.remarshal ]; + } '' + remarshal -if json -of toml \ + < ${pkgs.writeText "config.json" (builtins.toJSON cfg.extraConfig)} \ + > $out + ''; +in { + ###### interface + options = { + services.telegraf = { + enable = mkEnableOption "telegraf server"; + + package = mkOption { + default = pkgs.telegraf; + defaultText = "pkgs.telegraf"; + description = "Which telegraf derivation to use"; + type = types.package; + }; + + extraConfig = mkOption { + default = {}; + description = "Extra configuration options for telegraf"; + type = types.attrs; + example = { + outputs = { + influxdb = { + urls = ["http://localhost:8086"]; + database = "telegraf"; + }; + }; + inputs = { + statsd = { + service_address = ":8125"; + delete_timings = true; + }; + }; + }; + }; + }; + }; + + + ###### implementation + config = mkIf config.services.telegraf.enable { + systemd.services.telegraf = { + description = "Telegraf Agent"; + wantedBy = [ "multi-user.target" ]; + after = [ "network-online.target" ]; + serviceConfig = { + ExecStart=''${cfg.package}/bin/telegraf -config "${configFile}"''; + ExecReload="${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + User = "telegraf"; + Restart = "on-failure"; + }; + }; + + users.extraUsers = [{ + name = "telegraf"; + uid = config.ids.uids.telegraf; + description = "telegraf daemon user"; + }]; + }; +} diff --git a/nixos/modules/services/monitoring/ups.nix b/nixos/modules/services/monitoring/ups.nix index 5f80d547dbcb..c4c4ed227b35 100644 --- a/nixos/modules/services/monitoring/ups.nix +++ b/nixos/modules/services/monitoring/ups.nix @@ -169,8 +169,7 @@ in monitoring directly. These are usually attached to serial ports, but USB devices are also supported. ''; - type = types.attrsOf types.optionSet; - options = [ upsOptions ]; + type = with types; attrsOf (submodule upsOptions); }; }; @@ -182,7 +181,8 @@ in systemd.services.upsmon = { description = "Uninterruptible Power Supplies (Monitor)"; - wantedBy = [ "ip-up.target" ]; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; serviceConfig.Type = "forking"; script = "${pkgs.nut}/sbin/upsmon"; environment.NUT_CONFPATH = "/etc/nut/"; @@ -191,8 +191,8 @@ in systemd.services.upsd = { description = "Uninterruptible Power Supplies (Daemon)"; + after = [ "network.target" "upsmon.service" ]; wantedBy = [ "multi-user.target" ]; - after = [ "network-interfaces.target" "upsmon.service" ]; serviceConfig.Type = "forking"; # TODO: replace 'root' by another username. script = "${pkgs.nut}/sbin/upsd -u root"; @@ -202,8 +202,8 @@ in systemd.services.upsdrv = { description = "Uninterruptible Power Supplies (Register all UPS)"; - wantedBy = [ "multi-user.target" ]; after = [ "upsd.service" ]; + wantedBy = [ "multi-user.target" ]; # TODO: replace 'root' by another username. script = ''${pkgs.nut}/bin/upsdrvctl -u root start''; serviceConfig = { diff --git a/nixos/modules/services/monitoring/zabbix-agent.nix b/nixos/modules/services/monitoring/zabbix-agent.nix index a943075be0c4..88a63b4bf161 100644 --- a/nixos/modules/services/monitoring/zabbix-agent.nix +++ b/nixos/modules/services/monitoring/zabbix-agent.nix @@ -53,6 +53,7 @@ in extraConfig = mkOption { default = ""; + type = types.lines; description = '' Configuration that is injected verbatim into the configuration file. ''; |