{ lib, config, pkgs, ... }: let cfg = config.services.vm_grafana; in { options.services.vm_grafana = { enable = lib.mkEnableOption "Enable minimal config"; vm_ip = lib.mkOption { type = lib.types.str; description = "The VM IP address"; }; proxy_ip = lib.mkOption { type = lib.types.str; description = "The Nginx proxy IP address"; }; pgsql_ip = lib.mkOption { type = lib.types.str; description = "The PostgreSQL host IP address"; }; }; config = lib.mkIf cfg.enable { age.secrets = { grafana-lapi-key = { file = ../../secrets/grafana-lapi-key.age; owner = "crowdsec"; }; grafana-db = { file = ./secrets/grafana-db.age; owner = "grafana"; }; grafana-oauth_secret = { file = ./secrets/grafana-oauth_secret.age; owner = "grafana"; }; kuma-token.file = ./secrets/kuma-token.age; }; services = { crowdsec = { settings.lapi.credentialsFile = "${config.age.secrets.grafana-lapi-key.path}"; hub.collections = [ "LePresidente/grafana" ]; localConfig = { acquisitions = [ { source = "journalctl"; journalctl_filter = [ "_SYSTEMD_UNIT=grafana.service" ]; labels = { type = "journald"; }; } ]; }; }; influxdb2 = { enable = true; }; grafana = { enable = true; settings = { server = { protocol = "http"; http_addr = "${cfg.vm_ip}"; http_port = 3000; domain = "logs.le43.eu"; root_url = "https://logs.le43.eu"; serve_from_sub_path = false; }; database = { type = "postgres"; host = "${cfg.pgsql_ip}:5432"; name = "grafana"; user = "grafana"; password = "\$__file{${config.age.secrets.grafana-db.path}}"; }; "auth.generic_oauth" = { enabled = "true"; name = "authentik"; allow_sign_up = "true"; client_id = "9HV82G8F92Jcbw4nP8eppMcPpLcAw5uYpejfReLy"; client_secret = "\$__file{${config.age.secrets.grafana-oauth_secret.path}}"; scopes = "openid email profile"; auth_url = "https://authentik.le43.eu/application/o/authorize/"; token_url = "https://authentik.le43.eu/application/o/token/"; api_url = "https://authentik.le43.eu/application/o/userinfo/"; role_attribute_path = "contains(groups, 'admin') && 'Admin' || contains(groups, 'admin') && 'Editor' || 'Viewer';role_attribute_strict = false"; allow_assign_grafana_admin = "true"; }; }; }; prometheus = { enable = true; port = 9001; scrapeConfigs = [ { job_name = "kuma"; scrape_interval = "30s"; scheme = "http"; static_configs = [ { targets = ["192.168.1.90:3001"]; } ]; basic_auth.username = "tbarnouin"; basic_auth.password_file = config.age.secrets.kuma-token.path; } { job_name = "grafana"; static_configs = [ { targets = ["127.0.0.1:9002"]; } ]; } { job_name = "opportunity"; static_configs = [ { targets = ["192.168.1.125:9100"]; } ]; } { job_name = "nginx"; static_configs = [ { targets = ["${cfg.proxy_ip}:9002"]; } ]; } { job_name = "redis"; static_configs = [ { targets = ["192.168.1.16:9002"]; } ]; } { job_name = "ingenuity"; static_configs = [ { targets = ["192.168.1.90:9100"]; } ]; } { job_name = "gitea"; static_configs = [ { targets = ["192.168.1.14:9002"]; } ]; } { job_name = "postgresql"; static_configs = [ { targets = ["192.168.1.13:9002"]; } ]; } { job_name = "nextcloud"; static_configs = [ { targets = ["192.168.1.45:9100"]; } ]; } { job_name = "jellyfin"; static_configs = [ { targets = ["192.168.1.42:9002"]; } ]; } { job_name = "jellyfin_metrics"; metrics_path = "/metrics"; static_configs = [ { targets = ["192.168.1.42:8096"]; } ]; } { job_name = "crowdsec_authentik"; metrics_path = "/metrics"; static_configs = [ { targets = ["192.168.1.125:6060"]; } ]; } { job_name = "crowdsec_nextcloud"; metrics_path = "/metrics"; static_configs = [ { targets = ["192.168.1.45:6060"]; } ]; } { job_name = "crowdsec_nginx"; metrics_path = "/metrics"; static_configs = [ { targets = ["${cfg.proxy_ip}:6060"]; } ]; } { job_name = "crowdsec_jellyfin"; metrics_path = "/metrics"; static_configs = [ { targets = ["192.168.1.42:6060"]; } ]; } { job_name = "crowdsec_forgejo"; metrics_path = "/metrics"; static_configs = [ { targets = ["192.168.1.14:6060"]; } ]; } { job_name = "crowdsec_grafana"; metrics_path = "/metrics"; static_configs = [ { targets = ["192.168.1.27:6060"]; } ]; } { job_name = "crowdsec_postgresql"; metrics_path = "/metrics"; static_configs = [ { targets = ["192.168.1.13:6060"]; } ]; } ]; }; loki = { enable = true; configuration = { auth_enabled = false; server = { http_listen_port = 3100; grpc_listen_port = 9096; }; common = { instance_addr = "0.0.0.0"; path_prefix = "/tmp/loki"; storage.filesystem = { chunks_directory = "/tmp/loki/chunks"; rules_directory = "/tmp/loki/rules"; }; replication_factor = 1; ring.kvstore.store = "inmemory"; }; compactor = { working_directory = "/var/lib/loki"; compactor_ring = { kvstore = { store = "inmemory"; }; }; }; query_range.results_cache.cache.embedded_cache = { enabled = true; max_size_mb = 100; }; schema_config.configs = [ { from = "2025-05-13"; store = "tsdb"; object_store = "filesystem"; schema = "v13"; index = { prefix = "index_"; period = "24h"; }; } ]; ruler.alertmanager_url = "http://localhost:9093"; analytics.reporting_enabled = false; }; }; promtail = { enable = true; configuration = { server = { http_listen_port = 3101; grpc_listen_port = 9095; }; positions = { filename = "/tmp/positions.yaml"; }; clients = [ { url = "http://127.0.0.1:3100/loki/api/v1/push"; } ]; scrape_configs = [ { job_name = "syslog"; syslog = { listen_address = "0.0.0.0:1514"; listen_protocol = "tcp"; idle_timeout = "60s"; labels = { job = "syslog"; }; }; relabel_configs = [ { source_labels = ["__syslog_message_hostname"]; target_label = "host"; } { source_labels = ["__syslog_message_hostname"]; target_label = "hostname"; } { source_labels = ["__syslog_message_severity"]; target_label = "level"; } { source_labels = ["__syslog_message_app_name"]; target_label = "application"; } { source_labels = ["__syslog_message_facility"]; target_label = "facility"; } { source_labels = ["__syslog_connection_hostname"]; target_label = "connection_hostname"; } ]; } ]; }; }; }; # Open ports in the firewall. networking.firewall.allowedTCPPorts = [3000 3100 3101 8086 9001 1514 514]; networking.firewall.allowedUDPPorts = [514]; }; }