at 23.11-pre 4.1 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.zigbee2mqtt; 7 8 format = pkgs.formats.yaml { }; 9 configFile = format.generate "zigbee2mqtt.yaml" cfg.settings; 10 11in 12{ 13 meta.maintainers = with maintainers; [ sweber hexa ]; 14 15 imports = [ 16 # Remove warning before the 21.11 release 17 (mkRenamedOptionModule [ "services" "zigbee2mqtt" "config" ] [ "services" "zigbee2mqtt" "settings" ]) 18 ]; 19 20 options.services.zigbee2mqtt = { 21 enable = mkEnableOption (lib.mdDoc "zigbee2mqtt service"); 22 23 package = mkOption { 24 description = lib.mdDoc "Zigbee2mqtt package to use"; 25 default = pkgs.zigbee2mqtt; 26 defaultText = literalExpression '' 27 pkgs.zigbee2mqtt 28 ''; 29 type = types.package; 30 }; 31 32 dataDir = mkOption { 33 description = lib.mdDoc "Zigbee2mqtt data directory"; 34 default = "/var/lib/zigbee2mqtt"; 35 type = types.path; 36 }; 37 38 settings = mkOption { 39 type = format.type; 40 default = { }; 41 example = literalExpression '' 42 { 43 homeassistant = config.services.home-assistant.enable; 44 permit_join = true; 45 serial = { 46 port = "/dev/ttyACM1"; 47 }; 48 } 49 ''; 50 description = lib.mdDoc '' 51 Your {file}`configuration.yaml` as a Nix attribute set. 52 Check the [documentation](https://www.zigbee2mqtt.io/information/configuration.html) 53 for possible options. 54 ''; 55 }; 56 }; 57 58 config = mkIf (cfg.enable) { 59 60 # preset config values 61 services.zigbee2mqtt.settings = { 62 homeassistant = mkDefault config.services.home-assistant.enable; 63 permit_join = mkDefault false; 64 mqtt = { 65 base_topic = mkDefault "zigbee2mqtt"; 66 server = mkDefault "mqtt://localhost:1883"; 67 }; 68 serial.port = mkDefault "/dev/ttyACM0"; 69 # reference device configuration, that is kept in a separate file 70 # to prevent it being overwritten in the units ExecStartPre script 71 devices = mkDefault "devices.yaml"; 72 }; 73 74 systemd.services.zigbee2mqtt = { 75 description = "Zigbee2mqtt Service"; 76 wantedBy = [ "multi-user.target" ]; 77 after = [ "network.target" ]; 78 environment.ZIGBEE2MQTT_DATA = cfg.dataDir; 79 serviceConfig = { 80 ExecStart = "${cfg.package}/bin/zigbee2mqtt"; 81 User = "zigbee2mqtt"; 82 Group = "zigbee2mqtt"; 83 WorkingDirectory = cfg.dataDir; 84 Restart = "on-failure"; 85 86 # Hardening 87 CapabilityBoundingSet = ""; 88 DeviceAllow = [ 89 config.services.zigbee2mqtt.settings.serial.port 90 ]; 91 DevicePolicy = "closed"; 92 LockPersonality = true; 93 MemoryDenyWriteExecute = false; 94 NoNewPrivileges = true; 95 PrivateDevices = false; # prevents access to /dev/serial, because it is set 0700 root:root 96 PrivateUsers = true; 97 PrivateTmp = true; 98 ProtectClock = true; 99 ProtectControlGroups = true; 100 ProtectHome = true; 101 ProtectHostname = true; 102 ProtectKernelLogs = true; 103 ProtectKernelModules = true; 104 ProtectKernelTunables = true; 105 ProtectProc = "invisible"; 106 ProcSubset = "pid"; 107 ProtectSystem = "strict"; 108 ReadWritePaths = cfg.dataDir; 109 RemoveIPC = true; 110 RestrictAddressFamilies = [ 111 "AF_INET" 112 "AF_INET6" 113 ]; 114 RestrictNamespaces = true; 115 RestrictRealtime = true; 116 RestrictSUIDSGID = true; 117 SupplementaryGroups = [ 118 "dialout" 119 ]; 120 SystemCallArchitectures = "native"; 121 SystemCallFilter = [ 122 "@system-service @pkey" 123 "~@privileged @resources" 124 ]; 125 UMask = "0077"; 126 }; 127 preStart = '' 128 cp --no-preserve=mode ${configFile} "${cfg.dataDir}/configuration.yaml" 129 ''; 130 }; 131 132 users.users.zigbee2mqtt = { 133 home = cfg.dataDir; 134 createHome = true; 135 group = "zigbee2mqtt"; 136 uid = config.ids.uids.zigbee2mqtt; 137 }; 138 139 users.groups.zigbee2mqtt.gid = config.ids.gids.zigbee2mqtt; 140 }; 141}