1{ config, lib, pkgs, ... }:
2
3with lib;
4let
5 cfg = config.services.signald;
6 dataDir = "/var/lib/signald";
7 defaultUser = "signald";
8in
9{
10 options.services.signald = {
11 enable = mkEnableOption "signald, the unofficial daemon for interacting with Signal";
12
13 user = mkOption {
14 type = types.str;
15 default = defaultUser;
16 description = "User under which signald runs.";
17 };
18
19 group = mkOption {
20 type = types.str;
21 default = defaultUser;
22 description = "Group under which signald runs.";
23 };
24
25 socketPath = mkOption {
26 type = types.str;
27 default = "/run/signald/signald.sock";
28 description = "Path to the signald socket";
29 };
30 };
31
32 config = mkIf cfg.enable {
33 users.users = optionalAttrs (cfg.user == defaultUser) {
34 ${defaultUser} = {
35 group = cfg.group;
36 isSystemUser = true;
37 };
38 };
39
40 users.groups = optionalAttrs (cfg.group == defaultUser) {
41 ${defaultUser} = { };
42 };
43
44 systemd.services.signald = {
45 description = "A daemon for interacting with the Signal Private Messenger";
46 wants = [ "network.target" ];
47 wantedBy = [ "multi-user.target" ];
48 after = [ "network.target" ];
49
50 serviceConfig = {
51 User = cfg.user;
52 Group = cfg.group;
53 ExecStart = "${pkgs.signald}/bin/signald -d ${dataDir} -s ${cfg.socketPath}";
54 Restart = "on-failure";
55 StateDirectory = "signald";
56 RuntimeDirectory = "signald";
57 StateDirectoryMode = "0750";
58 RuntimeDirectoryMode = "0750";
59
60 BindReadOnlyPaths = [
61 "/nix/store"
62 "-/etc/resolv.conf"
63 "-/etc/nsswitch.conf"
64 "-/etc/hosts"
65 "-/etc/localtime"
66 ];
67 CapabilityBoundingSet = "";
68 # ProtectClock= adds DeviceAllow=char-rtc r
69 DeviceAllow = "";
70 # Use a static user so other applications can access the files
71 #DynamicUser = true;
72 LockPersonality = true;
73 # Needed for java
74 #MemoryDenyWriteExecute = true;
75 NoNewPrivileges = true;
76 PrivateDevices = true;
77 PrivateMounts = true;
78 # Needs network access
79 #PrivateNetwork = true;
80 PrivateTmp = true;
81 PrivateUsers = true;
82 ProcSubset = "pid";
83 ProtectClock = true;
84 ProtectHome = true;
85 ProtectHostname = true;
86 # Would re-mount paths ignored by temporary root
87 #ProtectSystem = "strict";
88 ProtectControlGroups = true;
89 ProtectKernelLogs = true;
90 ProtectKernelModules = true;
91 ProtectKernelTunables = true;
92 ProtectProc = "invisible";
93 RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
94 RestrictNamespaces = true;
95 RestrictRealtime = true;
96 RestrictSUIDSGID = true;
97 SystemCallArchitectures = "native";
98 SystemCallFilter = [ "@system-service" "~@privileged @resources @setuid @keyring" ];
99 TemporaryFileSystem = "/:ro";
100 # Does not work well with the temporary root
101 #UMask = "0066";
102 };
103 };
104 };
105}