1 {config, pkgs, lib, ...}:
3 cfg = config.services.zwave-js;
4 mergedConfigFile = "/run/zwave-js/config.json";
5 settingsFormat = pkgs.formats.json {};
7 options.services.zwave-js = {
8 enable = lib.mkEnableOption "the zwave-js server on boot";
10 package = lib.mkPackageOption pkgs "zwave-js-server" { };
13 type = lib.types.port;
16 Port for the server to listen on.
20 serialPort = lib.mkOption {
21 type = lib.types.path;
23 Serial port device path for Z-Wave controller.
25 example = "/dev/ttyUSB0";
28 secretsConfigFile = lib.mkOption {
29 type = lib.types.path;
31 JSON file containing secret keys. A dummy example:
36 "S0_Legacy": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
37 "S2_Unauthenticated": "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
38 "S2_Authenticated": "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC",
39 "S2_AccessControl": "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
45 <https://zwave-js.github.io/node-zwave-js/#/getting-started/security-s2>
46 for details. This file will be merged with the module-generated config
47 file (taking precedence).
49 Z-Wave keys can be generated with:
51 {command}`< /dev/urandom tr -dc A-F0-9 | head -c32 ;echo`
55 A file in the nix store should not be used since it will be readable to
59 example = "/secrets/zwave-js-keys.json";
62 settings = lib.mkOption {
63 type = lib.types.submodule {
64 freeformType = settingsFormat.type;
68 cacheDir = lib.mkOption {
69 type = lib.types.path;
70 default = "/var/cache/zwave-js";
72 description = "Cache directory";
79 Configuration settings for the generated config
84 extraFlags = lib.mkOption {
85 type = with lib.types; listOf str;
87 example = [ "--mock-driver" ];
89 Extra flags to pass to command
94 config = lib.mkIf cfg.enable {
95 systemd.services.zwave-js = let
96 configFile = settingsFormat.generate "zwave-js-config.json" cfg.settings;
98 wantedBy = [ "multi-user.target" ];
99 after = [ "network.target" ];
100 description = "Z-Wave JS Server";
103 /bin/sh -c "${pkgs.jq}/bin/jq -s '.[0] * .[1]' ${configFile} ${cfg.secretsConfigFile} > ${mergedConfigFile}"
105 ExecStart = lib.concatStringsSep " " [
106 "${cfg.package}/bin/zwave-server"
107 "--config ${mergedConfigFile}"
108 "--port ${toString cfg.port}"
110 (lib.escapeShellArgs cfg.extraFlags)
112 Restart = "on-failure";
114 SupplementaryGroups = [ "dialout" ];
115 CacheDirectory = "zwave-js";
116 RuntimeDirectory = "zwave-js";
119 CapabilityBoundingSet = "";
120 DeviceAllow = [cfg.serialPort];
121 DevicePolicy = "closed";
123 LockPersonality = true;
124 MemoryDenyWriteExecute = false;
125 NoNewPrivileges = true;
129 ProtectControlGroups = true;
131 ProtectHostname = true;
132 ProtectKernelLogs = true;
133 ProtectKernelModules = true;
135 RestrictNamespaces = true;
136 RestrictRealtime = true;
137 RestrictSUIDSGID = true;
138 SystemCallArchitectures = "native";
140 "@system-service @pkey"
141 "~@privileged @resources"
148 meta.maintainers = with lib.maintainers; [ graham33 ];