From eb6eebde166112397e8711a16a8618a52ecbcaca Mon Sep 17 00:00:00 2001 From: Azat Bahawi Date: Wed, 22 Mar 2023 15:20:22 +0300 Subject: 2023-03-22 --- modules/common/common/nix/default.nix | 12 +-- modules/common/profiles/default.nix | 1 + modules/common/profiles/email.nix | 89 ++++++++++++++++++++ modules/common/profiles/headful.nix | 76 +---------------- modules/nixos/default.nix | 2 + modules/nixos/monitoring/default.nix | 154 ++++++++++++++++++---------------- modules/nixos/nsd.nix | 3 +- modules/nixos/ntfy.nix | 57 +++++++++++++ modules/nixos/redis.nix | 36 ++++++++ modules/nixos/unbound.nix | 39 +++------ modules/nixos/victoriametrics.nix | 46 ++++++++++ 11 files changed, 326 insertions(+), 189 deletions(-) create mode 100644 modules/common/profiles/email.nix create mode 100644 modules/nixos/ntfy.nix create mode 100644 modules/nixos/redis.nix create mode 100644 modules/nixos/victoriametrics.nix (limited to 'modules') diff --git a/modules/common/common/nix/default.nix b/modules/common/common/nix/default.nix index b328e4c..45f8ed3 100644 --- a/modules/common/common/nix/default.nix +++ b/modules/common/common/nix/default.nix @@ -4,6 +4,7 @@ lib, localUsername ? lib.my.username, pkgs, + pkgsPR, this, ... }: @@ -98,16 +99,7 @@ with lib; { patches = [./patches/alejandra-no-ads.patch]; }); - logcli = super.grafana-loki.overrideAttrs (_: final: { - nativeBuildInputs = final.nativeBuildInputs ++ [pkgs.installShellFiles]; - subPackages = ["cmd/logcli"]; - postInstall = '' - installShellCompletion --cmd logcli \ - --bash <($out/bin/logcli --completion--script-bash) \ - --zsh <($out/bin/logcli --completion-script-zsh) - ''; - preFixup = null; - }); + inherit (pkgsPR "222519" "sha256-XQOs0rMs6GMXUZfzjYZiP7lTBOfqF3dsdWGr1rCQeH0=") grafanaPlugins; } // (with super; let np = nodePackages; diff --git a/modules/common/profiles/default.nix b/modules/common/profiles/default.nix index 06ddaf4..4f8fa4d 100644 --- a/modules/common/profiles/default.nix +++ b/modules/common/profiles/default.nix @@ -10,6 +10,7 @@ with lib; let in { imports = [ ./dev + ./email.nix ./headful.nix ./headless.nix (mkAliasOptionModule ["colourScheme"] [ diff --git a/modules/common/profiles/email.nix b/modules/common/profiles/email.nix new file mode 100644 index 0000000..e289c2e --- /dev/null +++ b/modules/common/profiles/email.nix @@ -0,0 +1,89 @@ +{ + config, + lib, + pkgs, + this, + ... +}: +with lib; let + cfg = config.nixfiles.modules.profiles.email.default; +in { + options.nixfiles.modules.profiles.email.default.enable = + mkEnableOption "Local Email management" // {default = this.isHeadful;}; + + config = mkIf cfg.enable { + hm = { + accounts.email = { + maildirBasePath = "${config.my.home}/doc/mail"; + + accounts = let + mkAccount = attrs: + mkMerge [ + { + mbsync = { + enable = true; + create = "both"; + expunge = "both"; + patterns = ["*"]; + }; + msmtp.enable = true; + mu.enable = true; + thunderbird = { + enable = pkgs.stdenv.isLinux; + settings = id: { + "mail.identity.id_${id}.compose_html" = false; + "mail.identity.id_${id}.reply_on_top" = 0; + }; + }; + } + attrs + ]; + + pass = path: "${config.hm.programs.password-store.package}/bin/pass show ${path}"; + in rec { + shire = mkAccount rec { + address = my.email; + aliases = [address "frodo@rohan.net" "azahi@shire.net"]; + realName = my.fullname; + gpg = { + inherit (my.pgp) key; + signByDefault = true; + encryptByDefault = false; + }; + + primary = true; + + imap = { + host = "shire.net"; + port = 993; + tls.enable = true; + }; + smtp = { + host = "shire.net"; + port = 465; + tls.enable = true; + }; + userName = "azahi@shire.net"; + passwordCommand = pass "email/shire.net/azahi"; + }; + + yahoo = mkAccount rec { + address = "admin@yahoo.com"; + aliases = [address "admin@yahoo.com"]; + realName = "Багавиев Азат"; + + flavor = "yahoo.com"; + userName = "admin@yahoo.com"; + passwordCommand = pass "email/yahoo.com/admin"; + }; + }; + }; + + programs = { + mbsync.enable = true; + msmtp.enable = true; + mu.enable = true; + }; + }; + }; +} diff --git a/modules/common/profiles/headful.nix b/modules/common/profiles/headful.nix index ea36b91..2be1b87 100644 --- a/modules/common/profiles/headful.nix +++ b/modules/common/profiles/headful.nix @@ -19,6 +19,7 @@ in { aria2.enable = true; emacs.enable = true; mpv.enable = true; + nullmailer.enable = true; openssh.client.enable = true; password-store.enable = true; }; @@ -33,85 +34,10 @@ in { packages = with pkgs; [ fd - logcli ripgrep ripgrep-all sd ]; - - sessionVariables.LOKI_ADDR = "https://loki.shire.net"; - }; - - accounts.email = { - maildirBasePath = "${config.my.home}/mail"; - - accounts = let - mkAccount = attrs: - mkMerge [ - { - mbsync = { - enable = true; - create = "both"; - expunge = "both"; - patterns = ["*"]; - }; - msmtp.enable = true; - mu.enable = true; - thunderbird = { - enable = pkgs.stdenv.isLinux; - settings = id: { - "mail.identity.id_${id}.compose_html" = false; - "mail.identity.id_${id}.reply_on_top" = 0; - }; - }; - } - attrs - ]; - - pass = path: "${config.hm.programs.password-store.package}/bin/pass show ${path}"; - in rec { - shire = mkAccount rec { - address = my.email; - aliases = [address "frodo@rohan.net" "azahi@shire.net"]; - realName = my.fullname; - gpg = { - inherit (my.pgp) key; - signByDefault = true; - encryptByDefault = false; - }; - - primary = true; - - imap = { - host = "shire.net"; - port = 993; - tls.enable = true; - }; - smtp = { - host = "shire.net"; - port = 465; - tls.enable = true; - }; - userName = "azahi@shire.net"; - passwordCommand = pass "email/shire.net/azahi"; - }; - - yahoo = mkAccount rec { - address = "admin@yahoo.com"; - aliases = [address "admin@yahoo.com"]; - realName = "Багавиев Азат"; - - flavor = "yahoo.com"; - userName = "admin@yahoo.com"; - passwordCommand = pass "email/yahoo.com/admin"; - }; - }; - }; - - programs = { - mbsync.enable = true; - msmtp.enable = true; - mu.enable = true; }; }; diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix index 269ce39..3c4192d 100644 --- a/modules/nixos/default.nix +++ b/modules/nixos/default.nix @@ -36,6 +36,7 @@ _: { ./nginx.nix ./node-exporter.nix ./nsd.nix + ./ntfy.nix ./nullmailer.nix ./openssh.nix ./podman.nix @@ -46,6 +47,7 @@ _: { ./psd.nix ./radarr.nix ./radicale.nix + ./redis.nix ./rss-bridge.nix ./rtorrent.nix ./searx.nix diff --git a/modules/nixos/monitoring/default.nix b/modules/nixos/monitoring/default.nix index 1108be6..6cdc2c9 100644 --- a/modules/nixos/monitoring/default.nix +++ b/modules/nixos/monitoring/default.nix @@ -1,78 +1,93 @@ { config, lib, + pkgs, ... }: with lib; let cfg = config.nixfiles.modules.monitoring; in { options.nixfiles.modules.monitoring.enable = mkEnableOption '' - a custom monitoring stack bas on the Grafana Labs toolkit + a glue to provision a monitoring stack ''; config = mkIf cfg.enable { nixfiles.modules = { + alertmanager.enable = true; grafana.enable = true; loki.enable = true; prometheus.enable = true; - alertmanager.enable = true; }; services = { - grafana.provision = { - enable = true; - - # https://grafana.com/docs/grafana/latest/administration/provisioning/#data-sources - datasources.settings.datasources = with config.nixfiles.modules; [ - { - name = "Prometheus"; - type = "prometheus"; - access = "proxy"; - url = "https://${prometheus.domain}"; - isDefault = true; - } - { - name = "Loki"; - type = "loki"; - access = "proxy"; - url = "https://${loki.domain}"; - } - { - name = "Alertmanager"; - type = "alertmanager"; - access = "proxy"; - jsonData.implementation = "prometheus"; - url = "https://${alertmanager.domain}"; - } + grafana = { + declarativePlugins = with pkgs.grafanaPlugins; [ + redis-app + redis-datasource + redis-explorer-app ]; - # https://grafana.com/docs/grafana/latest/administration/provisioning/#dashboards - dashboards.settings.providers = [ - # System dashboard is imported manually from here[1]. Too bad - # provisioned dashboards cannot properly integrate dynamic datasources - # yet. - # - # [1]: https://grafana.com/grafana/dashboards/1860-node-exporter-full - { - name = "endlessh"; - options.path = ./dashboards/endlessh.json; - } - { - name = "unbound"; - options.path = ./dashboards/unbound.json; - } - { - name = "nginx"; - options.path = ./dashboards/nginx.json; - } - { - name = "postgersql"; - options.path = ./dashboards/postgresql.json; - } - ]; + provision = { + enable = true; - alerting = { - contactPoints.settings.contactPoints = [ + # https://grafana.com/docs/grafana/latest/administration/provisioning/#data-sources + datasources.settings.datasources = with config.nixfiles.modules; [ + { + name = "Alertmanager"; + type = "alertmanager"; + access = "proxy"; + jsonData.implementation = "prometheus"; + url = "https://${alertmanager.domain}"; + } + { + name = "Loki"; + type = "loki"; + access = "proxy"; + url = "https://${loki.domain}"; + isDefault = true; + } + { + name = "Prometheus"; + type = "prometheus"; + access = "proxy"; + url = "https://${prometheus.domain}"; + } + (mkIf config.nixfiles.modules.redis.enable { + name = "Redis"; + type = "redis-datasource"; + access = "proxy"; + url = with config.services.redis.servers.default; "redis://${bind}:${toString port}"; + jsonData.client = "standalone"; + }) + ]; + + # https://grafana.com/docs/grafana/latest/administration/provisioning/#dashboards + dashboards.settings.providers = [ + # The System dashboard is imported manually from here[1]. Too bad + # provisioned dashboards cannot properly integrate dynamic datasources + # yet. + # + # [1]: https://grafana.com/grafana/dashboards/1860-node-exporter-full + { + name = "endlessh"; + options.path = ./dashboards/endlessh.json; + } + { + name = "unbound"; + options.path = ./dashboards/unbound.json; + } + { + name = "nginx"; + options.path = ./dashboards/nginx.json; + } + { + name = "postgersql"; + options.path = ./dashboards/postgresql.json; + } + ]; + + # https://grafana.com/docs/grafana/latest/administration/provisioning/#alerting + alerting.contactPoints.settings.contactPoints = [ { name = "Alertmanager"; receivers = [ @@ -84,25 +99,6 @@ in { ]; } ]; - muteTimings.settings.muteTimes = [ - { - name = "Sleep"; - time_intervals = [ - { - times = [ - { - start_time = "23:00"; - end_time = "24:00"; - } - { - start_time = "00:00"; - end_time = "09:00"; - } - ]; - } - ]; - } - ]; }; }; @@ -139,7 +135,6 @@ in { mkTargets [ manwe - varda yavanna ] nginx.port; @@ -174,6 +169,19 @@ in { } ]; } + { + job_name = "redis"; + static_configs = [ + { + targets = + mkTargets + [ + manwe + ] + redis.port; + } + ]; + } { job_name = "unbound"; static_configs = [ diff --git a/modules/nixos/nsd.nix b/modules/nixos/nsd.nix index 0dade8f..d2ab117 100644 --- a/modules/nixos/nsd.nix +++ b/modules/nixos/nsd.nix @@ -112,13 +112,12 @@ in { gotify = manwe; grafana = manwe; loki = manwe; + ntfy = manwe; prometheus = manwe; radicale = manwe; rss-bridge = manwe; vaultwarden = manwe; - minecraft = varda; - flood = yavanna; }; } diff --git a/modules/nixos/ntfy.nix b/modules/nixos/ntfy.nix new file mode 100644 index 0000000..2fd3234 --- /dev/null +++ b/modules/nixos/ntfy.nix @@ -0,0 +1,57 @@ +{ + config, + lib, + ... +}: +with lib; let + cfg = config.nixfiles.modules.ntfy; +in { + options.nixfiles.modules.ntfy = { + enable = mkEnableOption "ntfy"; + + port = mkOption { + description = "Port."; + type = types.port; + default = 2586; + }; + + domain = mkOption { + description = "Domain name sans protocol scheme."; + type = with types; str; + default = "ntfy.${config.networking.domain}"; + }; + }; + + config = mkIf cfg.enable { + nixfiles.modules.nginx = { + enable = true; + upstreams.ntfy.servers.${config.services.ntfy-sh.settings.listen-http} = {}; + virtualHosts.${cfg.domain} = { + locations."/" = { + proxyPass = "http://ntfy"; + proxyWebsockets = true; + }; + extraConfig = nginxInternalOnly; + }; + }; + + services.ntfy-sh = { + enable = true; + settings = { + listen-http = "127.0.0.1:${toString cfg.port}"; + base-url = "https://${cfg.domain}"; + cache-file = "/var/cache/ntfy/cache.db"; + behind-proxy = true; + attachment-cache-dir = "/var/cache/ntfy/attachments"; + auth-file = "/var/lib/ntfy/user.db"; + auth-default-access = "deny-all"; + }; + }; + + systemd.tmpfiles.rules = with config.services.ntfy-sh; [ + "d /var/lib/ntfy 0700 ${user} ${group} - -" + "d /var/cache/ntfy 0700 ${user} ${group} - -" + "d /var/cache/ntfy/attachments 0700 ${user} ${group} - -" + ]; + }; +} diff --git a/modules/nixos/redis.nix b/modules/nixos/redis.nix new file mode 100644 index 0000000..166407e --- /dev/null +++ b/modules/nixos/redis.nix @@ -0,0 +1,36 @@ +{ + config, + lib, + this, + ... +}: +with lib; let + cfg = config.nixfiles.modules.redis; +in { + options.nixfiles.modules.redis.enable = mkEnableOption "Redis"; + + config = mkIf cfg.enable { + services = { + redis = { + servers.default = { + enable = true; + bind = "127.0.0.1"; + port = 6379; + }; + vmOverCommit = true; + }; + + prometheus.exporters = { + redis = { + enable = true; + listenAddress = mkDefault this.wireguard.ipv4.address; + port = mkDefault 9121; + extraFlags = with config.services.redis.servers.default; [ + "--redis.addr=redis://${bind}:${toString port}" + "--redis.user=${user}" + ]; + }; + }; + }; + }; +} diff --git a/modules/nixos/unbound.nix b/modules/nixos/unbound.nix index 103e375..2291cc7 100644 --- a/modules/nixos/unbound.nix +++ b/modules/nixos/unbound.nix @@ -22,6 +22,8 @@ in { adblock-conf = "${config.services.unbound.stateDir}/adblock.conf"; in mkIf cfg.enable { + nixfiles.modules.redis.enable = true; + services = { unbound = { enable = true; @@ -114,7 +116,7 @@ in { } ]; - cachedb = with config.services.redis.servers.unbound; { + cachedb = with config.services.redis.servers.default; { backend = "redis"; redis-server-host = bind; redis-server-port = port; @@ -124,34 +126,13 @@ in { localControlSocketPath = "/run/unbound/unbound.socket"; }; - redis = { - servers.unbound = { - enable = true; - bind = "127.0.0.1"; - port = 6379; - }; - vmOverCommit = mkForce true; - }; - - prometheus.exporters = { - unbound = { - enable = true; - listenAddress = mkDefault this.wireguard.ipv4.address; - port = 9167; - fetchType = "uds"; - controlInterface = config.services.unbound.localControlSocketPath; - inherit (config.services.unbound) group user; - }; - - redis = { - enable = true; - listenAddress = mkDefault this.wireguard.ipv4.address; - port = mkDefault 9121; - extraFlags = with config.services.redis.servers.unbound; [ - "--redis.addr=redis://${bind}:${toString port}" - "--redis.user=${user}" - ]; - }; + prometheus.exporters.unbound = { + enable = true; + listenAddress = mkDefault this.wireguard.ipv4.address; + port = 9167; + fetchType = "uds"; + controlInterface = config.services.unbound.localControlSocketPath; + inherit (config.services.unbound) group user; }; }; diff --git a/modules/nixos/victoriametrics.nix b/modules/nixos/victoriametrics.nix new file mode 100644 index 0000000..509ee17 --- /dev/null +++ b/modules/nixos/victoriametrics.nix @@ -0,0 +1,46 @@ +{ + config, + lib, + ... +}: +with lib; let + cfg = config.nixfiles.modules.prometheus; +in { + options.nixfiles.modules.prometheus = { + enable = mkEnableOption "VictoriaMetrics"; + + port = mkOption { + description = "Port."; + type = with types; port; + default = 30113; + }; + + domain = mkOption { + description = "Domain name sans protocol scheme."; + type = with types; str; + default = "victoriametrics.${config.networking.domain}"; + }; + }; + + config = mkIf cfg.enable { + nixfiles.modules.nginx = with cfg; { + enable = true; + upstreams.victoriametrics.servers."127.0.0.1:${toString cfg.port}" = {}; + virtualHosts.${domain} = { + locations."/".proxyPass = "http://victoriametrics"; + extraConfig = nginxInternalOnly; + }; + }; + + services.victoriametrics = { + enable = true; + + listenAddress = "127.0.0.1:${toString cfg.port}"; + + extraOptions = [ + "-loggerLevel=WARN" + # TODO scrape_config + ]; + }; + }; +} -- cgit 1.4.1