grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / misc / mollysocket.nix
blobf40caa4a782ef68cc5298a22b205d3ff4e29a325
1 { config, lib, pkgs, ... }:
3 let
4   inherit (lib) getExe mkIf mkOption mkEnableOption optionals types;
6   cfg = config.services.mollysocket;
7   configuration = format.generate "mollysocket.conf" cfg.settings;
8   format = pkgs.formats.toml { };
9   package = pkgs.writeShellScriptBin "mollysocket" ''
10     MOLLY_CONF=${configuration} exec ${getExe pkgs.mollysocket} "$@"
11   '';
12 in {
13   options.services.mollysocket = {
14     enable = mkEnableOption ''
15       [MollySocket](https://github.com/mollyim/mollysocket) for getting Signal
16       notifications via UnifiedPush
17     '';
19     settings = mkOption {
20       default = { };
21       description = ''
22         Configuration for MollySocket. Available options are listed
23         [here](https://github.com/mollyim/mollysocket#configuration).
24       '';
25       type = types.submodule {
26         freeformType = format.type;
27         options = {
28           host = mkOption {
29             default = "127.0.0.1";
30             description = "Listening address of the web server";
31             type = types.str;
32           };
34           port = mkOption {
35             default = 8020;
36             description = "Listening port of the web server";
37             type = types.port;
38           };
40           allowed_endpoints = mkOption {
41             default = [ "*" ];
42             description = "List of UnifiedPush servers";
43             example = [ "https://ntfy.sh" ];
44             type = with types; listOf str;
45           };
47           allowed_uuids = mkOption {
48             default = [ "*" ];
49             description = "UUIDs of Signal accounts that may use this server";
50             example = [ "abcdef-12345-tuxyz-67890" ];
51             type = with types; listOf str;
52           };
53         };
54       };
55     };
57     environmentFile = mkOption {
58       default = null;
59       description = ''
60         Environment file (see {manpage}`systemd.exec(5)` "EnvironmentFile="
61         section for the syntax) passed to the service. This option can be
62         used to safely include secrets in the configuration.
63       '';
64       example = "/run/secrets/mollysocket";
65       type = with types; nullOr path;
66     };
68     logLevel = mkOption {
69       default = "info";
70       description = "Set the {env}`RUST_LOG` environment variable";
71       example = "debug";
72       type = types.str;
73     };
74   };
76   config = mkIf cfg.enable {
77     environment.systemPackages = [
78       package
79     ];
81     # see https://github.com/mollyim/mollysocket/blob/main/mollysocket.service
82     systemd.services.mollysocket = {
83       description = "MollySocket";
84       wantedBy = [ "multi-user.target" ];
85       after = [ "network-online.target" ];
86       wants = [ "network-online.target" ];
87       environment.RUST_LOG = cfg.logLevel;
88       serviceConfig = let
89         capabilities = [ "" ] ++ optionals (cfg.settings.port < 1024) [ "CAP_NET_BIND_SERVICE" ];
90       in {
91         EnvironmentFile = cfg.environmentFile;
92         ExecStart = "${getExe package} server";
93         KillSignal = "SIGINT";
94         Restart = "on-failure";
95         StateDirectory = "mollysocket";
96         TimeoutStopSec = 5;
97         WorkingDirectory = "/var/lib/mollysocket";
99         # hardening
100         AmbientCapabilities = capabilities;
101         CapabilityBoundingSet = capabilities;
102         DevicePolicy = "closed";
103         DynamicUser = true;
104         LockPersonality = true;
105         MemoryDenyWriteExecute = true;
106         NoNewPrivileges = true;
107         PrivateDevices = true;
108         PrivateTmp = true;
109         PrivateUsers = true;
110         ProcSubset = "pid";
111         ProtectClock = true;
112         ProtectControlGroups = true;
113         ProtectHome = true;
114         ProtectHostname = true;
115         ProtectKernelLogs = true;
116         ProtectKernelModules = true;
117         ProtectKernelTunables = true;
118         ProtectProc = "invisible";
119         ProtectSystem = "strict";
120         RemoveIPC = true;
121         RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
122         RestrictNamespaces = true;
123         RestrictRealtime = true;
124         RestrictSUIDSGID = true;
125         SystemCallArchitectures = "native";
126         SystemCallFilter = [ "@system-service" "~@resources" "~@privileged" ];
127         UMask = "0077";
128       };
129     };
130   };
132   meta.maintainers = with lib.maintainers; [ dotlambda ];