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