1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7
8let
9 cfg = config.services.grafana-to-ntfy;
10in
11{
12 options = {
13 services.grafana-to-ntfy = {
14 enable = lib.mkEnableOption "Grafana-to-ntfy (ntfy.sh) alerts channel";
15
16 package = lib.mkPackageOption pkgs "grafana-to-ntfy" { };
17
18 settings = {
19 ntfyUrl = lib.mkOption {
20 type = lib.types.str;
21 description = "The URL to the ntfy-sh topic.";
22 example = "https://push.example.com/grafana";
23 };
24
25 ntfyBAuthUser = lib.mkOption {
26 type = lib.types.nullOr lib.types.str;
27 description = ''
28 The ntfy-sh user to use for authenticating with the ntfy-sh instance.
29 Setting this option is required when using a ntfy-sh instance with access control enabled.
30 '';
31 default = null;
32 example = "grafana";
33 };
34
35 ntfyBAuthPass = lib.mkOption {
36 type = lib.types.path;
37 description = ''
38 The path to the password for the specified ntfy-sh user.
39 Setting this option is required when using a ntfy-sh instance with access control enabled.
40 '';
41 default = null;
42 };
43
44 bauthUser = lib.mkOption {
45 type = lib.types.str;
46 description = ''
47 The user that you will authenticate with in the Grafana webhook settings.
48 You can set this to whatever you like, as this is not the same as the ntfy-sh user.
49 '';
50 default = "admin";
51 };
52
53 bauthPass = lib.mkOption {
54 type = lib.types.path;
55 description = "The path to the password you will use in the Grafana webhook settings.";
56 };
57 };
58 };
59 };
60
61 config = lib.mkIf cfg.enable {
62 systemd.services.grafana-to-ntfy = {
63 wantedBy = [ "multi-user.target" ];
64
65 script = ''
66 export BAUTH_PASS=$(${lib.getExe' config.systemd.package "systemd-creds"} cat BAUTH_PASS_FILE)
67 ${lib.optionalString (cfg.settings.ntfyBAuthPass != null) ''
68 export NTFY_BAUTH_PASS=$(${lib.getExe' config.systemd.package "systemd-creds"} cat NTFY_BAUTH_PASS_FILE)
69 ''}
70 exec ${lib.getExe cfg.package}
71 '';
72
73 environment = {
74 NTFY_URL = cfg.settings.ntfyUrl;
75 BAUTH_USER = cfg.settings.bauthUser;
76 }
77 // lib.optionalAttrs (cfg.settings.ntfyBAuthUser != null) {
78 NTFY_BAUTH_USER = cfg.settings.ntfyBAuthUser;
79 };
80
81 serviceConfig = {
82 LoadCredential = [
83 "BAUTH_PASS_FILE:${cfg.settings.bauthPass}"
84 ]
85 ++ lib.optional (
86 cfg.settings.ntfyBAuthPass != null
87 ) "NTFY_BAUTH_PASS_FILE:${cfg.settings.ntfyBAuthPass}";
88
89 DynamicUser = true;
90 CapabilityBoundingSet = [ "" ];
91 DeviceAllow = "";
92 LockPersonality = true;
93 PrivateDevices = true;
94 PrivateUsers = true;
95 ProcSubset = "pid";
96 ProtectClock = true;
97 ProtectControlGroups = true;
98 ProtectHome = true;
99 ProtectHostname = true;
100 ProtectKernelLogs = true;
101 ProtectKernelModules = true;
102 ProtectKernelTunables = true;
103 ProtectProc = "invisible";
104 RestrictAddressFamilies = [
105 "AF_INET"
106 "AF_INET6"
107 "AF_UNIX"
108 ];
109 RestrictNamespaces = true;
110 RestrictRealtime = true;
111 MemoryDenyWriteExecute = true;
112 SystemCallArchitectures = "native";
113 SystemCallFilter = [
114 "@system-service"
115 "~@privileged"
116 ];
117 UMask = "0077";
118 };
119 };
120 };
121}