summary refs log tree commit diff
diff options
context:
space:
mode:
authorGraham Bennett <graham@grahambennett.org>2023-05-13 22:42:00 +0100
committerGraham Bennett <graham@grahambennett.org>2023-11-02 08:21:09 +0000
commitb2fccae80913400dc6b63aa37c27a5c96243fcad (patch)
treeedb47252bd49af0d4657453e9415cde8105d8e4f
parent8b1d659c6bda61723b373a4ea74a76c35c2af552 (diff)
downloadnixpkgs-b2fccae80913400dc6b63aa37c27a5c96243fcad.tar
nixpkgs-b2fccae80913400dc6b63aa37c27a5c96243fcad.tar.gz
nixpkgs-b2fccae80913400dc6b63aa37c27a5c96243fcad.tar.bz2
nixpkgs-b2fccae80913400dc6b63aa37c27a5c96243fcad.tar.lz
nixpkgs-b2fccae80913400dc6b63aa37c27a5c96243fcad.tar.xz
nixpkgs-b2fccae80913400dc6b63aa37c27a5c96243fcad.tar.zst
nixpkgs-b2fccae80913400dc6b63aa37c27a5c96243fcad.zip
zwave-js: module init, zwave-js-server: init at 1.33.0
Co-authored-by: Martin Weinelt <mweinelt@users.noreply.github.com>
Co-authored-by: h7x4 <h7x4@nani.wtf>
-rw-r--r--nixos/doc/manual/release-notes/rl-2311.section.md2
-rw-r--r--nixos/modules/module-list.nix1
-rw-r--r--nixos/modules/services/home-automation/zwave-js.nix152
-rw-r--r--nixos/tests/all-tests.nix1
-rw-r--r--nixos/tests/zwave-js.nix31
-rw-r--r--pkgs/by-name/zw/zwave-js-server/package.nix36
-rw-r--r--pkgs/development/node-packages/aliases.nix1
-rw-r--r--pkgs/development/node-packages/main-programs.nix1
-rw-r--r--pkgs/development/node-packages/node-packages.json1
-rw-r--r--pkgs/development/node-packages/node-packages.nix201
10 files changed, 224 insertions, 203 deletions
diff --git a/nixos/doc/manual/release-notes/rl-2311.section.md b/nixos/doc/manual/release-notes/rl-2311.section.md
index ffe977bf33b..eca3242cebb 100644
--- a/nixos/doc/manual/release-notes/rl-2311.section.md
+++ b/nixos/doc/manual/release-notes/rl-2311.section.md
@@ -104,6 +104,8 @@
 
 - hardware/infiniband.nix adds infiniband subnet manager support using an [opensm](https://github.com/linux-rdma/opensm) systemd-template service, instantiated on card guids. The module also adds kernel modules and cli tooling to help administrators debug and measure performance. Available as [hardware.infiniband.enable](#opt-hardware.infiniband.enable).
 
+- [zwave-js](https://github.com/zwave-js/zwave-js-server), a small server wrapper around Z-Wave JS to access it via a WebSocket. Available as [services.zwave-js](#opt-services.zwave-js.enable).
+
 - [Honk](https://humungus.tedunangst.com/r/honk), a complete ActivityPub server with minimal setup and support costs.
   Available as [services.honk](#opt-services.honk.enable).
 
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 2a6ca202024..f985de61445 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -563,6 +563,7 @@
   ./services/home-automation/home-assistant.nix
   ./services/home-automation/homeassistant-satellite.nix
   ./services/home-automation/zigbee2mqtt.nix
+  ./services/home-automation/zwave-js.nix
   ./services/logging/SystemdJournal2Gelf.nix
   ./services/logging/awstats.nix
   ./services/logging/filebeat.nix
diff --git a/nixos/modules/services/home-automation/zwave-js.nix b/nixos/modules/services/home-automation/zwave-js.nix
new file mode 100644
index 00000000000..87c9b8f1ac8
--- /dev/null
+++ b/nixos/modules/services/home-automation/zwave-js.nix
@@ -0,0 +1,152 @@
+{config, pkgs, lib, ...}:
+
+with lib;
+
+let
+  cfg = config.services.zwave-js;
+  mergedConfigFile = "/run/zwave-js/config.json";
+  settingsFormat = pkgs.formats.json {};
+in {
+  options.services.zwave-js = {
+    enable = mkEnableOption (mdDoc "the zwave-js server on boot");
+
+    package = mkPackageOptionMD pkgs "zwave-js-server" { };
+
+    port = mkOption {
+      type = types.port;
+      default = 3000;
+      description = mdDoc ''
+        Port for the server to listen on.
+      '';
+    };
+
+    serialPort = mkOption {
+      type = types.path;
+      description = mdDoc ''
+        Serial port device path for Z-Wave controller.
+      '';
+      example = "/dev/ttyUSB0";
+    };
+
+    secretsConfigFile = mkOption {
+      type = types.path;
+      description = mdDoc ''
+        JSON file containing secret keys. A dummy example:
+
+        ```
+        {
+          "securityKeys": {
+            "S0_Legacy": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+            "S2_Unauthenticated": "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
+            "S2_Authenticated": "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC",
+            "S2_AccessControl": "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
+          }
+        }
+        ```
+
+        See
+        <https://zwave-js.github.io/node-zwave-js/#/getting-started/security-s2>
+        for details. This file will be merged with the module-generated config
+        file (taking precedence).
+
+        Z-Wave keys can be generated with:
+
+          {command}`< /dev/urandom tr -dc A-F0-9 | head -c32 ;echo`
+
+
+        ::: {.warning}
+        A file in the nix store should not be used since it will be readable to
+        all users.
+        :::
+      '';
+      example = "/secrets/zwave-js-keys.json";
+    };
+
+    settings = mkOption {
+      type = lib.types.submodule {
+        freeformType = settingsFormat.type;
+
+        options = {
+          storage = {
+            cacheDir = mkOption {
+              type = types.path;
+              default = "/var/cache/zwave-js";
+              readOnly = true;
+              description = lib.mdDoc "Cache directory";
+            };
+          };
+        };
+      };
+      default = {};
+      description = mdDoc ''
+        Configuration settings for the generated config
+        file.
+      '';
+    };
+
+    extraFlags = lib.mkOption {
+      type = with lib.types; listOf str;
+      default = [ ];
+      example = [ "--mock-driver" ];
+      description = lib.mdDoc ''
+        Extra flags to pass to command
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.zwave-js = let
+      configFile = settingsFormat.generate "zwave-js-config.json" cfg.settings;
+    in {
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+      description = "Z-Wave JS Server";
+      serviceConfig = {
+        ExecStartPre = ''
+          /bin/sh -c "${pkgs.jq}/bin/jq -s '.[0] * .[1]' ${configFile} ${cfg.secretsConfigFile} > ${mergedConfigFile}"
+        '';
+        ExecStart = lib.concatStringsSep " " [
+          "${cfg.package}/bin/zwave-server"
+          "--config ${mergedConfigFile}"
+          "--port ${toString cfg.port}"
+          cfg.serialPort
+          (escapeShellArgs cfg.extraFlags)
+        ];
+        Restart = "on-failure";
+        User = "zwave-js";
+        SupplementaryGroups = [ "dialout" ];
+        CacheDirectory = "zwave-js";
+        RuntimeDirectory = "zwave-js";
+
+        # Hardening
+        CapabilityBoundingSet = "";
+        DeviceAllow = [cfg.serialPort];
+        DevicePolicy = "closed";
+        DynamicUser = true;
+        LockPersonality = true;
+        MemoryDenyWriteExecute = false;
+        NoNewPrivileges = true;
+        PrivateUsers = true;
+        PrivateTmp = true;
+        ProtectClock = true;
+        ProtectControlGroups = true;
+        ProtectHome = true;
+        ProtectHostname = true;
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        RemoveIPC = true;
+        RestrictNamespaces = true;
+        RestrictRealtime = true;
+        RestrictSUIDSGID = true;
+        SystemCallArchitectures = "native";
+        SystemCallFilter = [
+          "@system-service @pkey"
+          "~@privileged @resources"
+        ];
+        UMask = "0077";
+      };
+    };
+  };
+
+  meta.maintainers = with lib.maintainers; [ graham33 ];
+}
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index f7f8ac8fec8..891dc714876 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -932,4 +932,5 @@ in {
   zram-generator = handleTest ./zram-generator.nix {};
   zrepl = handleTest ./zrepl.nix {};
   zsh-history = handleTest ./zsh-history.nix {};
+  zwave-js = handleTest ./zwave-js.nix {};
 }
diff --git a/nixos/tests/zwave-js.nix b/nixos/tests/zwave-js.nix
new file mode 100644
index 00000000000..9239e6964fd
--- /dev/null
+++ b/nixos/tests/zwave-js.nix
@@ -0,0 +1,31 @@
+import ./make-test-python.nix ({ pkgs, lib, ...} :
+
+let
+  secretsConfigFile = pkgs.writeText "secrets.json" (builtins.toJSON {
+    securityKeys = {
+      "S0_Legacy" = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
+    };
+  });
+in {
+  name = "zwave-js";
+  meta.maintainers = with lib.maintainers; [ graham33 ];
+
+  nodes = {
+    machine = { config, ... }: {
+      services.zwave-js = {
+        enable = true;
+        serialPort = "/dev/null";
+        extraFlags = ["--mock-driver"];
+        inherit secretsConfigFile;
+      };
+    };
+  };
+
+  testScript = ''
+    start_all()
+
+    machine.wait_for_unit("zwave-js.service")
+    machine.wait_for_open_port(3000)
+    machine.wait_until_succeeds("journalctl --since -1m --unit zwave-js --grep 'ZwaveJS server listening'")
+  '';
+})
diff --git a/pkgs/by-name/zw/zwave-js-server/package.nix b/pkgs/by-name/zw/zwave-js-server/package.nix
new file mode 100644
index 00000000000..f97e16d6613
--- /dev/null
+++ b/pkgs/by-name/zw/zwave-js-server/package.nix
@@ -0,0 +1,36 @@
+{ lib
+, buildNpmPackage
+, fetchFromGitHub
+, nixosTests
+}:
+
+buildNpmPackage rec {
+  pname = "zwave-js-server";
+  version = "1.33.0";
+
+  src = fetchFromGitHub {
+    owner = "zwave-js";
+    repo = pname;
+    rev = version;
+    hash = "sha256-Lll3yE1v4ybJTjKO8dhPXMD/3VCn+9+fpnN7XczqaE4=";
+  };
+
+  npmDepsHash = "sha256-Re9fo+9+Z/+UGyDPlNWelH/4tLxcITPYXOCddQE9YDY=";
+
+  # For some reason the zwave-js dependency is in devDependencies
+  npmFlags = [ "--include=dev" ];
+
+  passthru = {
+    tests = {
+      inherit (nixosTests) zwave-js;
+    };
+  };
+
+  meta = {
+    changelog = "https://github.com/zwave-js/zwave-js-server/releases/tag/${version}";
+    description = "Small server wrapper around Z-Wave JS to access it via a WebSocket";
+    license = lib.licenses.asl20;
+    homepage = "https://github.com/zwave-js/zwave-js-server";
+    maintainers = with lib.maintainers; [ graham33 ];
+  };
+}
diff --git a/pkgs/development/node-packages/aliases.nix b/pkgs/development/node-packages/aliases.nix
index 3b4bf018e66..0bfe127efff 100644
--- a/pkgs/development/node-packages/aliases.nix
+++ b/pkgs/development/node-packages/aliases.nix
@@ -49,6 +49,7 @@ mapAliases {
   "@mermaid-js/mermaid-cli" = pkgs.mermaid-cli; # added 2023-10-01
   "@nerdwallet/shepherd" = pkgs.shepherd; # added 2023-09-30
   "@nestjs/cli" = pkgs.nest-cli; # Added 2023-05-06
+  "@zwave-js/server" = pkgs.zwave-js-server; # Added 2023-09-09
   alloy = pkgs.titanium-alloy; # added 2023-08-17
   antennas = pkgs.antennas; # added 2023-07-30
   inherit (pkgs) asar; # added 2023-08-26
diff --git a/pkgs/development/node-packages/main-programs.nix b/pkgs/development/node-packages/main-programs.nix
index bd722955690..7b57757a07c 100644
--- a/pkgs/development/node-packages/main-programs.nix
+++ b/pkgs/development/node-packages/main-programs.nix
@@ -60,5 +60,4 @@
   vscode-html-languageserver-bin = "html-languageserver";
   vscode-json-languageserver-bin = "json-languageserver";
   webtorrent-cli = "webtorrent";
-  "@zwave-js/server" = "zwave-server";
 }
diff --git a/pkgs/development/node-packages/node-packages.json b/pkgs/development/node-packages/node-packages.json
index f0e9b379f42..471b37c30bf 100644
--- a/pkgs/development/node-packages/node-packages.json
+++ b/pkgs/development/node-packages/node-packages.json
@@ -310,5 +310,4 @@
 , "@yaegassy/coc-nginx"
 , "yalc"
 , "yarn"
-, "@zwave-js/server"
 ]
diff --git a/pkgs/development/node-packages/node-packages.nix b/pkgs/development/node-packages/node-packages.nix
index 5f8eaa649d4..168d6b0c3c2 100644
--- a/pkgs/development/node-packages/node-packages.nix
+++ b/pkgs/development/node-packages/node-packages.nix
@@ -102095,205 +102095,4 @@ in
     bypassCache = true;
     reconstructLock = true;
   };
-  "@zwave-js/server" = nodeEnv.buildNodePackage {
-    name = "_at_zwave-js_slash_server";
-    packageName = "@zwave-js/server";
-    version = "1.33.0";
-    src = fetchurl {
-      url = "https://registry.npmjs.org/@zwave-js/server/-/server-1.33.0.tgz";
-      sha512 = "jHRpbeWcDVhTWidDTmln9x+lTveJ0H1cLJxl6dWIeWQ6YnB7YzRuHFDPhY+6ewAyUrc+Eq8tl+QnhjmVuevq+A==";
-    };
-    dependencies = [
-      (sources."@alcalzone/jsonl-db-3.1.0" // {
-        dependencies = [
-          sources."fs-extra-10.1.0"
-        ];
-      })
-      (sources."@alcalzone/pak-0.9.0" // {
-        dependencies = [
-          sources."execa-5.0.1"
-          sources."fs-extra-10.1.0"
-        ];
-      })
-      sources."@alcalzone/proper-lockfile-4.1.3-0"
-      sources."@colors/colors-1.6.0"
-      sources."@dabh/diagnostics-2.0.3"
-      sources."@homebridge/ciao-1.1.7"
-      sources."@leichtgewicht/ip-codec-2.0.4"
-      sources."@serialport/binding-mock-10.2.2"
-      (sources."@serialport/bindings-cpp-12.0.1" // {
-        dependencies = [
-          sources."@serialport/parser-delimiter-11.0.0"
-          sources."@serialport/parser-readline-11.0.0"
-          sources."node-gyp-build-4.6.0"
-        ];
-      })
-      sources."@serialport/bindings-interface-1.2.2"
-      sources."@serialport/parser-byte-length-12.0.0"
-      sources."@serialport/parser-cctalk-12.0.0"
-      sources."@serialport/parser-delimiter-12.0.0"
-      sources."@serialport/parser-inter-byte-timeout-12.0.0"
-      sources."@serialport/parser-packet-length-12.0.0"
-      sources."@serialport/parser-readline-12.0.0"
-      sources."@serialport/parser-ready-12.0.0"
-      sources."@serialport/parser-regex-12.0.0"
-      sources."@serialport/parser-slip-encoder-12.0.0"
-      sources."@serialport/parser-spacepacket-12.0.0"
-      sources."@serialport/stream-12.0.0"
-      sources."@sindresorhus/is-5.6.0"
-      sources."@szmarczak/http-timer-5.0.1"
-      sources."@types/http-cache-semantics-4.0.3"
-      sources."@types/triple-beam-1.3.4"
-      sources."@zwave-js/cc-12.3.0"
-      sources."@zwave-js/config-12.3.0"
-      sources."@zwave-js/core-12.3.0"
-      sources."@zwave-js/host-12.3.0"
-      sources."@zwave-js/nvmedit-12.3.0"
-      sources."@zwave-js/serial-12.3.0"
-      sources."@zwave-js/shared-12.2.3"
-      sources."@zwave-js/testing-12.3.0"
-      sources."alcalzone-shared-4.0.8"
-      sources."ansi-colors-4.1.3"
-      sources."ansi-regex-5.0.1"
-      sources."ansi-styles-4.3.0"
-      sources."async-3.2.4"
-      sources."asynckit-0.4.0"
-      sources."axios-0.27.2"
-      sources."buffer-from-1.1.2"
-      sources."bufferutil-4.0.8"
-      sources."cacheable-lookup-7.0.0"
-      sources."cacheable-request-10.2.14"
-      sources."cliui-8.0.1"
-      (sources."color-3.2.1" // {
-        dependencies = [
-          sources."color-convert-1.9.3"
-          sources."color-name-1.1.3"
-        ];
-      })
-      sources."color-convert-2.0.1"
-      sources."color-name-1.1.4"
-      sources."color-string-1.9.1"
-      sources."colorspace-1.1.4"
-      sources."combined-stream-1.0.8"
-      sources."cross-spawn-7.0.3"
-      sources."dayjs-1.11.10"
-      sources."debug-4.3.4"
-      (sources."decompress-response-6.0.0" // {
-        dependencies = [
-          sources."mimic-response-3.1.0"
-        ];
-      })
-      sources."defer-to-connect-2.0.1"
-      sources."delayed-stream-1.0.0"
-      sources."dns-packet-5.6.1"
-      sources."emoji-regex-8.0.0"
-      sources."enabled-2.0.0"
-      sources."escalade-3.1.1"
-      sources."eventemitter3-5.0.1"
-      sources."execa-5.1.1"
-      sources."fast-deep-equal-3.1.3"
-      sources."fecha-4.2.3"
-      sources."file-stream-rotator-0.6.1"
-      sources."fn.name-1.1.0"
-      sources."follow-redirects-1.15.3"
-      sources."form-data-4.0.0"
-      sources."form-data-encoder-2.1.4"
-      sources."fs-extra-11.1.1"
-      sources."get-caller-file-2.0.5"
-      sources."get-stream-6.0.1"
-      sources."globalyzer-0.1.0"
-      sources."globrex-0.1.2"
-      sources."got-13.0.0"
-      sources."graceful-fs-4.2.11"
-      sources."http-cache-semantics-4.1.1"
-      sources."http2-wrapper-2.2.0"
-      sources."human-signals-2.1.0"
-      sources."inherits-2.0.4"
-      sources."is-arrayish-0.3.2"
-      sources."is-fullwidth-code-point-3.0.0"
-      sources."is-stream-2.0.1"
-      sources."isexe-2.0.0"
-      sources."json-buffer-3.0.1"
-      sources."json-logic-js-2.0.2"
-      sources."json5-2.2.3"
-      sources."jsonfile-6.1.0"
-      sources."keyv-4.5.4"
-      sources."kuler-2.0.0"
-      sources."logform-2.6.0"
-      sources."lowercase-keys-3.0.0"
-      sources."lru-cache-6.0.0"
-      sources."mdns-server-1.0.11"
-      sources."merge-stream-2.0.0"
-      sources."mime-db-1.52.0"
-      sources."mime-types-2.1.35"
-      sources."mimic-fn-2.1.0"
-      sources."mimic-response-4.0.0"
-      sources."minimist-1.2.8"
-      sources."moment-2.29.4"
-      sources."ms-2.1.2"
-      sources."node-addon-api-7.0.0"
-      sources."node-gyp-build-4.6.1"
-      sources."normalize-url-8.0.0"
-      sources."npm-run-path-4.0.1"
-      sources."nrf-intel-hex-1.3.0"
-      sources."object-hash-2.2.0"
-      sources."one-time-1.0.0"
-      sources."onetime-5.1.2"
-      sources."p-cancelable-3.0.0"
-      sources."p-queue-7.4.1"
-      sources."p-timeout-5.1.0"
-      sources."path-key-3.1.1"
-      sources."proper-lockfile-4.1.2"
-      sources."quick-lru-5.1.1"
-      sources."readable-stream-3.6.2"
-      sources."reflect-metadata-0.1.13"
-      sources."require-directory-2.1.1"
-      sources."resolve-alpn-1.2.1"
-      sources."responselike-3.0.0"
-      sources."retry-0.12.0"
-      sources."safe-buffer-5.2.1"
-      sources."safe-stable-stringify-2.4.3"
-      sources."semver-7.5.4"
-      sources."serialport-12.0.0"
-      sources."shebang-command-2.0.0"
-      sources."shebang-regex-3.0.0"
-      sources."signal-exit-3.0.7"
-      sources."simple-swizzle-0.2.2"
-      sources."source-map-0.6.1"
-      sources."source-map-support-0.5.21"
-      sources."stack-trace-0.0.10"
-      sources."string-width-4.2.3"
-      sources."string_decoder-1.3.0"
-      sources."strip-ansi-6.0.1"
-      sources."strip-final-newline-2.0.0"
-      sources."text-hex-1.0.0"
-      sources."tiny-glob-0.2.9"
-      sources."triple-beam-1.4.1"
-      sources."tslib-2.6.2"
-      sources."universalify-2.0.1"
-      sources."utf-8-validate-6.0.3"
-      sources."util-deprecate-1.0.2"
-      sources."which-2.0.2"
-      sources."winston-3.11.0"
-      sources."winston-daily-rotate-file-4.7.1"
-      sources."winston-transport-4.6.0"
-      sources."wrap-ansi-7.0.0"
-      sources."ws-8.14.2"
-      sources."xstate-4.38.2"
-      sources."y18n-5.0.8"
-      sources."yallist-4.0.0"
-      sources."yargs-17.7.2"
-      sources."yargs-parser-21.1.1"
-      sources."zwave-js-12.3.0"
-    ];
-    buildInputs = globalBuildInputs;
-    meta = {
-      description = "Full access to zwave-js driver through Websockets";
-      homepage = "https://github.com/zwave-js/zwave-js-server#readme";
-      license = "Apache-2.0";
-    };
-    production = true;
-    bypassCache = true;
-    reconstructLock = true;
-  };
 }