From b2fccae80913400dc6b63aa37c27a5c96243fcad Mon Sep 17 00:00:00 2001 From: Graham Bennett Date: Sat, 13 May 2023 22:42:00 +0100 Subject: zwave-js: module init, zwave-js-server: init at 1.33.0 Co-authored-by: Martin Weinelt Co-authored-by: h7x4 --- .../modules/services/home-automation/zwave-js.nix | 152 +++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 nixos/modules/services/home-automation/zwave-js.nix (limited to 'nixos/modules/services') 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 000000000000..87c9b8f1ac81 --- /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 + + 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 ]; +} -- cgit v1.2.3