{ config, lib, ... }: let inherit (lib) types mkOption mkDefault; 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."; }; }; }); }; allExporters = mkOption { internal = true; description = "The full list of scraping-relevant settings of all exporters, extra or built-in."; type = types.attrsOf (types.submodule { port = mkOption { type = types.int; }; listenAddress = mkOption { type = types.str; }; extraSettings = mkOption { type = types.anything; default = {}; }; }); }; }; config = { systemd.services = 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; services.prometheus.allExporters = lib.mapAttrs (name: exporter: { inherit (exporter) listenAddress port; }) (config.services.prometheus.exporters ++ config.services.prometheus.extraExporters); }; }