normcap: fix on GNOME wayland when used via keybind or alt-f2 (#351763)
[NixPkgs.git] / nixos / modules / services / networking / deconz.nix
blob88e294f86c2de9366eaf6aa038fc6424fb8e036b
2   config,
3   lib,
4   pkgs,
5   ...
6 }:
8 let
9   cfg = config.services.deconz;
10   name = "deconz";
11   stateDir = "/var/lib/${name}";
12   # ref. upstream deconz.service
13   capabilities =
14     lib.optionals (cfg.httpPort < 1024 || cfg.wsPort < 1024) [ "CAP_NET_BIND_SERVICE" ]
15     ++ lib.optionals (cfg.allowRebootSystem) [ "CAP_SYS_BOOT" ]
16     ++ lib.optionals (cfg.allowRestartService) [ "CAP_KILL" ]
17     ++ lib.optionals (cfg.allowSetSystemTime) [ "CAP_SYS_TIME" ];
20   options.services.deconz = {
22     enable = lib.mkEnableOption "deCONZ, a Zigbee gateway for use with ConBee/RaspBee hardware (https://phoscon.de/)";
24     package = lib.mkOption {
25       type = lib.types.package;
26       default = pkgs.deconz;
27       defaultText = lib.literalExpression "pkgs.deconz";
28       description = "Which deCONZ package to use.";
29     };
31     device = lib.mkOption {
32       type = lib.types.nullOr lib.types.str;
33       default = null;
34       description = ''
35         Force deCONZ to use a specific USB device (e.g. /dev/ttyACM0). By
36         default it does a search.
37       '';
38     };
40     listenAddress = lib.mkOption {
41       type = lib.types.str;
42       default = "127.0.0.1";
43       description = ''
44         Pin deCONZ to the network interface specified through the provided IP
45         address. This applies for the webserver as well as the websocket
46         notifications.
47       '';
48     };
50     httpPort = lib.mkOption {
51       type = lib.types.port;
52       default = 80;
53       description = "TCP port for the web server.";
54     };
56     wsPort = lib.mkOption {
57       type = lib.types.port;
58       default = 443;
59       description = "TCP port for the WebSocket.";
60     };
62     openFirewall = lib.mkEnableOption "opening up the service ports in the firewall";
64     allowRebootSystem = lib.mkEnableOption "rebooting the system";
66     allowRestartService = lib.mkEnableOption "killing/restarting processes";
68     allowSetSystemTime = lib.mkEnableOption "setting the system time";
70     extraArgs = lib.mkOption {
71       type = lib.types.listOf lib.types.str;
72       default = [ ];
73       example = [
74         "--dbg-info=1"
75         "--dbg-err=2"
76       ];
77       description = ''
78         Extra command line arguments for deCONZ, see
79         https://github.com/dresden-elektronik/deconz-rest-plugin/wiki/deCONZ-command-line-parameters.
80       '';
81     };
82   };
84   config = lib.mkIf cfg.enable {
86     networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [
87       cfg.httpPort
88       cfg.wsPort
89     ];
91     services.udev.packages = [ cfg.package ];
93     systemd.services.deconz = {
94       description = "deCONZ Zigbee gateway";
95       wantedBy = [ "multi-user.target" ];
96       preStart = ''
97         # The service puts a nix store path reference in here, and that path can
98         # be garbage collected. Ensure the file gets "refreshed" on every start.
99         rm -f ${stateDir}/.local/share/dresden-elektronik/deCONZ/zcldb.txt
100       '';
101       postStart = ''
102         # Delay signalling service readiness until it's actually up.
103         while ! "${lib.getExe pkgs.curl}" -sSfL -o /dev/null "http://${cfg.listenAddress}:${toString cfg.httpPort}"; do
104             echo "Waiting for TCP port ${toString cfg.httpPort} to be open..."
105             sleep 1
106         done
107       '';
108       environment = {
109         HOME = stateDir;
110         XDG_RUNTIME_DIR = "/run/${name}";
111       };
112       serviceConfig = {
113         ExecStart =
114           "${lib.getExe cfg.package}"
115           + " -platform minimal"
116           + " --http-listen=${cfg.listenAddress}"
117           + " --http-port=${toString cfg.httpPort}"
118           + " --ws-port=${toString cfg.wsPort}"
119           + " --auto-connect=1"
120           + (lib.optionalString (cfg.device != null) " --dev=${cfg.device}")
121           + " "
122           + (lib.escapeShellArgs cfg.extraArgs);
123         Restart = "on-failure";
124         AmbientCapabilities = capabilities;
125         CapabilityBoundingSet = capabilities;
126         UMask = "0027";
127         DynamicUser = true;
128         RuntimeDirectory = name;
129         RuntimeDirectoryMode = "0700";
130         StateDirectory = name;
131         SuccessExitStatus = [ 143 ];
132         WorkingDirectory = stateDir;
133         # For access to /dev/ttyACM0 (ConBee).
134         SupplementaryGroups = [ "dialout" ];
135         ProtectHome = true;
136       };
137     };
138   };