{ config, lib, pkgs, ... }: let cfg = config.monitoring; in { options.monitoring = { grafanaUiPort = lib.mkOption { type = lib.types.int; }; lokiPort = lib.mkOption { type = lib.types.int; }; alloyUiPort = lib.mkOption { type = lib.types.int; }; prometheusExporterPort = lib.mkOption { type = lib.types.int; }; }; config = { services.grafana = { enable = true; settings = { server = { http_addr = "0.0.0.0"; http_port = cfg.grafanaUiPort; }; }; provision = { enable = true; datasources.settings.datasources = [ { name = "Prometheus"; type = "prometheus"; url = "http://${config.services.prometheus.listenAddress}:${toString config.services.prometheus.port}"; } { name = "Loki"; type = "loki"; access = "proxy"; url = "http://127.0.0.1:${toString cfg.lokiPort}"; } ]; }; }; services.prometheus = { enable = true; exporters.node = { enable = true; enabledCollectors = [ "systemd" ]; port = cfg.prometheusExporterPort; }; scrapeConfigs = [ { job_name = "node"; static_configs = [{ targets = [ "localhost:${toString cfg.prometheusExporterPort}" ]; }]; } ]; }; services.loki = { enable = true; configuration = { server.http_listen_port = cfg.lokiPort; auth_enabled = false; ingester = { lifecycler = { address = "127.0.0.1"; ring = { kvstore.store = "inmemory"; replication_factor = 1; }; }; }; schema_config = { configs = [{ store = "tsdb"; object_store = "filesystem"; schema = "v13"; index = { prefix = "index_"; period = "24h"; }; }]; }; storage_config = { tsdb_shipper = { active_index_directory = "/var/lib/loki/tsdb-active"; cache_location = "/var/lib/loki/tsdb-cache"; }; }; compactor = { working_directory = "/var/lib/loki"; }; }; }; services.alloy = { enable = true; extraFlags = ["--server.http.listen-addr=0.0.0.0:${toString cfg.alloyUiPort}"]; # TODO: submit PR to nixpkgs so that the alloy config can be specified as a JSON expression configPath = pkgs.writeText "config.alloy" '' loki.source.journal "journal" { max_age = "12h0m0s" relabel_rules = discovery.relabel.journal.rules forward_to = [loki.write.default.receiver] labels = { host = "tente", job = "systemd-journal", } } discovery.relabel "journal" { targets = [] rule { source_labels = ["__journal__systemd_unit"] target_label = "unit" } } loki.write "default" { endpoint { url = "http://127.0.0.1:${toString cfg.lokiPort}/loki/api/v1/push" } external_labels = {} } ''; }; }; }