{config, ...}: let serviceName = "grafana"; servicePort = config.m3ta.ports.get serviceName; prometheusPort = config.m3ta.ports.get "prometheus"; in { services.grafana = { enable = true; settings = { server = { http_addr = "127.0.0.1"; http_port = servicePort; domain = "g.l.az-gruppe.com"; root_url = "https://g.l.az-gruppe.com"; serve_from_sub_path = false; }; database = { type = "postgres"; host = "127.0.0.1"; name = "grafana"; user = "grafana"; password = "$__file{${config.age.secrets.grafana-db-password.path}}"; ssl_mode = "disable"; }; security = { admin_user = "admin"; # Grafana file-provider: $__file{} reads the raw secret from the file. # The agenix secrets must contain ONLY the raw value (no KEY= prefix). admin_password = "$__file{${config.age.secrets.grafana-admin-pw.path}}"; secret_key = "$__file{${config.age.secrets.grafana-secret-key.path}}"; disable_gravatar = true; }; }; provision = { datasources.settings.datasources = [ { name = "Prometheus"; uid = "prometheus"; type = "prometheus"; url = "http://localhost:${toString prometheusPort}"; isDefault = true; access = "proxy"; jsonData.timeInterval = "15s"; } # Phase 3: add Loki datasource here once services.loki is enabled. ]; dashboards.settings.providers = [ { name = "default"; options.path = "/etc/grafana-dashboards"; } ]; }; }; # Dashboards directory (Phase 1: empty placeholder, JSON files added later) environment.etc."grafana-dashboards".source = ./. + "/dashboards"; systemd.services.grafana = { after = ["postgresql.service"]; wants = ["postgresql.service"]; }; # Traefik configuration specific to grafana services.traefik.dynamicConfigOptions.http = { services.${serviceName}.loadBalancer.servers = [ { url = "http://localhost:${toString servicePort}/"; } ]; routers.${serviceName} = { rule = "Host(`g.l.az-gruppe.com`)"; tls = { certResolver = "ionos"; }; service = serviceName; entrypoints = "websecure"; }; }; }