.dotfiles/modules/nixos/server/monitoring.nix
2025-12-02 00:57:35 +01:00

249 lines
8.2 KiB
Nix

{ self, lib, config, globals, dns, confLib, ... }:
let
inherit (confLib.gen { name = "grafana"; port = 3000; }) servicePort serviceName serviceUser serviceGroup serviceDomain serviceAddress serviceProxy proxyAddress4 proxyAddress6;
prometheusPort = 9090;
prometheusUser = "prometheus";
prometheusGroup = prometheusUser;
grafanaUpstream = "grafana";
prometheusUpstream = "prometheus";
prometheusWebRoot = "prometheus";
kanidmDomain = globals.services.kanidm.domain;
inherit (config.swarselsystems) sopsFile;
in
{
options.swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
config = lib.mkIf config.swarselmodules.server.${serviceName} {
nodes.stoicclub.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = {
"${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
};
sops = {
secrets = {
grafana-admin-pw = { inherit sopsFile; owner = serviceUser; group = serviceGroup; mode = "0440"; };
prometheus-admin-pw = { inherit sopsFile; owner = serviceUser; group = serviceGroup; mode = "0440"; };
kanidm-grafana-client = { inherit sopsFile; owner = serviceUser; group = serviceGroup; mode = "0440"; };
prometheus-admin-hash = { sopsFile = self + /secrets/winters/secrets2.yaml; owner = prometheusUser; group = prometheusGroup; mode = "0440"; };
};
templates = {
"web-config" = {
content = ''
basic_auth_users:
admin: ${config.sops.placeholder.prometheus-admin-hash}
'';
owner = prometheusUser;
group = prometheusGroup;
mode = "0440";
};
};
};
users = {
users = {
nextcloud-exporter = {
extraGroups = [ "nextcloud" ];
};
${serviceUser} = {
extraGroups = [ "users" ];
};
};
};
networking.firewall.allowedTCPPorts = [ servicePort prometheusPort ];
topology.self.services.prometheus.info = "https://${serviceDomain}/${prometheusWebRoot}";
globals.services.${serviceName} = {
domain = serviceDomain;
inherit proxyAddress4 proxyAddress6;
};
services = {
${serviceName} = {
enable = true;
dataDir = "/Vault/data/${serviceName}";
provision = {
enable = true;
datasources.settings = {
datasources = [
{
name = "prometheus";
type = "prometheus";
url = "https://${serviceDomain}/prometheus";
editable = false;
access = "proxy";
basicAuth = true;
basicAuthUser = "admin";
jsonData = {
httpMethod = "POST";
manageAlerts = true;
prometheusType = "Prometheus";
prometheusVersion = "> 2.50.x";
cacheLevel = "High";
disableRecordingRules = false;
incrementalQueryOverlapWindow = "10m";
};
secureJsonData = {
basicAuthPassword = "$__file{/run/secrets/prometheus-admin-pw}";
};
}
];
};
};
settings = {
analytics.reporting_enabled = false;
users.allow_sign_up = false;
security = {
admin_password = "$__file{/run/secrets/grafana-admin-pw}";
cookie_secure = true;
disable_gravatar = true;
};
server = {
domain = serviceDomain;
root_url = "https://${serviceDomain}";
http_port = servicePort;
http_addr = "0.0.0.0";
protocol = "http";
enforce_domain = true;
enable_gzip = true;
};
"auth.generic_oauth" = {
enabled = true;
name = "Kanidm";
icon = "signin";
allow_sign_up = true;
#auto_login = true;
client_id = "grafana";
client_secret = "$__file{${config.sops.secrets.kanidm-grafana-client.path}}";
scopes = "openid email profile";
login_attribute_path = "preferred_username";
auth_url = "https://${kanidmDomain}/ui/oauth2";
token_url = "https://${kanidmDomain}/oauth2/token";
api_url = "https://${kanidmDomain}/oauth2/openid/grafana/userinfo";
use_pkce = true;
use_refresh_token = true;
# Allow mapping oauth2 roles to server admin
allow_assign_grafana_admin = true;
role_attribute_path = "contains(groups[*], 'server_admin') && 'GrafanaAdmin' || contains(groups[*], 'admin') && 'Admin' || contains(groups[*], 'editor') && 'Editor' || 'Viewer'";
};
};
};
prometheus =
let
nextcloudUser = config.repo.secrets.local.nextcloud.adminuser;
in
{
enable = true;
webExternalUrl = "https://${serviceDomain}/${prometheusWebRoot}";
port = prometheusPort;
listenAddress = "0.0.0.0";
globalConfig = {
scrape_interval = "10s";
};
webConfigFile = config.sops.templates.web-config.path;
scrapeConfigs = [
{
job_name = "node";
static_configs = [{
targets = [ "localhost:${toString config.services.prometheus.exporters.node.port}" ];
}];
}
{
job_name = "zfs";
static_configs = [{
targets = [ "localhost:${toString config.services.prometheus.exporters.zfs.port}" ];
}];
}
{
job_name = "nginx";
static_configs = [{
targets = [ "localhost:${toString config.services.prometheus.exporters.nginx.port}" ];
}];
}
{
job_name = "nextcloud";
static_configs = [{
targets = [ "localhost:${toString config.services.prometheus.exporters.nextcloud.port}" ];
}];
}
];
exporters = {
node = {
enable = true;
port = 9000;
enabledCollectors = [ "systemd" ];
extraFlags = [ "--collector.ethtool" "--collector.softirqs" "--collector.tcpstat" "--collector.wifi" ];
};
zfs = {
enable = true;
port = 9134;
pools = [
"Vault"
];
};
restic = {
enable = false;
port = 9753;
};
nginx = {
enable = true;
port = 9113;
sslVerify = false;
scrapeUri = "http://localhost/nginx_status";
};
nextcloud = lib.mkIf config.swarselmodules.server.nextcloud {
enable = true;
port = 9205;
url = "https://${serviceDomain}/ocs/v2.php/apps/serverinfo/api/v1/info";
username = nextcloudUser;
passwordFile = config.sops.secrets.nextcloud-admin-pw.path;
};
};
};
};
nodes.${serviceProxy}.services.nginx = {
upstreams = {
"${grafanaUpstream}" = {
servers = {
"${serviceAddress}:${builtins.toString servicePort}" = { };
};
};
"${prometheusUpstream}" = {
servers = {
"${serviceAddress}:${builtins.toString prometheusPort}" = { };
};
};
};
virtualHosts = {
"${serviceDomain}" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://${grafanaUpstream}";
proxyWebsockets = true;
extraConfig = ''
client_max_body_size 0;
'';
};
"/${prometheusWebRoot}" = {
proxyPass = "http://${prometheusUpstream}";
extraConfig = ''
client_max_body_size 0;
'';
};
};
};
};
};
};
}