1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.ntfy-sh;
7
8 settingsFormat = pkgs.formats.yaml { };
9in
10
11{
12 options.services.ntfy-sh = {
13 enable = mkEnableOption (mdDoc "[ntfy-sh](https://ntfy.sh), a push notification service");
14
15 package = mkOption {
16 type = types.package;
17 default = pkgs.ntfy-sh;
18 defaultText = literalExpression "pkgs.ntfy-sh";
19 description = mdDoc "The ntfy.sh package to use.";
20 };
21
22 user = mkOption {
23 default = "ntfy-sh";
24 type = types.str;
25 description = lib.mdDoc "User the ntfy-sh server runs under.";
26 };
27
28 group = mkOption {
29 default = "ntfy-sh";
30 type = types.str;
31 description = lib.mdDoc "Primary group of ntfy-sh user.";
32 };
33
34 settings = mkOption {
35 type = types.submodule { freeformType = settingsFormat.type; };
36
37 default = { };
38
39 example = literalExpression ''
40 {
41 listen-http = ":8080";
42 }
43 '';
44
45 description = mdDoc ''
46 Configuration for ntfy.sh, supported values are [here](https://ntfy.sh/docs/config/#config-options).
47 '';
48 };
49 };
50
51 config =
52 let
53 configuration = settingsFormat.generate "server.yml" cfg.settings;
54 in
55 mkIf cfg.enable {
56 # to configure access control via the cli
57 environment = {
58 etc."ntfy/server.yml".source = configuration;
59 systemPackages = [ cfg.package ];
60 };
61
62 services.ntfy-sh.settings = {
63 auth-file = mkDefault "/var/lib/ntfy-sh/user.db";
64 };
65
66 systemd.services.ntfy-sh = {
67 description = "Push notifications server";
68
69 wantedBy = [ "multi-user.target" ];
70 after = [ "network.target" ];
71
72 serviceConfig = {
73 ExecStart = "${cfg.package}/bin/ntfy serve -c ${configuration}";
74 User = cfg.user;
75 StateDirectory = "ntfy-sh";
76
77 AmbientCapabilities = "CAP_NET_BIND_SERVICE";
78 PrivateTmp = true;
79 NoNewPrivileges = true;
80 CapabilityBoundingSet = "CAP_NET_BIND_SERVICE";
81 ProtectSystem = "full";
82 ProtectKernelTunables = true;
83 ProtectKernelModules = true;
84 ProtectKernelLogs = true;
85 ProtectControlGroups = true;
86 PrivateDevices = true;
87 RestrictSUIDSGID = true;
88 RestrictNamespaces = true;
89 RestrictRealtime = true;
90 MemoryDenyWriteExecute = true;
91 };
92 };
93
94 users.groups = optionalAttrs (cfg.group == "ntfy-sh") {
95 ntfy-sh = { };
96 };
97
98 users.users = optionalAttrs (cfg.user == "ntfy-sh") {
99 ntfy-sh = {
100 isSystemUser = true;
101 group = cfg.group;
102 };
103 };
104 };
105}