diff --git a/nixos/doc/manual/release-notes/rl-2505.section.md b/nixos/doc/manual/release-notes/rl-2505.section.md index bfc3ad7dde6a..3d8576706a8e 100644 --- a/nixos/doc/manual/release-notes/rl-2505.section.md +++ b/nixos/doc/manual/release-notes/rl-2505.section.md @@ -164,6 +164,8 @@ - [OliveTin](https://www.olivetin.app/), gives safe and simple access to predefined shell commands from a web interface. Available as [services.olivetin](#opt-services.olivetin.enable). +- [alertmanager-ntfy](https://github.com/alexbakker/alertmanager-ntfy), forwards Prometheus Alertmanager notifications to ntfy.sh. Available as [services.prometheus.alertmanager-ntfy](#opt-services.prometheus.alertmanager-ntfy.enable). + - [Stash](https://github.com/stashapp/stash), An organizer for your adult videos/images, written in Go. Available as [services.stash](#opt-services.stash.enable). - [vsmartcard-vpcd](https://frankmorgner.github.io/vsmartcard/virtualsmartcard/README.html), a virtual smart card driver. Available as [services.vsmartcard-vpcd](#opt-services.vsmartcard-vpcd.enable). diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 616e9e6b3394..259ec5234bb6 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -982,6 +982,7 @@ ./services/monitoring/pgscv.nix ./services/monitoring/prometheus/alertmanager-gotify-bridge.nix ./services/monitoring/prometheus/alertmanager-irc-relay.nix + ./services/monitoring/prometheus/alertmanager-ntfy.nix ./services/monitoring/prometheus/alertmanager-webhook-logger.nix ./services/monitoring/prometheus/alertmanager.nix ./services/monitoring/prometheus/default.nix diff --git a/nixos/modules/services/monitoring/prometheus/alertmanager-ntfy.nix b/nixos/modules/services/monitoring/prometheus/alertmanager-ntfy.nix new file mode 100644 index 000000000000..5237a24406b1 --- /dev/null +++ b/nixos/modules/services/monitoring/prometheus/alertmanager-ntfy.nix @@ -0,0 +1,201 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.services.prometheus.alertmanager-ntfy; + + settingsFormat = pkgs.formats.yaml { }; + settingsFile = settingsFormat.generate "settings.yml" cfg.settings; + + configsArg = lib.concatStringsSep "," ( + [ settingsFile ] ++ lib.imap0 (i: _: "%d/config-${toString i}.yml") cfg.extraConfigFiles + ); +in + +{ + meta.maintainers = with lib.maintainers; [ defelo ]; + + options.services.prometheus.alertmanager-ntfy = { + enable = lib.mkEnableOption "alertmanager-ntfy"; + + package = lib.mkPackageOption pkgs "alertmanager-ntfy" { }; + + settings = lib.mkOption { + description = '' + Configuration of alertmanager-ntfy. + See for more information. + ''; + default = { }; + + type = lib.types.submodule { + freeformType = settingsFormat.type; + + options = { + http.addr = lib.mkOption { + type = lib.types.str; + description = "The address to listen on."; + default = "127.0.0.1:8000"; + example = ":8000"; + }; + + ntfy = { + baseurl = lib.mkOption { + type = lib.types.str; + description = "The base URL of the ntfy.sh instance."; + example = "https://ntfy.sh"; + }; + + notification = { + topic = lib.mkOption { + type = lib.types.str; + description = '' + The topic to which alerts should be published. + Can either be a hardcoded string or a gval expression that evaluates to a string. + ''; + example = "alertmanager"; + }; + + priority = lib.mkOption { + type = lib.types.str; + description = '' + The ntfy.sh message priority (see for more information). + Can either be a hardcoded string or a gval expression that evaluates to a string. + ''; + default = ''status == "firing" ? "high" : "default"''; + }; + + tags = lib.mkOption { + type = lib.types.listOf ( + lib.types.submodule { + options = { + tag = lib.mkOption { + type = lib.types.str; + description = '' + The tag to add. + See for a list of all supported emojis. + ''; + example = "rotating_light"; + }; + + condition = lib.mkOption { + type = lib.types.nullOr lib.types.str; + description = '' + The condition under which this tag should be added. + Tags with no condition are always included. + ''; + default = null; + example = ''status == "firing"''; + }; + }; + } + ); + description = '' + Tags to add to ntfy.sh messages. + See for more information. + ''; + default = [ + { + tag = "green_circle"; + condition = ''status == "resolved"''; + } + { + tag = "red_circle"; + condition = ''status == "firing"''; + } + ]; + }; + + templates = { + title = lib.mkOption { + type = lib.types.str; + description = "The ntfy.sh message title template."; + default = '' + {{ if eq .Status "resolved" }}Resolved: {{ end }}{{ index .Annotations "summary" }} + ''; + }; + + description = lib.mkOption { + type = lib.types.str; + description = "The ntfy.sh message description template."; + default = '' + {{ index .Annotations "description" }} + ''; + }; + }; + }; + }; + }; + }; + }; + + extraConfigFiles = lib.mkOption { + type = lib.types.listOf lib.types.path; + default = [ ]; + example = [ "/run/secrets/alertmanager-ntfy.yml" ]; + description = '' + Config files to merge into the settings defined in [](#opt-services.prometheus.alertmanager-ntfy.settings). + This is useful to avoid putting secrets into the Nix store. + See for more information. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.alertmanager-ntfy = { + wantedBy = [ "multi-user.target" ]; + + wants = [ "network-online.target" ]; + after = [ "network-online.target" ]; + + serviceConfig = { + User = "alertmanager-ntfy"; + Group = "alertmanager-ntfy"; + DynamicUser = true; + + LoadCredential = lib.imap0 (i: path: "config-${toString i}.yml:${path}") cfg.extraConfigFiles; + + ExecStart = "${lib.getExe cfg.package} --configs ${configsArg}"; + + Restart = "always"; + RestartSec = 5; + + # Hardening + AmbientCapabilities = ""; + CapabilityBoundingSet = [ "" ]; + DevicePolicy = "closed"; + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateTmp = true; + PrivateUsers = true; + ProcSubset = "pid"; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + ProtectSystem = "strict"; + RemoveIPC = true; + RestrictAddressFamilies = [ "AF_INET AF_INET6" ]; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + SystemCallFilter = [ + "@system-service" + "~@privileged" + "~@resources" + ]; + UMask = "0077"; + }; + }; + }; +}