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