summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorMartin Weinelt <mweinelt@users.noreply.github.com>2021-04-30 21:59:22 +0200
committerGitHub <noreply@github.com>2021-04-30 21:59:22 +0200
commitefb30a191e851d936ab47e3a82ab3a6e8b361f90 (patch)
treeceb7bb216c65860fe40077b1ab6b22ec1bfc9204 /nixos
parent9a597deb23d49cdc58a866b4d5218646187d5370 (diff)
parent62de527dc32563e65556669037f5ce81943091bf (diff)
downloadnixpkgs-efb30a191e851d936ab47e3a82ab3a6e8b361f90.tar
nixpkgs-efb30a191e851d936ab47e3a82ab3a6e8b361f90.tar.gz
nixpkgs-efb30a191e851d936ab47e3a82ab3a6e8b361f90.tar.bz2
nixpkgs-efb30a191e851d936ab47e3a82ab3a6e8b361f90.tar.lz
nixpkgs-efb30a191e851d936ab47e3a82ab3a6e8b361f90.tar.xz
nixpkgs-efb30a191e851d936ab47e3a82ab3a6e8b361f90.tar.zst
nixpkgs-efb30a191e851d936ab47e3a82ab3a6e8b361f90.zip
Merge pull request #120529 from mweinelt/zigbee2mqtt
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/release-notes/rl-2105.xml6
-rw-r--r--nixos/modules/services/misc/zigbee2mqtt.nix96
-rw-r--r--nixos/tests/zigbee2mqtt.nix6
3 files changed, 82 insertions, 26 deletions
diff --git a/nixos/doc/manual/release-notes/rl-2105.xml b/nixos/doc/manual/release-notes/rl-2105.xml
index 6e4a9e7114b..b45c19fa9af 100644
--- a/nixos/doc/manual/release-notes/rl-2105.xml
+++ b/nixos/doc/manual/release-notes/rl-2105.xml
@@ -692,6 +692,12 @@ environment.systemPackages = [
        <literal>skip-kernel-setup true</literal> and takes care of setting forwarding and rp_filter sysctls by itself as well
        as for each interface in <varname>services.babeld.interfaces</varname>.
      </para>
+    </listitem>
+   <listitem>
+     <para>
+      The <option>services.zigbee2mqtt.config</option> option has been renamed to <option>services.zigbee2mqtt.settings</option> and
+      now follows <link xlink:href="https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md">RFC 0042</link>.
+     </para>
    </listitem>
   </itemizedlist>
  </section>
diff --git a/nixos/modules/services/misc/zigbee2mqtt.nix b/nixos/modules/services/misc/zigbee2mqtt.nix
index cd987eb76c7..4458da1346b 100644
--- a/nixos/modules/services/misc/zigbee2mqtt.nix
+++ b/nixos/modules/services/misc/zigbee2mqtt.nix
@@ -5,29 +5,17 @@ with lib;
 let
   cfg = config.services.zigbee2mqtt;
 
-  configJSON = pkgs.writeText "configuration.json"
-    (builtins.toJSON (recursiveUpdate defaultConfig cfg.config));
-  configFile = pkgs.runCommand "configuration.yaml" { preferLocalBuild = true; } ''
-    ${pkgs.remarshal}/bin/json2yaml -i ${configJSON} -o $out
-  '';
+  format = pkgs.formats.yaml { };
+  configFile = format.generate "zigbee2mqtt.yaml" cfg.settings;
 
-  # the default config contains all required settings,
-  # so the service starts up without crashing.
-  defaultConfig = {
-    homeassistant = false;
-    permit_join = false;
-    mqtt = {
-      base_topic = "zigbee2mqtt";
-      server = "mqtt://localhost:1883";
-    };
-    serial.port = "/dev/ttyACM0";
-    # put device configuration into separate file because configuration.yaml
-    # is copied from the store on startup
-    devices = "devices.yaml";
-  };
 in
 {
-  meta.maintainers = with maintainers; [ sweber ];
+  meta.maintainers = with maintainers; [ sweber hexa ];
+
+  imports = [
+    # Remove warning before the 21.11 release
+    (mkRenamedOptionModule [ "services" "zigbee2mqtt" "config" ] [ "services" "zigbee2mqtt" "settings" ])
+  ];
 
   options.services.zigbee2mqtt = {
     enable = mkEnableOption "enable zigbee2mqtt service";
@@ -37,7 +25,11 @@ in
       default = pkgs.zigbee2mqtt.override {
         dataDir = cfg.dataDir;
       };
-      defaultText = "pkgs.zigbee2mqtt";
+      defaultText = literalExample ''
+        pkgs.zigbee2mqtt {
+          dataDir = services.zigbee2mqtt.dataDir
+        }
+      '';
       type = types.package;
     };
 
@@ -47,9 +39,9 @@ in
       type = types.path;
     };
 
-    config = mkOption {
+    settings = mkOption {
+      type = format.type;
       default = {};
-      type = with types; nullOr attrs;
       example = literalExample ''
         {
           homeassistant = config.services.home-assistant.enable;
@@ -61,11 +53,28 @@ in
       '';
       description = ''
         Your <filename>configuration.yaml</filename> as a Nix attribute set.
+        Check the <link xlink:href="https://www.zigbee2mqtt.io/information/configuration.html">documentation</link>
+        for possible options.
       '';
     };
   };
 
   config = mkIf (cfg.enable) {
+
+    # preset config values
+    services.zigbee2mqtt.settings = {
+      homeassistant = mkDefault config.services.home-assistant.enable;
+      permit_join = mkDefault false;
+      mqtt = {
+        base_topic = mkDefault "zigbee2mqtt";
+        server = mkDefault "mqtt://localhost:1883";
+      };
+      serial.port = mkDefault "/dev/ttyACM0";
+      # reference device configuration, that is kept in a separate file
+      # to prevent it being overwritten in the units ExecStartPre script
+      devices = mkDefault "devices.yaml";
+    };
+
     systemd.services.zigbee2mqtt = {
       description = "Zigbee2mqtt Service";
       wantedBy = [ "multi-user.target" ];
@@ -76,10 +85,48 @@ in
         User = "zigbee2mqtt";
         WorkingDirectory = cfg.dataDir;
         Restart = "on-failure";
+
+        # Hardening
+        CapabilityBoundingSet = "";
+        DeviceAllow = [
+          config.services.zigbee2mqtt.settings.serial.port
+        ];
+        DevicePolicy = "closed";
+        LockPersonality = true;
+        MemoryDenyWriteExecute = false;
+        NoNewPrivileges = true;
+        PrivateDevices = false; # prevents access to /dev/serial, because it is set 0700 root:root
+        PrivateUsers = true;
+        PrivateTmp = true;
+        ProtectClock = true;
+        ProtectControlGroups = true;
+        ProtectHome = true;
+        ProtectHostname = true;
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        ProtectProc = "invisible";
+        ProcSubset = "pid";
         ProtectSystem = "strict";
         ReadWritePaths = cfg.dataDir;
-        PrivateTmp = true;
         RemoveIPC = true;
+        RestrictAddressFamilies = [
+          "AF_INET"
+          "AF_INET6"
+        ];
+        RestrictNamespaces = true;
+        RestrictRealtime = true;
+        RestrictSUIDSGID = true;
+        SupplementaryGroups = [
+          "dialout"
+        ];
+        SystemCallArchitectures = "native";
+        SystemCallFilter = [
+          "@system-service"
+          "~@privileged"
+          "~@resources"
+        ];
+        UMask = "0077";
       };
       preStart = ''
         cp --no-preserve=mode ${configFile} "${cfg.dataDir}/configuration.yaml"
@@ -90,7 +137,6 @@ in
       home = cfg.dataDir;
       createHome = true;
       group = "zigbee2mqtt";
-      extraGroups = [ "dialout" ];
       uid = config.ids.uids.zigbee2mqtt;
     };
 
diff --git a/nixos/tests/zigbee2mqtt.nix b/nixos/tests/zigbee2mqtt.nix
index b7bb21f9227..98aadbb699b 100644
--- a/nixos/tests/zigbee2mqtt.nix
+++ b/nixos/tests/zigbee2mqtt.nix
@@ -1,4 +1,4 @@
-import ./make-test-python.nix ({ pkgs, ... }:
+import ./make-test-python.nix ({ pkgs, lib, ... }:
 
   {
     machine = { pkgs, ... }:
@@ -6,6 +6,8 @@ import ./make-test-python.nix ({ pkgs, ... }:
         services.zigbee2mqtt = {
           enable = true;
         };
+
+        systemd.services.zigbee2mqtt.serviceConfig.DevicePolicy = lib.mkForce "auto";
       };
 
     testScript = ''
@@ -14,6 +16,8 @@ import ./make-test-python.nix ({ pkgs, ... }:
       machine.succeed(
           "journalctl -eu zigbee2mqtt | grep \"Error: Error while opening serialport 'Error: Error: No such file or directory, cannot open /dev/ttyACM0'\""
       )
+
+      machine.log(machine.succeed("systemd-analyze security zigbee2mqtt.service"))
     '';
   }
 )