1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7let
8 inherit (lib)
9 getExe
10 mkIf
11 mkEnableOption
12 mkOption
13 mkPackageOption
14 types
15 ;
16 cfg = config.services.zwave-js-ui;
17in
18{
19 options.services.zwave-js-ui = {
20 enable = mkEnableOption "zwave-js-ui";
21
22 package = mkPackageOption pkgs "zwave-js-ui" { };
23
24 serialPort = mkOption {
25 type = types.path;
26 description = ''
27 Serial port for the Z-Wave controller.
28
29 Only used to grant permissions to the device; must be additionally configured in the application
30 '';
31 example = "/dev/serial/by-id/usb-example";
32 };
33
34 settings = mkOption {
35 type = types.submodule {
36 freeformType =
37 with types;
38 attrsOf (
39 nullOr (oneOf [
40 str
41 path
42 package
43 ])
44 );
45
46 options = {
47 STORE_DIR = mkOption {
48 type = types.str;
49 default = "%S/zwave-js-ui";
50 visible = false;
51 readOnly = true;
52 };
53
54 ZWAVEJS_EXTERNAL_CONFIG = mkOption {
55 type = types.str;
56 default = "%S/zwave-js-ui/.config-db";
57 visible = false;
58 readOnly = true;
59 };
60 };
61 };
62
63 description = ''
64 Extra environment variables passed to the zwave-js-ui process.
65
66 Check <https://zwave-js.github.io/zwave-js-ui/#/guide/env-vars> for possible options
67 '';
68 example = {
69 HOST = "::";
70 PORT = "8091";
71 };
72 };
73 };
74 config = mkIf cfg.enable {
75 systemd.services.zwave-js-ui = {
76 environment = cfg.settings;
77 wantedBy = [ "multi-user.target" ];
78 serviceConfig = {
79 ExecStart = getExe cfg.package;
80 RuntimeDirectory = "zwave-js-ui";
81 StateDirectory = "zwave-js-ui";
82 RootDirectory = "%t/zwave-js-ui";
83 BindReadOnlyPaths = [
84 "/nix/store"
85 ];
86 DeviceAllow = [ cfg.serialPort ];
87 DynamicUser = true;
88 SupplementaryGroups = [ "dialout" ];
89 CapabilityBoundingSet = [ "" ];
90 RestrictAddressFamilies = "AF_INET AF_INET6";
91 DevicePolicy = "closed";
92 LockPersonality = true;
93 MemoryDenyWriteExecute = false;
94 NoNewPrivileges = true;
95 PrivateUsers = true;
96 PrivateTmp = true;
97 ProtectClock = true;
98 ProtectControlGroups = true;
99 ProtectHome = true;
100 ProtectHostname = true;
101 ProtectKernelLogs = true;
102 ProtectKernelModules = true;
103 ProtectKernalTunables = true;
104 ProtectProc = "invisible";
105 ProcSubset = "pid";
106 RemoveIPC = true;
107 RestrictNamespaces = true;
108 RestrictRealtime = true;
109 RestrictSUIDSGID = true;
110 SystemCallArchitectures = "native";
111 SystemCallFilter = [
112 "@system-service @pkey"
113 "~@privileged @resources"
114 "@chown"
115 ];
116 UMask = "0077";
117 };
118 };
119 };
120 meta.maintainers = with lib.maintainers; [ cdombroski ];
121}