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 --- flake.nix | 35 +++++-- lib/my.nix | 1 + 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 +++++++++ nixosConfigurations/eonwe/default.nix | 1 - nixosConfigurations/manwe/default.nix | 58 ++++++------ nixosConfigurations/manwe/mailserver.nix | 8 ++ 16 files changed, 392 insertions(+), 226 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 diff --git a/flake.nix b/flake.nix index fc96852..a1fe2f5 100644 --- a/flake.nix +++ b/flake.nix @@ -145,6 +145,17 @@ # nixpkgs.follows = "nixpkgs"; # }; # }; + # alertmanager-gotify = { + # type = "github"; + # owner = "pinpox"; + # repo = "alertmanager-ntfy"; + # ref = "main"; + # inputs = { + # flake-compat.follows = "flake-compat"; + # flake-utils.follows = "flake-utils"; + # nixpkgs.follows = "nixpkgs"; + # }; + # }; flake-utils = { type = "github"; @@ -236,7 +247,6 @@ overlays = [self.overlays.default]; }; in { - # TODO Add packages from `self.overlay.default`. packages = with lib; (mapAttrs (_: c: c.config.system.build.toplevel) (builtins.removeAttrs self.nixosConfigurations ["iso-arm" "iso-x86"])) @@ -298,12 +308,23 @@ darwinModules.nixfiles = import ./modules/darwin; darwinConfigurations = importConfigurations ./darwinConfigurations; - overlays.default = final: _: { - bruh = final.callPackage ./packages/bruh.nix {}; - mpv-autosub = final.callPackage ./packages/mpv-autosub.nix {}; - myip = final.callPackage ./packages/myip.nix {}; - nixfiles = final.callPackage ./packages/nixfiles.nix {}; - throttled = final.callPackage ./packages/throttled.nix {}; + overlays.default = final: prev: rec { + bruh = prev.callPackage ./packages/bruh.nix {}; + mpv-autosub = prev.callPackage ./packages/mpv-autosub.nix {}; + myip = prev.callPackage ./packages/myip.nix {}; + nixfiles = prev.callPackage ./packages/nixfiles.nix {}; + throttled = prev.callPackage ./packages/throttled.nix {}; + logcli = prev.grafana-loki.overrideAttrs (_: super: { + pname = "logcli"; + subPackages = ["cmd/logcli"]; + nativeBuildInputs = super.nativeBuildInputs ++ [final.installShellFiles]; + postInstall = '' + installShellCompletion --cmd logcli \ + --bash <($out/bin/logcli --completion--script-bash) \ + --zsh <($out/bin/logcli --completion-script-zsh) + ''; + preFixup = null; + }); }; }); } diff --git a/lib/my.nix b/lib/my.nix index 03cb37a..96f26f3 100644 --- a/lib/my.nix +++ b/lib/my.nix @@ -168,6 +168,7 @@ with lib; "gotify.${shire}" "grafana.${shire}" "loki.${shire}" + "ntfy.${shire}" "prometheus.${shire}" "radicale.${shire}" "rss-bridge.${shire}" 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 + ]; + }; + }; +} diff --git a/nixosConfigurations/eonwe/default.nix b/nixosConfigurations/eonwe/default.nix index b5a5fc4..4c29013 100644 --- a/nixosConfigurations/eonwe/default.nix +++ b/nixosConfigurations/eonwe/default.nix @@ -25,7 +25,6 @@ with lib; { libvirtd.enable = true; qutebrowser.enable = true; mpd.enable = true; - nullmailer.enable = true; }; hm = { diff --git a/nixosConfigurations/manwe/default.nix b/nixosConfigurations/manwe/default.nix index a47cd88..a3c16b0 100644 --- a/nixosConfigurations/manwe/default.nix +++ b/nixosConfigurations/manwe/default.nix @@ -1,6 +1,5 @@ { config, - inputs, lib, ... }: @@ -44,36 +43,37 @@ with lib; { domain = my.domain.azahi; }; vaultwarden.enable = true; + ntfy.enable = true; }; - # To play old LAN games with the boys. - secrets."wireguard-private-key-70".file = "${inputs.self}/secrets/wireguard-private-key-70"; - networking = mkIf config.nixfiles.modules.wireguard.server.enable { - wireguard.interfaces.wg70 = { - ips = ["10.70.0.1/16"]; - listenPort = 7070; - privateKeyFile = config.secrets."wireguard-private-key-70".path; - peers = [ - { - publicKey = "@PUBLIC_KEY@"; - allowedIPs = ["10.70.1.1/32"]; - } - { - publicKey = "@PUBLIC_KEY@"; - allowedIPs = ["10.70.1.2/32"]; - } - { - publicKey = "@PUBLIC_KEY@"; - allowedIPs = ["10.70.1.3/32"]; - } - { - publicKey = "@PUBLIC_KEY@"; - allowedIPs = ["10.70.1.4/32"]; - } - ]; - }; - firewall.allowedUDPPorts = [7070]; - }; + # A VPN to play old LAN games with the boys. + # secrets."wireguard-private-key-70".file = "${inputs.self}/secrets/wireguard-private-key-70"; + # networking = mkIf config.nixfiles.modules.wireguard.server.enable { + # wireguard.interfaces.wg70 = { + # ips = ["10.70.0.1/16"]; + # listenPort = 7070; + # privateKeyFile = config.secrets."wireguard-private-key-70".path; + # peers = [ + # { + # publicKey = "@PUBLIC_KEY@"; + # allowedIPs = ["10.70.1.1/32"]; + # } + # { + # publicKey = "@PUBLIC_KEY@"; + # allowedIPs = ["10.70.1.2/32"]; + # } + # { + # publicKey = "@PUBLIC_KEY@"; + # allowedIPs = ["10.70.1.3/32"]; + # } + # { + # publicKey = "@PUBLIC_KEY@"; + # allowedIPs = ["10.70.1.4/32"]; + # } + # ]; + # }; + # firewall.allowedUDPPorts = [7070]; + # }; boot = { loader.grub = { diff --git a/nixosConfigurations/manwe/mailserver.nix b/nixosConfigurations/manwe/mailserver.nix index e8d1781..b59f0a8 100644 --- a/nixosConfigurations/manwe/mailserver.nix +++ b/nixosConfigurations/manwe/mailserver.nix @@ -7,6 +7,8 @@ with lib; { imports = [inputs.simple-nixos-mailserver.nixosModule]; + nixfiles.modules.redis.enable = true; + secrets = { dkim-key-azahi-cc = { file = "${inputs.self}/secrets/dkim-key-azahi-cc"; @@ -52,6 +54,12 @@ with lib; { lmtpSaveToDetailMailbox = "no"; + redis = with config.services.redis.servers.default; { + address = bind; + inherit port; + password = requirePass; + }; + loginAccounts = with my.domain; { "azahi@${shire}" = { hashedPassword = "@HASHED_PASSWORD@"; -- cgit 1.4.1