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
- '';
};
};
}