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 {
75 NTFY_URL = cfg.settings.ntfyUrl;
76 BAUTH_USER = cfg.settings.bauthUser;
77 }
78 // lib.optionalAttrs (cfg.settings.ntfyBAuthUser != null) {
79 NTFY_BAUTH_USER = cfg.settings.ntfyBAuthUser;
80 };
81
82 serviceConfig = {
83 LoadCredential =
84 [
85 "BAUTH_PASS_FILE:${cfg.settings.bauthPass}"
86 ]
87 ++ lib.optional (
88 cfg.settings.ntfyBAuthPass != null
89 ) "NTFY_BAUTH_PASS_FILE:${cfg.settings.ntfyBAuthPass}";
90
91 DynamicUser = true;
92 CapabilityBoundingSet = [ "" ];
93 DeviceAllow = "";
94 LockPersonality = true;
95 PrivateDevices = true;
96 PrivateUsers = true;
97 ProcSubset = "pid";
98 ProtectClock = true;
99 ProtectControlGroups = true;
100 ProtectHome = true;
101 ProtectHostname = true;
102 ProtectKernelLogs = true;
103 ProtectKernelModules = true;
104 ProtectKernelTunables = true;
105 ProtectProc = "invisible";
106 RestrictAddressFamilies = [
107 "AF_INET"
108 "AF_INET6"
109 "AF_UNIX"
110 ];
111 RestrictNamespaces = true;
112 RestrictRealtime = true;
113 MemoryDenyWriteExecute = true;
114 SystemCallArchitectures = "native";
115 SystemCallFilter = [
116 "@system-service"
117 "~@privileged"
118 ];
119 UMask = "0077";
120 };
121 };
122 };
123}