{ pkgs, config, lib, ... }: let inherit (lib) types mkOption mkDefault; yaml = pkgs.formats.yaml { }; in { options = { services.prometheus = { extraExporters = mkOption { type = types.attrsOf ( types.submodule { options = { port = mkOption { type = types.int; description = "The port on which this exporter listens."; }; listenAddress = mkOption { type = types.str; default = "127.0.0.1"; description = "Address to listen on."; }; serviceOpts = mkOption { type = types.attrs; description = "An attrset to be merged with the exporter's systemd service."; }; }; } ); }; }; services.victoriametrics.scrapeConfigs = mkOption { type = types.attrsOf ( types.submodule ( { name, self, ... }: { options = { job_name = mkOption { type = types.str; default = name; }; extraSettings = mkOption { type = types.anything; description = '' Other settings to set for this scrape config. ''; default = { }; }; targets = mkOption { type = types.listOf types.str; description = lib.mdDoc '' Addresses scrape targets for this config listen on. Shortcut for `static_configs = lib.singleton {targets = [];}` ''; default = [ ]; }; static_configs = mkOption { default = [ ]; type = types.listOf ( types.submodule { options = { targets = mkOption { type = types.listOf types.str; description = lib.mdDoc '' The addresses scrape targets for this config listen on. Must in `listenAddress:port` format. ''; }; labels = mkOption { type = types.attrsOf types.str; description = lib.mdDoc '' Labels to apply to all targets defined for this static config. ''; default = { }; }; }; } ); }; }; } ) ); }; }; config = { systemd.services = lib.mkMerge [ (lib.mapAttrs' ( name: exporter: lib.nameValuePair "prometheus-${name}-exporter" ( lib.mkMerge [ { # Shamelessly copied from upstream because the upstream # module is an intractable mess wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; serviceConfig.Restart = mkDefault "always"; serviceConfig.PrivateTmp = mkDefault true; serviceConfig.WorkingDirectory = mkDefault /tmp; serviceConfig.DynamicUser = mkDefault true; # Hardening serviceConfig.CapabilityBoundingSet = mkDefault [ "" ]; serviceConfig.DeviceAllow = [ "" ]; serviceConfig.LockPersonality = true; serviceConfig.MemoryDenyWriteExecute = true; serviceConfig.NoNewPrivileges = true; serviceConfig.PrivateDevices = mkDefault true; serviceConfig.ProtectClock = mkDefault true; serviceConfig.ProtectControlGroups = true; serviceConfig.ProtectHome = true; serviceConfig.ProtectHostname = true; serviceConfig.ProtectKernelLogs = true; serviceConfig.ProtectKernelModules = true; serviceConfig.ProtectKernelTunables = true; serviceConfig.ProtectSystem = mkDefault "strict"; serviceConfig.RemoveIPC = true; serviceConfig.RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; serviceConfig.RestrictNamespaces = true; serviceConfig.RestrictRealtime = true; serviceConfig.RestrictSUIDSGID = true; serviceConfig.SystemCallArchitectures = "native"; serviceConfig.UMask = "0077"; } exporter.serviceOpts ] ) ) config.services.prometheus.extraExporters) { vmagent-scrape-exporters = let listenAddress = config.services.victoriametrics.listenAddress; vmAddr = (lib.optionalString (lib.hasPrefix ":" listenAddress) "127.0.0.1") + listenAddress; promscrape = yaml.generate "prometheus.yml" { scrape_configs = lib.mapAttrsToList ( _: scrape: lib.recursiveUpdate { inherit (scrape) job_name; static_configs = scrape.static_configs ++ lib.optional (scrape.targets != [ ]) { targets = scrape.targets; }; } scrape.extraSettings ) config.services.victoriametrics.scrapeConfigs; }; in { enable = true; path = [ pkgs.victoriametrics ]; wantedBy = [ "multi-user.target" ]; after = [ "network.target" "victoriametrics.service" ]; serviceConfig = { ExecStart = [ (lib.concatStringsSep " " [ "${pkgs.victoriametrics}/bin/vmagent" "-promscrape.config=${promscrape}" "-remoteWrite.url=http://${vmAddr}/api/v1/write" "-remoteWrite.tmpDataPath=%t/vmagent" ]) ]; SupplementaryGroups = "metrics"; DynamicUser = true; RuntimeDirectory = "vmagent"; CapabilityBoundingSet = [ "" ]; DeviceAllow = [ "" ]; LockPersonality = true; MemoryDenyWriteExecute = true; NoNewPrivileges = true; PrivateDevices = true; ProtectClock = true; ProtectControlGroups = true; ProtectHome = true; ProtectHostname = true; ProtectKernelLogs = true; ProtectKernelModules = true; ProtectKernelTunables = true; ProtectSystem = "strict"; RemoveIPC = true; RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; RestrictNamespaces = true; RestrictRealtime = true; RestrictSUIDSGID = true; SystemCallArchitectures = "native"; UMask = "0077"; }; }; } ]; users.groups.metrics = { }; services.victoriametrics.scrapeConfigs = let allExporters = lib.mapAttrs (name: exporter: { inherit (exporter) listenAddress port; }) ( (lib.filterAttrs ( _: exporter: builtins.isAttrs exporter && exporter.enable ) config.services.prometheus.exporters) // config.services.prometheus.extraExporters ); in lib.mapAttrs (_: exporter: { targets = [ "${exporter.listenAddress}:${toString exporter.port}" ]; }) allExporters; }; }