From 4b21221569236dacda64d821de94c5fb4a3af627 Mon Sep 17 00:00:00 2001 From: Felix Buehler Date: Sun, 12 Nov 2023 23:36:30 +0100 Subject: [PATCH] treewide: avoid repetitive keys in attrSets --- images/yubikey-installer.nix | 34 +- machines/newton/services.nix | 46 +-- machines/serverle/services.nix | 22 +- modules/services/alertmanager/default.nix | 188 +++++----- modules/services/blackbox/default.nix | 80 +++-- modules/services/blocky/default.nix | 78 ++-- modules/services/gitea/default.nix | 106 +++--- modules/services/hedgedoc/default.nix | 71 ++-- modules/services/homer/config.nix | 96 ++--- modules/services/loki/default.nix | 168 ++++----- modules/services/navidrome/default.nix | 82 ++--- modules/services/nextcloud/default.nix | 168 ++++----- modules/services/nginx/default.nix | 410 +++++++++++----------- modules/services/prometheus/default.nix | 214 +++++------ modules/system/docker/default.nix | 52 +-- profiles/gaming/default.nix | 8 +- profiles/gnome/default.nix | 10 +- profiles/nautilus/default.nix | 26 +- profiles/sway/default.nix | 82 ++--- 19 files changed, 994 insertions(+), 947 deletions(-) diff --git a/images/yubikey-installer.nix b/images/yubikey-installer.nix index 032c4fc..8a97397 100644 --- a/images/yubikey-installer.nix +++ b/images/yubikey-installer.nix @@ -65,13 +65,15 @@ let # Uncomment this to disable compression and speed up image creation time #isoImage.squashfsCompression = "gzip -Xcompression-level 1"; - boot.kernelPackages = linuxPackages_latest; - # Always copytoram so that, if the image is booted from, e.g., a - # USB stick, nothing is mistakenly written to persistent storage. - boot.kernelParams = [ "copytoram" ]; - # Secure defaults - boot.tmp.cleanOnBoot = true; - boot.kernel.sysctl = { "kernel.unprivileged_bpf_disabled" = 1; }; + boot = { + kernelPackages = linuxPackages_latest; + # Always copytoram so that, if the image is booted from, e.g., a + # USB stick, nothing is mistakenly written to persistent storage. + kernelParams = [ "copytoram" ]; + # Secure defaults + tmp.cleanOnBoot = true; + kernel.sysctl = { "kernel.unprivileged_bpf_disabled" = 1; }; + }; services.pcscd.enable = true; services.udev.packages = [ yubikey-personalization ]; @@ -121,14 +123,16 @@ let # Disable networking so the system is air-gapped # Comment all of these lines out if you'll need internet access boot.initrd.network.enable = false; - networking.dhcpcd.enable = false; - networking.dhcpcd.allowInterfaces = [ ]; - networking.interfaces = { }; - networking.firewall.enable = true; - networking.useDHCP = false; - networking.useNetworkd = false; - networking.wireless.enable = false; - networking.networkmanager.enable = lib.mkForce false; + networking = { + dhcpcd.enable = false; + dhcpcd.allowInterfaces = [ ]; + interfaces = { }; + firewall.enable = true; + useDHCP = false; + useNetworkd = false; + wireless.enable = false; + networkmanager.enable = lib.mkForce false; + }; # Unset history so it's never stored # Set GNUPGHOME to an ephemeral location and configure GPG with the diff --git a/machines/newton/services.nix b/machines/newton/services.nix index 3b133d9..1466996 100644 --- a/machines/newton/services.nix +++ b/machines/newton/services.nix @@ -4,28 +4,30 @@ let inherit (config.sops) secrets; in { - sops.secrets."acme/inwx" = { }; - sops.secrets."borgbackup/password" = { }; - sops.secrets."borgbackup/ssh_key" = { }; - sops.secrets."sso/auth-key" = { }; - sops.secrets."sso/felix/password-hash" = { }; - sops.secrets."sso/felix/totp-secret" = { }; - sops.secrets."paperless/password" = { }; - sops.secrets."nextcloud/password" = { - owner = config.users.users.nextcloud.name; - }; - sops.secrets."nextcloud-exporter/password" = { - owner = config.users.users.nextcloud-exporter.name; - }; - sops.secrets."freshrss/password" = { - owner = config.users.users.freshrss.name; - }; - sops.secrets."photoprism/password" = { }; - sops.secrets."grafana/password" = { - owner = config.users.users.grafana.name; - }; - sops.secrets."matrix-bot/password" = { - owner = config.systemd.services.go-neb.serviceConfig.User; + sops.secrets = { + "acme/inwx" = { }; + "borgbackup/password" = { }; + "borgbackup/ssh_key" = { }; + "sso/auth-key" = { }; + "sso/felix/password-hash" = { }; + "sso/felix/totp-secret" = { }; + "paperless/password" = { }; + "nextcloud/password" = { + owner = config.users.users.nextcloud.name; + }; + "nextcloud-exporter/password" = { + owner = config.users.users.nextcloud-exporter.name; + }; + "freshrss/password" = { + owner = config.users.users.freshrss.name; + }; + "photoprism/password" = { }; + "grafana/password" = { + owner = config.users.users.grafana.name; + }; + "matrix-bot/password" = { + owner = config.systemd.services.go-neb.serviceConfig.User; + }; }; # List services that you want to enable: diff --git a/machines/serverle/services.nix b/machines/serverle/services.nix index b01ecab..91a0506 100644 --- a/machines/serverle/services.nix +++ b/machines/serverle/services.nix @@ -4,16 +4,18 @@ let inherit (config.sops) secrets; in { - sops.secrets."acme/inwx" = { }; - sops.secrets."borgbackup/password" = { }; - sops.secrets."borgbackup/ssh_key" = { }; - sops.secrets."dyndns/password" = { }; - sops.secrets."sso/auth-key" = { }; - sops.secrets."sso/felix/password-hash" = { }; - sops.secrets."sso/felix/totp-secret" = { }; - sops.secrets."prowlarr/apikey" = { }; - sops.secrets."radarr/apikey" = { }; - sops.secrets."sonarr/apikey" = { }; + sops.secrets = { + "acme/inwx" = { }; + "borgbackup/password" = { }; + "borgbackup/ssh_key" = { }; + "dyndns/password" = { }; + "sso/auth-key" = { }; + "sso/felix/password-hash" = { }; + "sso/felix/totp-secret" = { }; + "prowlarr/apikey" = { }; + "radarr/apikey" = { }; + "sonarr/apikey" = { }; + }; # List services that you want to enable: my.services = { diff --git a/modules/services/alertmanager/default.nix b/modules/services/alertmanager/default.nix index ad3bd9d..4cb97be 100644 --- a/modules/services/alertmanager/default.nix +++ b/modules/services/alertmanager/default.nix @@ -25,108 +25,110 @@ in } ]; - services.prometheus = { - alertmanager = { - enable = true; - listenAddress = "127.0.0.1"; - inherit (cfg) port; - configuration = import ./config.nix; - webExternalUrl = "https://alerts.${domain}"; - # fix issue: https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4556 - extraFlags = [ "--cluster.advertise-address 127.0.0.1:${toString cfg.port}" ]; + services = { + prometheus = { + alertmanager = { + enable = true; + listenAddress = "127.0.0.1"; + inherit (cfg) port; + configuration = import ./config.nix; + webExternalUrl = "https://alerts.${domain}"; + # fix issue: https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4556 + extraFlags = [ "--cluster.advertise-address 127.0.0.1:${toString cfg.port}" ]; + }; + + alertmanagers = [ + { + static_configs = [ + { + targets = [ "localhost:${toString cfg.port}" ]; + } + ]; + } + ]; + scrapeConfigs = [ + { + job_name = "alertmanager"; + static_configs = [{ + targets = [ "127.0.0.1:${toString cfg.port}" ]; + labels = { + instance = config.networking.hostName; + }; + }]; + } + ]; }; - alertmanagers = [ - { - static_configs = [ - { - targets = [ "localhost:${toString cfg.port}" ]; - } - ]; - } - ]; - scrapeConfigs = [ - { - job_name = "alertmanager"; - static_configs = [{ - targets = [ "127.0.0.1:${toString cfg.port}" ]; - labels = { - instance = config.networking.hostName; + grafana.provision = { + datasources.settings.datasources = [ + { + name = "Alertmanager"; + type = "alertmanager"; + url = "http://127.0.0.1:${toString cfg.port}"; + jsonData = { + implementation = "prometheus"; + handleGrafanaManagedAlerts = config.services.prometheus.enable; }; - }]; - } - ]; - }; + } + ]; + }; - services.grafana.provision = { - datasources.settings.datasources = [ + grafana.provision = { + dashboards.settings.providers = [ + { + name = "Alertmanager"; + options.path = pkgs.grafana-dashboards.alertmanager; + disableDeletion = true; + } + ]; + }; + + # for mail delivery + postfix.enable = true; + + go-neb.config.services = [ { - name = "Alertmanager"; - type = "alertmanager"; - url = "http://127.0.0.1:${toString cfg.port}"; - jsonData = { - implementation = "prometheus"; - handleGrafanaManagedAlerts = config.services.prometheus.enable; - }; - } - ]; - }; - - services.grafana.provision = { - dashboards.settings.providers = [ - { - name = "Alertmanager"; - options.path = pkgs.grafana-dashboards.alertmanager; - disableDeletion = true; - } - ]; - }; - - # for mail delivery - services.postfix.enable = true; - - services.go-neb.config.services = [ - { - ID = "alertmanager_service"; - Type = "alertmanager"; - UserId = config.my.services.matrix-bot.Username; - Config = { - # url contains "alertmanager_service" encoded as base64 - webhook_url = "http://localhost:4050/services/hooks/YWxlcnRtYW5hZ2VyX3NlcnZpY2U"; - rooms = { - "${config.my.services.matrix-bot.RoomID}" = { - #bots:nixos.org - text_template = '' - {{range .Alerts -}} [{{ .Status }}] {{index .Labels "alertname" }}: {{index .Annotations "description"}} {{ end -}} - ''; - # $$severity otherwise envsubst replaces $severity with an empty string - html_template = '' - {{range .Alerts -}} - {{ $$severity := index .Labels "severity" }} - {{ if eq .Status "firing" }} - {{ if eq $$severity "critical"}} - [FIRING - CRITICAL] - {{ else if eq $$severity "warning"}} - [FIRING - WARNING] + ID = "alertmanager_service"; + Type = "alertmanager"; + UserId = config.my.services.matrix-bot.Username; + Config = { + # url contains "alertmanager_service" encoded as base64 + webhook_url = "http://localhost:4050/services/hooks/YWxlcnRtYW5hZ2VyX3NlcnZpY2U"; + rooms = { + "${config.my.services.matrix-bot.RoomID}" = { + #bots:nixos.org + text_template = '' + {{range .Alerts -}} [{{ .Status }}] {{index .Labels "alertname" }}: {{index .Annotations "description"}} {{ end -}} + ''; + # $$severity otherwise envsubst replaces $severity with an empty string + html_template = '' + {{range .Alerts -}} + {{ $$severity := index .Labels "severity" }} + {{ if eq .Status "firing" }} + {{ if eq $$severity "critical"}} + [FIRING - CRITICAL] + {{ else if eq $$severity "warning"}} + [FIRING - WARNING] + {{ else }} + [FIRING - {{ $$severity }}] + {{ end }} {{ else }} - [FIRING - {{ $$severity }}] + [RESOLVED] {{ end }} - {{ else }} - [RESOLVED] - {{ end }} - {{ index .Labels "alertname"}}: {{ index .Annotations "summary"}} - ( - 📈 Grafana, - 🔥 Prometheus, - 🔕 Silence - )
- {{end -}}''; - msg_type = "m.text"; # Must be either `m.text` or `m.notice` + {{ index .Labels "alertname"}}: {{ index .Annotations "summary"}} + ( + 📈 Grafana, + 🔥 Prometheus, + 🔕 Silence + )
+ {{end -}}''; + msg_type = "m.text"; # Must be either `m.text` or `m.notice` + }; }; }; - }; - } - ]; + } + ]; + }; my.services.prometheus.rules = { alerts_silences_changed = { diff --git a/modules/services/blackbox/default.nix b/modules/services/blackbox/default.nix index f406957..b68f645 100644 --- a/modules/services/blackbox/default.nix +++ b/modules/services/blackbox/default.nix @@ -42,40 +42,49 @@ in }; config = lib.mkIf cfg.enable { - services.prometheus.exporters.blackbox = { - enable = true; - configFile = pkgs.writeText "blackbox-config.yml" (builtins.toJSON blackBoxConfig); - }; + services = { + prometheus.exporters.blackbox = { + enable = true; + configFile = pkgs.writeText "blackbox-config.yml" (builtins.toJSON blackBoxConfig); + }; - # relabels as in https://github.com/prometheus/blackbox_exporter#prometheus-configuration - services.prometheus = { - scrapeConfigs = [ + # relabels as in https://github.com/prometheus/blackbox_exporter#prometheus-configuration + prometheus = { + scrapeConfigs = [ + { + job_name = "blackbox"; + metrics_path = "/probe"; + params.module = [ "http_2xx" ]; + static_configs = [ + { + targets = cfg.http_endpoints; + labels = { + instance = config.networking.hostName; + }; + } + ]; + relabel_configs = [ + { + source_labels = [ "__address__" ]; + target_label = "__param_target"; + } + { + source_labels = [ "__param_target" ]; + target_label = "instance"; + } + { + target_label = "__address__"; + replacement = "127.0.0.1:${toString config.services.prometheus.exporters.blackbox.port}"; + } + ]; + } + ]; + }; + grafana.provision.dashboards.settings.providers = [ { - job_name = "blackbox"; - metrics_path = "/probe"; - params.module = [ "http_2xx" ]; - static_configs = [ - { - targets = cfg.http_endpoints; - labels = { - instance = config.networking.hostName; - }; - } - ]; - relabel_configs = [ - { - source_labels = [ "__address__" ]; - target_label = "__param_target"; - } - { - source_labels = [ "__param_target" ]; - target_label = "instance"; - } - { - target_label = "__address__"; - replacement = "127.0.0.1:${toString config.services.prometheus.exporters.blackbox.port}"; - } - ]; + name = "Blackbox"; + options.path = pkgs.grafana-dashboards.blackbox; + disableDeletion = true; } ]; }; @@ -143,12 +152,5 @@ in }; }; }; - services.grafana.provision.dashboards.settings.providers = [ - { - name = "Blackbox"; - options.path = pkgs.grafana-dashboards.blackbox; - disableDeletion = true; - } - ]; }; } diff --git a/modules/services/blocky/default.nix b/modules/services/blocky/default.nix index 1842095..de8d467 100644 --- a/modules/services/blocky/default.nix +++ b/modules/services/blocky/default.nix @@ -27,46 +27,48 @@ in }; config = lib.mkIf cfg.enable { - services.blocky = { - enable = true; + services = { + blocky = { + enable = true; - settings = { - ports = { - tls = "853"; - http = cfg.httpPort; - }; - upstream = { - default = [ - "dns2.digitalcourage.de2" # classic - "tcp-tls:dns3.digitalcourage.de" # DoT - "https://dns.digitale-gesellschaft.ch/dns-query" # DoH + settings = { + ports = { + tls = "853"; + http = cfg.httpPort; + }; + upstream = { + default = [ + "dns2.digitalcourage.de2" # classic + "tcp-tls:dns3.digitalcourage.de" # DoT + "https://dns.digitale-gesellschaft.ch/dns-query" # DoH + ]; + }; + prometheus.enable = config.services.prometheus.enable; + } // cfg.settings; + }; + + prometheus.scrapeConfigs = [ + { + job_name = "blocky"; + static_configs = [ + { + targets = [ "127.0.0.1:${toString cfg.httpPort}" ]; + labels = { + instance = config.networking.hostName; + }; + } ]; - }; - prometheus.enable = config.services.prometheus.enable; - } // cfg.settings; + } + ]; + + # untested + grafana.provision.dashboards.settings.providers = [ + { + name = "Blocky"; + options.path = pkgs.grafana-dashboards.blocky; + disableDeletion = true; + } + ]; }; - - services.prometheus.scrapeConfigs = [ - { - job_name = "blocky"; - static_configs = [ - { - targets = [ "127.0.0.1:${toString cfg.httpPort}" ]; - labels = { - instance = config.networking.hostName; - }; - } - ]; - } - ]; - - # untested - services.grafana.provision.dashboards.settings.providers = [ - { - name = "Blocky"; - options.path = pkgs.grafana-dashboards.blocky; - disableDeletion = true; - } - ]; }; } diff --git a/modules/services/gitea/default.nix b/modules/services/gitea/default.nix index 072238e..e3e3de4 100644 --- a/modules/services/gitea/default.nix +++ b/modules/services/gitea/default.nix @@ -16,66 +16,70 @@ in }; config = lib.mkIf cfg.enable { - services.gitea = { - enable = true; - settings = { - server = { - HTTP_PORT = cfg.port; - ROOT_URL = "https://code.${domain}"; + services = { + gitea = { + enable = true; + settings = { + server = { + HTTP_PORT = cfg.port; + ROOT_URL = "https://code.${domain}"; + }; + session.COOKIE_SECURE = true; + service.DISABLE_REGISTRATION = true; + ui.DEFAULT_THEME = "arc-green"; + log.LEVEL = "Warn"; + metrics.ENABLED = config.services.prometheus.enable; }; - session.COOKIE_SECURE = true; - service.DISABLE_REGISTRATION = true; - ui.DEFAULT_THEME = "arc-green"; - log.LEVEL = "Warn"; - metrics.ENABLED = config.services.prometheus.enable; + lfs.enable = true; + }; + + prometheus = { + scrapeConfigs = [ + { + job_name = "gitea"; + static_configs = [ + { + targets = [ "127.0.0.1:${toString cfg.port}" ]; + labels = { + instance = config.networking.hostName; + }; + } + ]; + } + ]; + }; + grafana.provision = { + dashboards.settings.providers = [ + { + name = "Gitea"; + options.path = pkgs.grafana-dashboards.gitea; + disableDeletion = true; + } + ]; }; - lfs.enable = true; }; # Proxy to Gitea - my.services.nginx.virtualHosts = [ - { - subdomain = "code"; - inherit (cfg) port; - } - ]; - - my.services.backup = { - paths = [ - config.services.gitea.lfs.contentDir - config.services.gitea.repositoryRoot - ]; - }; - - services.prometheus = { - scrapeConfigs = [ + my.services = { + nginx.virtualHosts = [ { - job_name = "gitea"; - static_configs = [ - { - targets = [ "127.0.0.1:${toString cfg.port}" ]; - labels = { - instance = config.networking.hostName; - }; - } - ]; + subdomain = "code"; + inherit (cfg) port; } ]; - }; - services.grafana.provision = { - dashboards.settings.providers = [ - { - name = "Gitea"; - options.path = pkgs.grafana-dashboards.gitea; - disableDeletion = true; - } - ]; - }; - my.services.prometheus.rules = { - gitea = { - condition = ''rate(promhttp_metric_handler_requests_total{job="gitea", code="500"}[5m]) > 3''; - description = "{{$labels.instance}}: gitea instances error rate went up: {{$value}} errors in 5 minutes"; + backup = { + paths = [ + config.services.gitea.lfs.contentDir + config.services.gitea.repositoryRoot + ]; + }; + + prometheus.rules = { + gitea = { + condition = ''rate(promhttp_metric_handler_requests_total{job="gitea", code="500"}[5m]) > 3''; + description = "{{$labels.instance}}: gitea instances error rate went up: {{$value}} errors in 5 minutes"; + }; }; }; diff --git a/modules/services/hedgedoc/default.nix b/modules/services/hedgedoc/default.nix index ad8ab1b..6b2a4da 100644 --- a/modules/services/hedgedoc/default.nix +++ b/modules/services/hedgedoc/default.nix @@ -31,48 +31,51 @@ in }; config = lib.mkIf cfg.enable { - services.hedgedoc = { - enable = true; + services = { + hedgedoc = { + enable = true; - settings = { - domain = "notes.${domain}"; - inherit (cfg) port; - host = "127.0.0.1"; - protocolUseSSL = true; - db = { - dialect = "sqlite"; - storage = "/var/lib/hedgedoc/hedgedoc.sqlite"; - }; - } // cfg.settings; - }; + settings = { + domain = "notes.${domain}"; + inherit (cfg) port; + host = "127.0.0.1"; + protocolUseSSL = true; + db = { + dialect = "sqlite"; + storage = "/var/lib/hedgedoc/hedgedoc.sqlite"; + }; + } // cfg.settings; + }; - # temporary fix for: https://github.com/NixOS/nixpkgs/issues/198250 - #systemd.services.hedgedoc.serviceConfig.StateDirectory = lib.mkForce "/var/lib/hedgedoc"; - systemd.services.hedgedoc.serviceConfig.StateDirectory = lib.mkForce "hedgedoc"; + prometheus = { + scrapeConfigs = [ + { + job_name = "hedgedoc"; + static_configs = [ + { + targets = [ "127.0.0.1:${toString cfg.port}" ]; + labels = { + instance = config.networking.hostName; + }; + } + ]; + } + ]; + }; - services.prometheus = { - scrapeConfigs = [ + grafana.provision.dashboards.settings.providers = [ { - job_name = "hedgedoc"; - static_configs = [ - { - targets = [ "127.0.0.1:${toString cfg.port}" ]; - labels = { - instance = config.networking.hostName; - }; - } - ]; + name = "Hedgedoc"; + options.path = pkgs.grafana-dashboards.hedgedoc; + disableDeletion = true; } ]; }; - services.grafana.provision.dashboards.settings.providers = [ - { - name = "Hedgedoc"; - options.path = pkgs.grafana-dashboards.hedgedoc; - disableDeletion = true; - } - ]; + # TODO remove for 23.11 + # temporary fix for: https://github.com/NixOS/nixpkgs/issues/198250 + #systemd.services.hedgedoc.serviceConfig.StateDirectory = lib.mkForce "/var/lib/hedgedoc"; + systemd.services.hedgedoc.serviceConfig.StateDirectory = lib.mkForce "hedgedoc"; my.services.nginx.virtualHosts = [ { diff --git a/modules/services/homer/config.nix b/modules/services/homer/config.nix index 375b190..b342176 100644 --- a/modules/services/homer/config.nix +++ b/modules/services/homer/config.nix @@ -37,53 +37,55 @@ type = lib.types.attrsOf (lib.types.submodule { options = { - dashboard.url = lib.mkOption { - type = lib.types.nullOr lib.types.str; - description = '' - Url to webapp - ''; - example = "http://192.168.1.10:1234"; - default = null; - }; - dashboard.name = lib.mkOption { - type = lib.types.nullOr lib.types.str; - description = '' - Application name. - ''; - example = "App"; - default = null; - }; - dashboard.category = lib.mkOption { - type = lib.types.nullOr lib.types.str; - description = '' - App category tag. - ''; - example = "app"; - default = null; - }; - dashboard.icon = lib.mkOption { - type = lib.types.nullOr lib.types.str; - description = '' - Font Awesome application icon. - ''; - example = "rss"; - default = null; - }; - dashboard.type = lib.mkOption { - type = lib.types.nullOr lib.types.str; - description = '' - application type. - ''; - example = "Ping"; - default = "Ping"; - }; - dashboard.method = lib.mkOption { - type = lib.types.enum [ "get" "head" ]; - description = '' - method of request used - ''; - example = "get"; - default = "head"; + dashboard = { + url = lib.mkOption { + type = lib.types.nullOr lib.types.str; + description = '' + Url to webapp + ''; + example = "http://192.168.1.10:1234"; + default = null; + }; + name = lib.mkOption { + type = lib.types.nullOr lib.types.str; + description = '' + Application name. + ''; + example = "App"; + default = null; + }; + category = lib.mkOption { + type = lib.types.nullOr lib.types.str; + description = '' + App category tag. + ''; + example = "app"; + default = null; + }; + icon = lib.mkOption { + type = lib.types.nullOr lib.types.str; + description = '' + Font Awesome application icon. + ''; + example = "rss"; + default = null; + }; + type = lib.mkOption { + type = lib.types.nullOr lib.types.str; + description = '' + application type. + ''; + example = "Ping"; + default = "Ping"; + }; + method = lib.mkOption { + type = lib.types.enum [ "get" "head" ]; + description = '' + method of request used + ''; + example = "get"; + default = "head"; + }; }; }; }); diff --git a/modules/services/loki/default.nix b/modules/services/loki/default.nix index f3579aa..06dde58 100644 --- a/modules/services/loki/default.nix +++ b/modules/services/loki/default.nix @@ -62,80 +62,98 @@ in }; config = lib.mkIf cfg.enable { - services.loki = { - enable = true; - configuration = { - server = { - http_listen_address = "127.0.0.1"; - http_listen_port = cfg.port; - }; - auth_enabled = false; + services = { + loki = { + enable = true; + configuration = { + server = { + http_listen_address = "127.0.0.1"; + http_listen_port = cfg.port; + }; + auth_enabled = false; - common = { - instance_addr = "127.0.0.1"; - ring.kvstore.store = "inmemory"; - replication_factor = 1; - path_prefix = "/tmp/loki"; - }; - - ruler = lib.mkIf config.my.services.alertmanager.enable { - storage = { - type = "local"; - local = { - # having the "fake" directory is important, because loki is running in single-tenant mode - directory = pkgs.writeTextDir "fake/loki-rules.yml" (builtins.toJSON { - groups = [ - { - name = "alerting-rules"; - rules = lib.mapAttrsToList - (name: opts: { - alert = name; - inherit (opts) condition labels; - for = opts.time; - annotations.description = opts.description; - }) - cfg.rules; - } - ]; - }); - }; + common = { + instance_addr = "127.0.0.1"; + ring.kvstore.store = "inmemory"; + replication_factor = 1; + path_prefix = "/tmp/loki"; }; - alertmanager_url = "http://127.0.0.1:${toString config.my.services.alertmanager.port}"; - enable_alertmanager_v2 = true; - }; - - schema_config = { - configs = [{ - from = "2020-05-15"; - store = "boltdb-shipper"; - object_store = "filesystem"; - schema = "v11"; - index = { - prefix = "index_"; - period = "24h"; + ruler = lib.mkIf config.my.services.alertmanager.enable { + storage = { + type = "local"; + local = { + # having the "fake" directory is important, because loki is running in single-tenant mode + directory = pkgs.writeTextDir "fake/loki-rules.yml" (builtins.toJSON { + groups = [ + { + name = "alerting-rules"; + rules = lib.mapAttrsToList + (name: opts: { + alert = name; + inherit (opts) condition labels; + for = opts.time; + annotations.description = opts.description; + }) + cfg.rules; + } + ]; + }); + }; }; - }]; + + alertmanager_url = "http://127.0.0.1:${toString config.my.services.alertmanager.port}"; + enable_alertmanager_v2 = true; + }; + + schema_config = { + configs = [{ + from = "2020-05-15"; + store = "boltdb-shipper"; + object_store = "filesystem"; + schema = "v11"; + index = { + prefix = "index_"; + period = "24h"; + }; + }]; + }; }; }; - }; - services.grafana.provision = { - datasources.settings.datasources = [ - { - name = "Loki"; - type = "loki"; - access = "proxy"; - url = "http://127.0.0.1:${toString cfg.port}"; - } - ]; - dashboards.settings.providers = [ - { - name = "Loki"; - options.path = pkgs.grafana-dashboards.loki; - disableDeletion = true; - } - ]; + grafana.provision = { + datasources.settings.datasources = [ + { + name = "Loki"; + type = "loki"; + access = "proxy"; + url = "http://127.0.0.1:${toString cfg.port}"; + } + ]; + dashboards.settings.providers = [ + { + name = "Loki"; + options.path = pkgs.grafana-dashboards.loki; + disableDeletion = true; + } + ]; + }; + + prometheus = { + scrapeConfigs = [ + { + job_name = "loki"; + static_configs = [ + { + targets = [ "127.0.0.1:${toString cfg.port}" ]; + labels = { + instance = config.networking.hostName; + }; + } + ]; + } + ]; + }; }; my.services.loki.rules = { @@ -144,21 +162,5 @@ in description = "Loki has a high logging rate"; }; }; - - services.prometheus = { - scrapeConfigs = [ - { - job_name = "loki"; - static_configs = [ - { - targets = [ "127.0.0.1:${toString cfg.port}" ]; - labels = { - instance = config.networking.hostName; - }; - } - ]; - } - ]; - }; }; } diff --git a/modules/services/navidrome/default.nix b/modules/services/navidrome/default.nix index b1dc13b..5ddeaee 100644 --- a/modules/services/navidrome/default.nix +++ b/modules/services/navidrome/default.nix @@ -39,15 +39,49 @@ in }; config = lib.mkIf cfg.enable { - services.navidrome = { - enable = true; + services = { + navidrome = { + enable = true; - settings = cfg.settings // { - Port = cfg.port; - Address = "127.0.0.1"; - MusicFolder = cfg.musicFolder; - LogLevel = "info"; - Prometheus.Enabled = config.services.prometheus.enable; + settings = cfg.settings // { + Port = cfg.port; + Address = "127.0.0.1"; + MusicFolder = cfg.musicFolder; + LogLevel = "info"; + Prometheus.Enabled = config.services.prometheus.enable; + }; + }; + + prometheus = { + scrapeConfigs = [ + { + job_name = "navidrome"; + static_configs = [ + { + targets = [ "127.0.0.1:${toString cfg.port}" ]; + labels = { + instance = config.networking.hostName; + }; + } + ]; + } + ]; + }; + grafana.provision = { + dashboards.settings.providers = [ + { + name = "Navidrome"; + options.path = pkgs.grafana-dashboards.navidrome; + disableDeletion = true; + } + ]; + }; + }; + + my.services.prometheus.rules = { + navidrome_not_enough_albums = { + condition = ''http_navidrome_album_count != 1''; + description = "navidrome: not enough albums as expected: {{$value}}"; }; }; @@ -58,38 +92,6 @@ in } ]; - services.prometheus = { - scrapeConfigs = [ - { - job_name = "navidrome"; - static_configs = [ - { - targets = [ "127.0.0.1:${toString cfg.port}" ]; - labels = { - instance = config.networking.hostName; - }; - } - ]; - } - ]; - }; - services.grafana.provision = { - dashboards.settings.providers = [ - { - name = "Navidrome"; - options.path = pkgs.grafana-dashboards.navidrome; - disableDeletion = true; - } - ]; - }; - - my.services.prometheus.rules = { - navidrome_not_enough_albums = { - condition = ''http_navidrome_album_count != 1''; - description = "navidrome: not enough albums as expected: {{$value}}"; - }; - }; - webapps.apps.navidrome = { dashboard = { name = "Music"; diff --git a/modules/services/nextcloud/default.nix b/modules/services/nextcloud/default.nix index 0ab04b8..09b42d2 100644 --- a/modules/services/nextcloud/default.nix +++ b/modules/services/nextcloud/default.nix @@ -51,70 +51,103 @@ in }; config = lib.mkIf cfg.enable { - services.nextcloud = { - enable = true; - package = pkgs.nextcloud27; - hostName = "cloud.${domain}"; - maxUploadSize = cfg.maxSize; - autoUpdateApps.enable = true; - config = { - adminuser = cfg.admin; - adminpassFile = cfg.passwordFile; - inherit (cfg) defaultPhoneRegion; + services = { + nextcloud = { + enable = true; + package = pkgs.nextcloud27; + hostName = "cloud.${domain}"; + maxUploadSize = cfg.maxSize; + autoUpdateApps.enable = true; + config = { + adminuser = cfg.admin; + adminpassFile = cfg.passwordFile; + inherit (cfg) defaultPhoneRegion; - overwriteProtocol = "https"; # Nginx only allows SSL + overwriteProtocol = "https"; # Nginx only allows SSL - #dbtype = "pgsql"; - #dbhost = "/run/postgresql"; + #dbtype = "pgsql"; + #dbhost = "/run/postgresql"; + }; + + extraApps = { + calendar = let version = "4.5.2"; in pkgs.fetchNextcloudApp { + url = "https://github.com/nextcloud-releases/calendar/releases/download/v${version}/calendar-v${version}.tar.gz"; + sha256 = "sha256-n7GjgAyw2SLoZTEfakmI3IllWUk6o1MF89Zt3WGhR6A="; + }; + contacts = let version = "5.4.2"; in pkgs.fetchNextcloudApp { + url = "https://github.com/nextcloud-releases/contacts/releases/download/v${version}/contacts-v${version}.tar.gz"; + sha256 = "sha256-IkKHJ3MY/UPZqa4H86WGOEOypffMIHyJ9WvMqkq/4t8="; + }; + tasks = let version = "0.15.0"; in pkgs.fetchNextcloudApp { + url = "https://github.com/nextcloud/tasks/releases/download/v${version}/tasks.tar.gz"; + sha256 = "sha256-zMMqtEWiXmhB1C2IeWk8hgP7eacaXLkT7Tgi4NK6PCg="; + }; + deck = let version = "1.11.0"; in pkgs.fetchNextcloudApp { + url = "https://github.com/nextcloud/deck/releases/download/v${version}/deck.tar.gz"; + sha256 = "sha256-stb9057pP8WXIhztNl7H8ymLqSZzSulgKgB2cbib2pQ="; + }; + }; }; - extraApps = { - calendar = let version = "4.5.2"; in pkgs.fetchNextcloudApp { - url = "https://github.com/nextcloud-releases/calendar/releases/download/v${version}/calendar-v${version}.tar.gz"; - sha256 = "sha256-n7GjgAyw2SLoZTEfakmI3IllWUk6o1MF89Zt3WGhR6A="; - }; - contacts = let version = "5.4.2"; in pkgs.fetchNextcloudApp { - url = "https://github.com/nextcloud-releases/contacts/releases/download/v${version}/contacts-v${version}.tar.gz"; - sha256 = "sha256-IkKHJ3MY/UPZqa4H86WGOEOypffMIHyJ9WvMqkq/4t8="; - }; - tasks = let version = "0.15.0"; in pkgs.fetchNextcloudApp { - url = "https://github.com/nextcloud/tasks/releases/download/v${version}/tasks.tar.gz"; - sha256 = "sha256-zMMqtEWiXmhB1C2IeWk8hgP7eacaXLkT7Tgi4NK6PCg="; - }; - deck = let version = "1.11.0"; in pkgs.fetchNextcloudApp { - url = "https://github.com/nextcloud/deck/releases/download/v${version}/deck.tar.gz"; - sha256 = "sha256-stb9057pP8WXIhztNl7H8ymLqSZzSulgKgB2cbib2pQ="; - }; + #postgresql = { + # enable = true; + # ensureDatabases = [ "nextcloud" ]; + # ensureUsers = [ + # { + # name = "nextcloud"; + # ensurePermissions."DATABASE nextcloud" = "ALL PRIVILEGES"; + # } + # ]; + #}; + + # The service above configures the domain, no need for my wrapper + nginx.virtualHosts."cloud.${domain}" = { + forceSSL = true; + useACMEHost = domain; + + # so homer can get the online status + extraConfig = lib.optionalString config.my.services.homer.enable '' + add_header Access-Control-Allow-Origin https://${domain}; + ''; + }; + + prometheus.exporters.nextcloud = { + enable = true; + url = "https://cloud.${domain}"; + username = cfg.admin; + passwordFile = cfg.exporterPasswordFile; + port = cfg.exporterPort; + }; + + prometheus.scrapeConfigs = [ + { + job_name = "nextcloud"; + static_configs = [ + { + targets = [ "127.0.0.1:${toString cfg.exporterPort}" ]; + labels = { + instance = config.networking.hostName; + }; + } + ]; + } + ]; + grafana.provision = { + dashboards.settings.providers = [ + { + name = "Nextcloud"; + options.path = pkgs.grafana-dashboards.nextcloud; + disableDeletion = true; + } + ]; }; }; - #services.postgresql = { - # enable = true; - # ensureDatabases = [ "nextcloud" ]; - # ensureUsers = [ - # { - # name = "nextcloud"; - # ensurePermissions."DATABASE nextcloud" = "ALL PRIVILEGES"; - # } - # ]; - #}; - #systemd.services."nextcloud-setup" = { # requires = [ "postgresql.service" ]; # after = [ "postgresql.service" ]; #}; - # The service above configures the domain, no need for my wrapper - services.nginx.virtualHosts."cloud.${domain}" = { - forceSSL = true; - useACMEHost = domain; - - # so homer can get the online status - extraConfig = lib.optionalString config.my.services.homer.enable '' - add_header Access-Control-Allow-Origin https://${domain}; - ''; - }; - my.services.backup = { exclude = [ # image previews can take up a lot of space @@ -122,37 +155,6 @@ in ]; }; - services.prometheus.exporters.nextcloud = { - enable = true; - url = "https://cloud.${domain}"; - username = cfg.admin; - passwordFile = cfg.exporterPasswordFile; - port = cfg.exporterPort; - }; - - services.prometheus.scrapeConfigs = [ - { - job_name = "nextcloud"; - static_configs = [ - { - targets = [ "127.0.0.1:${toString cfg.exporterPort}" ]; - labels = { - instance = config.networking.hostName; - }; - } - ]; - } - ]; - services.grafana.provision = { - dashboards.settings.providers = [ - { - name = "Nextcloud"; - options.path = pkgs.grafana-dashboards.nextcloud; - disableDeletion = true; - } - ]; - }; - webapps.apps.nextcloud = { dashboard = { name = "Cloud"; diff --git a/modules/services/nginx/default.nix b/modules/services/nginx/default.nix index a6baa25..5139d02 100644 --- a/modules/services/nginx/default.nix +++ b/modules/services/nginx/default.nix @@ -153,8 +153,7 @@ in }; }; config = lib.mkIf cfg.enable { - assertions = [ ] - ++ (lib.flip builtins.map cfg.virtualHosts ({ subdomain, ... } @ args: + assertions = lib.flip builtins.map cfg.virtualHosts ({ subdomain, ... } @ args: let conflicts = [ "port" "root" ]; optionsNotNull = builtins.map (v: args.${v} != null) conflicts; @@ -167,7 +166,7 @@ in lib.concatStringsSep ", " (builtins.map (v: "'${v}'") conflicts) } configured. ''; - })) + }) # ++ ( # let # ports = lib.my.mapFilter @@ -201,184 +200,219 @@ in # map mkAssertion nonUniques # ) ; - services.nginx = { - enable = true; - statusPage = true; # For monitoring scraping. - - recommendedGzipSettings = true; - recommendedOptimisation = true; - recommendedTlsSettings = true; - recommendedProxySettings = true; - recommendedBrotliSettings = true; - - # Only allow PFS-enabled ciphers with AES256 - sslCiphers = "AES256+EECDH:AES256+EDH:!aNULL"; - - commonHttpConfig = '' - # Add HSTS header with preloading to HTTPS requests. - # Adding this header to HTTP requests is discouraged - map $scheme $hsts_header { - https "max-age=31536000; includeSubdomains; preload"; - } - add_header Strict-Transport-Security $hsts_header; - - # CORS header - # some applications set it to wildcard, therefore this overrides it - proxy_hide_header Access-Control-Allow-Origin; - add_header Access-Control-Allow-Origin https://${config.networking.domain}; - - # Minimize information leaked to other domains - add_header 'Referrer-Policy' 'strict-origin-when-cross-origin'; - - # Disable embedding as a frame - add_header X-Frame-Options DENY; - - # Prevent injection of code in other mime types (XSS Attacks) - add_header X-Content-Type-Options nosniff; - - # Enable XSS protection of the browser. - # May be unnecessary when CSP is configured properly (see above) - add_header X-XSS-Protection "1; mode=block"; - - # This might create errors - proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict"; - - # Enable CSP for your services. - #add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always; - ''; - - virtualHosts = - let - genAttrs' = values: f: lib.listToAttrs (map f values); - inherit (config.networking) domain; - mkVHost = { subdomain, ... } @ args: lib.nameValuePair - "${subdomain}.${domain}" - (lib.foldl lib.recursiveUpdate { } [ - # Base configuration - { - forceSSL = true; - useACMEHost = domain; - } - # Proxy to port - (lib.optionalAttrs (args.port != null) { - locations."/".proxyPass = - "http://127.0.0.1:${toString args.port}"; - # TODO make ipv6 possible - # http://[::1]:${toString args.port}; - }) - # Serve filesystem content - (lib.optionalAttrs (args.root != null) { - inherit (args) root; - }) - # VHost specific configuration - args.extraConfig - # SSO configuration - (lib.optionalAttrs args.sso.enable { - extraConfig = (args.extraConfig.extraConfig or "") + '' - error_page 401 = @error401; - ''; - locations."@error401".return = '' - 302 https://${cfg.sso.subdomain}.${config.networking.domain}/login?go=$scheme://$http_host$request_uri - ''; - locations."/" = { - extraConfig = - (args.extraConfig.locations."/".extraConfig or "") + '' - # Use SSO - auth_request /sso-auth; - # Set username through header - auth_request_set $username $upstream_http_x_username; - proxy_set_header X-User $username; - # Renew SSO cookie on request - auth_request_set $cookie $upstream_http_set_cookie; - add_header Set-Cookie $cookie; - ''; - }; - locations."/sso-auth" = { - proxyPass = "http://localhost:${toString cfg.sso.port}/auth"; - extraConfig = '' - # Do not allow requests from outside - internal; - # Do not forward the request body - proxy_pass_request_body off; - proxy_set_header Content-Length ""; - # Set X-Application according to subdomain for matching - proxy_set_header X-Application "${subdomain}"; - # Set origin URI for matching - proxy_set_header X-Origin-URI $request_uri; - ''; - }; - }) - ]) - ; - in - genAttrs' cfg.virtualHosts mkVHost; - sso = { + services = { + nginx = { enable = true; - configuration = { - listen = { - addr = "127.0.0.1"; - inherit (cfg.sso) port; - }; - audit_log = { - target = [ - "fd://stdout" - ]; - events = [ - "access_denied" - "login_success" - "login_failure" - "logout" - "validate" - ]; - headers = [ - "x-origin-uri" - "x-application" - ]; - }; - cookie = { - domain = ".${config.networking.domain}"; - secure = true; - authentication_key = { - _secret = cfg.sso.authKeyFile; - }; - }; - login = { - title = "Bühlers's SSO"; - default_method = "simple"; - hide_mfa_field = false; - names = { - simple = "Username / Password"; - }; - }; - providers = { - simple = - let - applyUsers = lib.flip lib.mapAttrs cfg.sso.users; - in - { - users = applyUsers (_: v: { _secret = v.passwordHashFile; }); - mfa = applyUsers (_: v: [{ - provider = "totp"; - attributes = { - secret = { - _secret = v.totpSecretFile; + statusPage = true; # For monitoring scraping. + + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedTlsSettings = true; + recommendedProxySettings = true; + recommendedBrotliSettings = true; + + # Only allow PFS-enabled ciphers with AES256 + sslCiphers = "AES256+EECDH:AES256+EDH:!aNULL"; + + commonHttpConfig = '' + # Add HSTS header with preloading to HTTPS requests. + # Adding this header to HTTP requests is discouraged + map $scheme $hsts_header { + https "max-age=31536000; includeSubdomains; preload"; + } + add_header Strict-Transport-Security $hsts_header; + + # CORS header + # some applications set it to wildcard, therefore this overrides it + proxy_hide_header Access-Control-Allow-Origin; + add_header Access-Control-Allow-Origin https://${config.networking.domain}; + + # Minimize information leaked to other domains + add_header 'Referrer-Policy' 'strict-origin-when-cross-origin'; + + # Disable embedding as a frame + add_header X-Frame-Options DENY; + + # Prevent injection of code in other mime types (XSS Attacks) + add_header X-Content-Type-Options nosniff; + + # Enable XSS protection of the browser. + # May be unnecessary when CSP is configured properly (see above) + add_header X-XSS-Protection "1; mode=block"; + + # This might create errors + proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict"; + + # Enable CSP for your services. + #add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always; + ''; + + virtualHosts = + let + genAttrs' = values: f: lib.listToAttrs (map f values); + inherit (config.networking) domain; + mkVHost = { subdomain, ... } @ args: lib.nameValuePair + "${subdomain}.${domain}" + (lib.foldl lib.recursiveUpdate { } [ + # Base configuration + { + forceSSL = true; + useACMEHost = domain; + } + # Proxy to port + (lib.optionalAttrs (args.port != null) { + locations."/".proxyPass = + "http://127.0.0.1:${toString args.port}"; + # TODO make ipv6 possible + # http://[::1]:${toString args.port}; + }) + # Serve filesystem content + (lib.optionalAttrs (args.root != null) { + inherit (args) root; + }) + # VHost specific configuration + args.extraConfig + # SSO configuration + (lib.optionalAttrs args.sso.enable { + extraConfig = (args.extraConfig.extraConfig or "") + '' + error_page 401 = @error401; + ''; + locations = { + "@error401".return = '' + 302 https://${cfg.sso.subdomain}.${config.networking.domain}/login?go=$scheme://$http_host$request_uri + ''; + "/" = { + extraConfig = + (args.extraConfig.locations."/".extraConfig or "") + '' + # Use SSO + auth_request /sso-auth; + # Set username through header + auth_request_set $username $upstream_http_x_username; + proxy_set_header X-User $username; + # Renew SSO cookie on request + auth_request_set $cookie $upstream_http_set_cookie; + add_header Set-Cookie $cookie; + ''; + }; + "/sso-auth" = { + proxyPass = "http://localhost:${toString cfg.sso.port}/auth"; + extraConfig = '' + # Do not allow requests from outside + internal; + # Do not forward the request body + proxy_pass_request_body off; + proxy_set_header Content-Length ""; + # Set X-Application according to subdomain for matching + proxy_set_header X-Application "${subdomain}"; + # Set origin URI for matching + proxy_set_header X-Origin-URI $request_uri; + ''; }; }; - }]); - inherit (cfg.sso) groups; + }) + ]) + ; + in + genAttrs' cfg.virtualHosts mkVHost; + sso = { + enable = true; + configuration = { + listen = { + addr = "127.0.0.1"; + inherit (cfg.sso) port; + }; + audit_log = { + target = [ + "fd://stdout" + ]; + events = [ + "access_denied" + "login_success" + "login_failure" + "logout" + "validate" + ]; + headers = [ + "x-origin-uri" + "x-application" + ]; + }; + cookie = { + domain = ".${config.networking.domain}"; + secure = true; + authentication_key = { + _secret = cfg.sso.authKeyFile; }; - }; - acl = { - rule_sets = [ - { - rules = [{ field = "x-application"; present = true; }]; - allow = [ "@root" ]; - } - ]; + }; + login = { + title = "Bühlers's SSO"; + default_method = "simple"; + hide_mfa_field = false; + names = { + simple = "Username / Password"; + }; + }; + providers = { + simple = + let + applyUsers = lib.flip lib.mapAttrs cfg.sso.users; + in + { + users = applyUsers (_: v: { _secret = v.passwordHashFile; }); + mfa = applyUsers (_: v: [{ + provider = "totp"; + attributes = { + secret = { + _secret = v.totpSecretFile; + }; + }; + }]); + inherit (cfg.sso) groups; + }; + }; + acl = { + rule_sets = [ + { + rules = [{ field = "x-application"; present = true; }]; + allow = [ "@root" ]; + } + ]; + }; }; }; }; + + # services.prometheus = lib.mkIf cfg.monitoring.enable { + prometheus = { + exporters.nginx = { + enable = true; + listenAddress = "127.0.0.1"; + }; + scrapeConfigs = [ + { + job_name = "nginx"; + static_configs = [ + { + targets = [ "127.0.0.1:${toString config.services.prometheus.exporters.nginx.port}" ]; + labels = { + instance = config.networking.hostName; + }; + } + ]; + } + ]; + }; + grafana.provision = { + dashboards.settings.providers = [ + { + name = "Nginx"; + options.path = pkgs.grafana-dashboards.nginx; + disableDeletion = true; + } + ]; + }; }; + my.services.nginx.virtualHosts = [ { subdomain = "login"; @@ -407,35 +441,5 @@ in }; }; }; - - # services.prometheus = lib.mkIf cfg.monitoring.enable { - services.prometheus = { - exporters.nginx = { - enable = true; - listenAddress = "127.0.0.1"; - }; - scrapeConfigs = [ - { - job_name = "nginx"; - static_configs = [ - { - targets = [ "127.0.0.1:${toString config.services.prometheus.exporters.nginx.port}" ]; - labels = { - instance = config.networking.hostName; - }; - } - ]; - } - ]; - }; - services.grafana.provision = { - dashboards.settings.providers = [ - { - name = "Nginx"; - options.path = pkgs.grafana-dashboards.nginx; - disableDeletion = true; - } - ]; - }; }; } diff --git a/modules/services/prometheus/default.nix b/modules/services/prometheus/default.nix index 50bf1c9..26bb42c 100644 --- a/modules/services/prometheus/default.nix +++ b/modules/services/prometheus/default.nix @@ -78,112 +78,116 @@ in }; config = lib.mkIf cfg.enable { - services.prometheus = { - enable = true; - webExternalUrl = "https://monitor.${domain}"; - inherit (cfg) port; - listenAddress = "127.0.0.1"; - - inherit (cfg) retentionTime; - - globalConfig = { - scrape_interval = cfg.scrapeInterval; - }; - - ruleFiles = [ - (pkgs.writeText "prometheus-rules.yml" (builtins.toJSON { - groups = [ - { - name = "alerting-rules"; - rules = lib.mapAttrsToList - (name: opts: { - alert = name; - expr = opts.condition; - for = opts.time; - inherit (opts) labels; - annotations = { - inherit (opts) description; - grafana = lib.optionalString config.services.grafana.enable "https://visualization.${domain}"; - }; - }) - cfg.rules; - } - ]; - })) - ]; - - scrapeConfigs = [ - { - job_name = "prometheus"; - static_configs = [{ - targets = [ "127.0.0.1:${toString cfg.port}" ]; - labels = { - instance = config.networking.hostName; - }; - }]; - } - ]; - }; - - my.services.node-exporter.enable = true; - - services.grafana.provision = { - datasources.settings.datasources = [ - { - name = "Prometheus"; - type = "prometheus"; - isDefault = true; - url = "http://127.0.0.1:${toString config.services.prometheus.port}"; - jsonData = { - prometheusType = "Prometheus"; - prometheusVersion = toString pkgs.prometheus.version; - timeInterval = config.services.prometheus.globalConfig.scrape_interval; - }; - } - ]; - dashboards.settings.providers = [ - { - name = "Prometheus"; - options.path = pkgs.grafana-dashboards.prometheus; - disableDeletion = true; - } - ]; - }; - - my.services.prometheus.rules = { - prometheus_too_many_restarts = { - condition = ''changes(process_start_time_seconds{job=~"prometheus|alertmanager"}[15m]) > 2''; - description = "Prometheus has restarted more than twice in the last 15 minutes. It might be crashlooping"; - }; - - alert_manager_config_not_synced = { - condition = ''count(count_values("config_hash", alertmanager_config_hash)) > 1''; - description = "Configurations of AlertManager cluster instances are out of sync"; - }; - - prometheus_not_connected_to_alertmanager = { - condition = "prometheus_notifications_alertmanagers_discovered < 1"; - description = "Prometheus cannot connect the alertmanager\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"; - }; - - prometheus_rule_evaluation_failures = { - condition = "increase(prometheus_rule_evaluation_failures_total[3m]) > 0"; - description = "Prometheus encountered {{ $value }} rule evaluation failures, leading to potentially ignored alerts.\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"; - }; - - prometheus_template_expansion_failures = { - condition = "increase(prometheus_template_text_expansion_failures_total[3m]) > 0"; - time = "0m"; - description = "Prometheus encountered {{ $value }} template text expansion failures\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"; - }; - }; - - my.services.nginx.virtualHosts = [ - { - subdomain = "monitor"; + services = { + prometheus = { + enable = true; + webExternalUrl = "https://monitor.${domain}"; inherit (cfg) port; - } - ]; + listenAddress = "127.0.0.1"; + + inherit (cfg) retentionTime; + + globalConfig = { + scrape_interval = cfg.scrapeInterval; + }; + + ruleFiles = [ + (pkgs.writeText "prometheus-rules.yml" (builtins.toJSON { + groups = [ + { + name = "alerting-rules"; + rules = lib.mapAttrsToList + (name: opts: { + alert = name; + expr = opts.condition; + for = opts.time; + inherit (opts) labels; + annotations = { + inherit (opts) description; + grafana = lib.optionalString config.services.grafana.enable "https://visualization.${domain}"; + }; + }) + cfg.rules; + } + ]; + })) + ]; + + scrapeConfigs = [ + { + job_name = "prometheus"; + static_configs = [{ + targets = [ "127.0.0.1:${toString cfg.port}" ]; + labels = { + instance = config.networking.hostName; + }; + }]; + } + ]; + }; + + grafana.provision = { + datasources.settings.datasources = [ + { + name = "Prometheus"; + type = "prometheus"; + isDefault = true; + url = "http://127.0.0.1:${toString config.services.prometheus.port}"; + jsonData = { + prometheusType = "Prometheus"; + prometheusVersion = toString pkgs.prometheus.version; + timeInterval = config.services.prometheus.globalConfig.scrape_interval; + }; + } + ]; + dashboards.settings.providers = [ + { + name = "Prometheus"; + options.path = pkgs.grafana-dashboards.prometheus; + disableDeletion = true; + } + ]; + }; + }; + + my.services = { + node-exporter.enable = true; + + prometheus.rules = { + prometheus_too_many_restarts = { + condition = ''changes(process_start_time_seconds{job=~"prometheus|alertmanager"}[15m]) > 2''; + description = "Prometheus has restarted more than twice in the last 15 minutes. It might be crashlooping"; + }; + + alert_manager_config_not_synced = { + condition = ''count(count_values("config_hash", alertmanager_config_hash)) > 1''; + description = "Configurations of AlertManager cluster instances are out of sync"; + }; + + prometheus_not_connected_to_alertmanager = { + condition = "prometheus_notifications_alertmanagers_discovered < 1"; + description = "Prometheus cannot connect the alertmanager\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"; + }; + + prometheus_rule_evaluation_failures = { + condition = "increase(prometheus_rule_evaluation_failures_total[3m]) > 0"; + description = "Prometheus encountered {{ $value }} rule evaluation failures, leading to potentially ignored alerts.\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"; + }; + + prometheus_template_expansion_failures = { + condition = "increase(prometheus_template_text_expansion_failures_total[3m]) > 0"; + time = "0m"; + description = "Prometheus encountered {{ $value }} template text expansion failures\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"; + }; + }; + + nginx.virtualHosts = [ + { + subdomain = "monitor"; + inherit (cfg) port; + } + ]; + }; webapps.apps = { prometheus.dashboard = { diff --git a/modules/system/docker/default.nix b/modules/system/docker/default.nix index bf95406..f913942 100644 --- a/modules/system/docker/default.nix +++ b/modules/system/docker/default.nix @@ -19,32 +19,34 @@ in autoPrune.enable = true; }; - services.cadvisor.enable = config.services.prometheus.enable; + services = { + cadvisor.enable = config.services.prometheus.enable; - services.prometheus = { - scrapeConfigs = [ - { - job_name = "docker"; - static_configs = [ - { - targets = [ "127.0.0.1:${toString config.services.cadvisor.port}" ]; - labels = { - instance = config.networking.hostName; - }; - } - ]; - } - ]; - }; - # dashboard untested - services.grafana.provision = { - dashboards.settings.providers = [ - { - name = "Docker"; - options.path = pkgs.grafana-dashboards.cadvisor; - disableDeletion = true; - } - ]; + prometheus = { + scrapeConfigs = [ + { + job_name = "docker"; + static_configs = [ + { + targets = [ "127.0.0.1:${toString config.services.cadvisor.port}" ]; + labels = { + instance = config.networking.hostName; + }; + } + ]; + } + ]; + }; + # dashboard untested + grafana.provision = { + dashboards.settings.providers = [ + { + name = "Docker"; + options.path = pkgs.grafana-dashboards.cadvisor; + disableDeletion = true; + } + ]; + }; }; }; } diff --git a/profiles/gaming/default.nix b/profiles/gaming/default.nix index c36fb6f..b316831 100644 --- a/profiles/gaming/default.nix +++ b/profiles/gaming/default.nix @@ -24,8 +24,10 @@ in programs.steam.enable = true; - hardware.opengl.driSupport32Bit = true; - hardware.opengl.extraPackages32 = with pkgs.pkgsi686Linux; [ libva ]; - hardware.pulseaudio.support32Bit = true; + hardware = { + opengl.driSupport32Bit = true; + opengl.extraPackages32 = with pkgs.pkgsi686Linux; [ libva ]; + pulseaudio.support32Bit = true; + }; }; } diff --git a/profiles/gnome/default.nix b/profiles/gnome/default.nix index c303040..d84d986 100644 --- a/profiles/gnome/default.nix +++ b/profiles/gnome/default.nix @@ -9,7 +9,6 @@ in config = lib.mkIf cfg.enable { programs.gnome-disks.enable = true; - services.udisks2.enable = true; xdg.mime.enable = true; @@ -17,9 +16,12 @@ in programs.dconf.enable = true; # gnome services - services.dbus.packages = [ pkgs.dconf ]; - services.udev.packages = [ pkgs.gnome.gnome-settings-daemon ]; - services.gnome.gnome-keyring.enable = true; + services = { + udisks2.enable = true; + dbus.packages = [ pkgs.dconf ]; + udev.packages = [ pkgs.gnome.gnome-settings-daemon ]; + gnome.gnome-keyring.enable = true; + }; environment.systemPackages = with pkgs; [ glib diff --git a/profiles/nautilus/default.nix b/profiles/nautilus/default.nix index 2430c0e..523e3b3 100644 --- a/profiles/nautilus/default.nix +++ b/profiles/nautilus/default.nix @@ -14,24 +14,26 @@ in # enable trash & network-mount services.gvfs.enable = true; - environment.sessionVariables.NAUTILUS_4_EXTENSION_DIR = "${config.system.path}/lib/nautilus/extensions-4"; - environment.pathsToLink = [ - "/share/nautilus-python/extensions" - ]; - services.gnome.glib-networking.enable = true; # network-mount # default-programs xdg.mime.enable = true; xdg.icons.enable = true; - environment.systemPackages = with pkgs; [ - gnome.nautilus + environment = { + systemPackages = with pkgs; [ + gnome.nautilus - ffmpegthumbnailer # thumbnails - gnome.nautilus-python # enable plugins - gst_all_1.gst-libav # thumbnails - nautilus-open-any-terminal # terminal-context-entry - ]; + ffmpegthumbnailer # thumbnails + gnome.nautilus-python # enable plugins + gst_all_1.gst-libav # thumbnails + nautilus-open-any-terminal # terminal-context-entry + ]; + + sessionVariables.NAUTILUS_4_EXTENSION_DIR = "${config.system.path}/lib/nautilus/extensions-4"; + pathsToLink = [ + "/share/nautilus-python/extensions" + ]; + }; }; } diff --git a/profiles/sway/default.nix b/profiles/sway/default.nix index ffc40b7..1e88007 100644 --- a/profiles/sway/default.nix +++ b/profiles/sway/default.nix @@ -28,48 +28,50 @@ in ]; environment.pathsToLink = [ "/libexec" ]; - programs.wshowkeys.enable = true; - programs.light.enable = true; + programs = { + wshowkeys.enable = true; + light.enable = true; - programs.sway = { - enable = true; - wrapperFeatures = { - gtk = true; - base = true; + sway = { + enable = true; + wrapperFeatures = { + gtk = true; + base = true; + }; + + extraPackages = with pkgs; [ + brightnessctl + dmenu + foot + gammastep + grim + i3status-rust + mako + slurp + swayidle + swaylock + wdisplays + wf-recorder + wl-clipboard + wofi + xwayland + # wshowkeys + ]; + + extraSessionCommands = '' + export XDG_SESSION_TYPE=wayland + export XDG_CURRENT_DESKTOP=sway + export SDL_VIDEODRIVER=wayland + export QT_QPA_PLATFORM=wayland + export QT_WAYLAND_DISABLE_WINDOWDECORATION="1" + export _JAVA_AWT_WM_NONREPARENTING=1 + export CLUTTER_BACKEND=wayland + export SAL_USE_VCLPLUGIN=gtk3 + export MOZ_ENABLE_WAYLAND=1 + export MOZ_USE_XINPUT2=1 + export NIXOS_OZONE_WL=1 + ''; }; - - extraPackages = with pkgs; [ - brightnessctl - dmenu - foot - gammastep - grim - i3status-rust - mako - slurp - swayidle - swaylock - wdisplays - wf-recorder - wl-clipboard - wofi - xwayland - # wshowkeys - ]; - - extraSessionCommands = '' - export XDG_SESSION_TYPE=wayland - export XDG_CURRENT_DESKTOP=sway - export SDL_VIDEODRIVER=wayland - export QT_QPA_PLATFORM=wayland - export QT_WAYLAND_DISABLE_WINDOWDECORATION="1" - export _JAVA_AWT_WM_NONREPARENTING=1 - export CLUTTER_BACKEND=wayland - export SAL_USE_VCLPLUGIN=gtk3 - export MOZ_ENABLE_WAYLAND=1 - export MOZ_USE_XINPUT2=1 - export NIXOS_OZONE_WL=1 - ''; }; }; }