{ config, lib, pkgs, ... }: with lib; let inherit (lib.strings) concatStringsSep; cfg = config.fudo.prometheus; fudo-cfg = config.fudo.common; in { options.fudo.prometheus = { enable = mkEnableOption "Fudo Prometheus Data-Gathering Server"; service-discovery-dns = mkOption { type = with types; attrsOf (listOf str); description = '' A map of exporter type to a list of domains to use for service discovery. ''; example = { node = [ "node._metrics._tcp.my-domain.com" ]; postfix = [ "postfix._metrics._tcp.my-domain.com" ]; }; default = { dovecot = []; node = []; postfix = []; rspamd = []; }; }; static-targets = mkOption { type = with types; attrsOf (listOf str); description = '' A map of exporter type to a list of host:ports from which to collect metrics. ''; example = { node = [ "my-host.my-domain:1111" ]; }; default = { dovecot = []; node = []; postfix = []; rspamd = []; }; }; docker-hosts = mkOption { type = with types; listOf str; description = '' A list of explicit docker targets from which to gather node data. ''; default = []; }; push-url = mkOption { type = with types; nullOr str; description = '' The that services can use to manually push data. ''; default = null; }; push-address = mkOption { type = with types; nullOr str; description = '' The address on which to listen for incoming data. ''; default = null; }; hostname = mkOption { type = with types; str; description = "The hostname upon which Prometheus will serve."; example = "my-metrics-server.fudo.org"; }; }; config = mkIf cfg.enable { security.acme.certs.${cfg.hostname}.email = fudo-cfg.admin-email; services.nginx = { enable = true; virtualHosts = { "${cfg.hostname}" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://127.0.0.1:9090"; extraConfig = '' proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-By $server_addr:$server_port; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; ${optionalString ((length fudo-cfg.local-networks) > 0) (concatStringsSep "\n" (map (network: "allow ${network};") fudo-cfg.local-networks)) + "\ndeny all;"} ''; }; }; }; }; services.prometheus = { enable = true; webExternalUrl = "https://${cfg.hostname}"; listenAddress = "127.0.0.1:9090"; scrapeConfigs = [ { job_name = "docker"; honor_labels = false; static_configs = [ { targets = cfg.docker-hosts; } ]; } { job_name = "node"; scheme = "https"; metrics_path = "/metrics/node"; honor_labels = false; dns_sd_configs = [ { names = cfg.service-discovery-dns.node; } ]; static_configs = [ { targets = cfg.static-targets.node; } ]; } { job_name = "dovecot"; scheme = "https"; metrics_path = "/metrics/dovecot"; honor_labels = false; dns_sd_configs = [ { names = cfg.service-discovery-dns.dovecot; } ]; static_configs = [ { targets = cfg.static-targets.dovecot; } ]; } { job_name = "postfix"; scheme = "https"; metrics_path = "/metrics/postfix"; honor_labels = false; dns_sd_configs = [ { names = cfg.service-discovery-dns.postfix; } ]; static_configs = [ { targets = cfg.static-targets.postfix; } ]; } { job_name = "rspamd"; scheme = "https"; metrics_path = "/metrics/rspamd"; honor_labels = false; dns_sd_configs = [ { names = cfg.service-discovery-dns.rspamd; } ]; static_configs = [ { targets = cfg.static-targets.rspamd; } ]; } ]; pushgateway = { enable = if (cfg.push-url != null) then true else false; web = { external-url = if cfg.push-url == null then cfg.push-address else cfg.push-url; listen-address = cfg.push-address; }; }; }; }; }