nixos/ntfy-sh: init

Changed files
+131
nixos
doc
manual
from_md
release-notes
release-notes
modules
tests
+7
nixos/doc/manual/from_md/release-notes/rl-2211.section.xml
···
</listitem>
<listitem>
<para>
+
<link xlink:href="https://ntfy.sh">ntfy.sh</link>, a push
+
notification service. Available as
+
<link linkend="opt-services.ntfy-sh.enable">services.ntfy-sh</link>
+
</para>
+
</listitem>
+
<listitem>
+
<para>
<link xlink:href="https://git.sr.ht/~migadu/alps">alps</link>,
a simple and extensible webmail. Available as
<link linkend="opt-services.alps.enable">services.alps</link>.
+2
nixos/doc/manual/release-notes/rl-2211.section.md
···
- [Outline](https://www.getoutline.com/), a wiki and knowledge base similar to Notion. Available as [services.outline](#opt-services.outline.enable).
+
- [ntfy.sh](https://ntfy.sh), a push notification service. Available as [services.ntfy-sh](#opt-services.ntfy-sh.enable)
+
- [alps](https://git.sr.ht/~migadu/alps), a simple and extensible webmail. Available as [services.alps](#opt-services.alps.enable).
- [netbird](https://netbird.io), a zero configuration VPN.
+1
nixos/modules/module-list.nix
···
./services/misc/nix-optimise.nix
./services/misc/nix-ssh-serve.nix
./services/misc/novacomd.nix
+
./services/misc/ntfy-sh.nix
./services/misc/nzbget.nix
./services/misc/nzbhydra2.nix
./services/misc/octoprint.nix
+100
nixos/modules/services/misc/ntfy-sh.nix
···
+
{ config, lib, pkgs, ... }:
+
+
with lib;
+
+
let
+
cfg = config.services.ntfy-sh;
+
+
settingsFormat = pkgs.formats.yaml { };
+
in
+
+
{
+
options.services.ntfy-sh = {
+
enable = mkEnableOption (mdDoc "[ntfy-sh](https://ntfy.sh), a push notification service");
+
+
package = mkOption {
+
type = types.package;
+
default = pkgs.ntfy-sh;
+
defaultText = literalExpression "pkgs.ntfy-sh";
+
description = mdDoc "The ntfy.sh package to use.";
+
};
+
+
user = mkOption {
+
default = "ntfy-sh";
+
type = types.str;
+
description = lib.mdDoc "User the ntfy-sh server runs under.";
+
};
+
+
group = mkOption {
+
default = "ntfy-sh";
+
type = types.str;
+
description = lib.mdDoc "Primary group of ntfy-sh user.";
+
};
+
+
settings = mkOption {
+
type = types.submodule { freeformType = settingsFormat.type; };
+
+
default = { };
+
+
example = literalExpression ''
+
{
+
listen-http = ":8080";
+
}
+
'';
+
+
description = mdDoc ''
+
Configuration for ntfy.sh, supported values are [here](https://ntfy.sh/docs/config/#config-options).
+
'';
+
};
+
};
+
+
config =
+
let
+
configuration = settingsFormat.generate "server.yml" cfg.settings;
+
in
+
mkIf cfg.enable {
+
# to configure access control via the cli
+
environment = {
+
etc."ntfy/server.yml".source = configuration;
+
systemPackages = [ cfg.package ];
+
};
+
+
systemd.services.ntfy-sh = {
+
description = "Push notifications server";
+
+
wantedBy = [ "multi-user.target" ];
+
after = [ "network.target" ];
+
+
serviceConfig = {
+
ExecStart = "${cfg.package}/bin/ntfy serve -c ${configuration}";
+
User = cfg.user;
+
+
AmbientCapabilities = "CAP_NET_BIND_SERVICE";
+
PrivateTmp = true;
+
NoNewPrivileges = true;
+
CapabilityBoundingSet = "CAP_NET_BIND_SERVICE";
+
ProtectSystem = "full";
+
ProtectKernelTunables = true;
+
ProtectKernelModules = true;
+
ProtectKernelLogs = true;
+
ProtectControlGroups = true;
+
PrivateDevices = true;
+
RestrictSUIDSGID = true;
+
RestrictNamespaces = true;
+
RestrictRealtime = true;
+
MemoryDenyWriteExecute = true;
+
};
+
};
+
+
users.groups = optionalAttrs (cfg.group == "ntfy-sh") {
+
ntfy-sh = { };
+
};
+
+
users.users = optionalAttrs (cfg.user == "ntfy-sh") {
+
ntfy-sh = {
+
isSystemUser = true;
+
group = cfg.group;
+
};
+
};
+
};
+
}
+1
nixos/tests/all-tests.nix
···
noto-fonts = handleTest ./noto-fonts.nix {};
novacomd = handleTestOn ["x86_64-linux"] ./novacomd.nix {};
nsd = handleTest ./nsd.nix {};
+
ntfy-sh = handleTest ./ntfy-sh.nix {};
nzbget = handleTest ./nzbget.nix {};
nzbhydra2 = handleTest ./nzbhydra2.nix {};
oh-my-zsh = handleTest ./oh-my-zsh.nix {};
+20
nixos/tests/ntfy-sh.nix
···
+
import ./make-test-python.nix {
+
+
nodes.machine = { ... }: {
+
services.ntfy-sh.enable = true;
+
};
+
+
testScript = ''
+
import json
+
+
msg = "Test notification"
+
+
machine.wait_for_unit("multi-user.target")
+
+
machine.succeed(f"curl -d '{msg}' localhost:80/test")
+
+
notif = json.loads(machine.succeed("curl -s localhost:80/test/json?poll=1"))
+
+
assert msg == notif["message"], "Wrong message"
+
'';
+
}