zoekt: 3.7.2-2-unstable-2024-10-24 -> 3.7.2-2-unstable-2024-12-09 (#363818)
[NixPkgs.git] / nixos / modules / services / home-automation / ebusd.nix
bloba0bff26e2ae3a2a5c9a6067661389d7fff181cb8
2   config,
3   lib,
4   pkgs,
5   ...
6 }:
7 let
8   cfg = config.services.ebusd;
9 in
11   meta.maintainers = with lib.maintainers; [ nathan-gs ];
13   options.services.ebusd = {
14     enable = lib.mkEnableOption "ebusd, a daemon for communication with eBUS heating systems";
16     package = lib.mkPackageOption pkgs "ebusd" { };
18     device = lib.mkOption {
19       type = lib.types.str;
20       default = "";
21       example = "IP:PORT";
22       description = ''
23         Use DEV as eBUS device [/dev/ttyUSB0].
24         This can be either:
25           enh:DEVICE or enh:IP:PORT for enhanced device (only adapter v3 and newer),
26           ens:DEVICE for enhanced high speed serial device (only adapter v3 and newer with firmware since 20220731),
27           DEVICE for serial device (normal speed, for all other serial adapters like adapter v2 as well as adapter v3 in non-enhanced mode), or
28           [udp:]IP:PORT for network device.
30         Source: <https://github.com/john30/ebusd/wiki/2.-Run#device-options>
31       '';
32     };
34     port = lib.mkOption {
35       default = 8888;
36       type = lib.types.port;
37       description = ''
38         The port on which to listen on
39       '';
40     };
42     readonly = lib.mkOption {
43       type = lib.types.bool;
44       default = false;
45       description = ''
46         Only read from device, never write to it
47       '';
48     };
50     configpath = lib.mkOption {
51       type = lib.types.str;
52       default = "https://cfg.ebusd.eu/";
53       description = ''
54         Directory to read CSV config files from. This can be a local folder or a URL.
55       '';
56     };
58     scanconfig = lib.mkOption {
59       type = lib.types.str;
60       default = "full";
61       description = ''
62         Pick CSV config files matching initial scan ("none" or empty for no initial scan message, "full" for full scan, or a single hex address to scan, default is to send a broadcast ident message).
63         If combined with --checkconfig, you can add scan message data as arguments for checking a particular scan configuration, e.g. "FF08070400/0AB5454850303003277201". For further details on this option,
64         see [Automatic configuration](https://github.com/john30/ebusd/wiki/4.7.-Automatic-configuration).
65       '';
66     };
68     logs =
69       let
70         # "all" must come first so it can be overridden by more specific areas
71         areas = [
72           "all"
73           "main"
74           "network"
75           "bus"
76           "update"
77           "other"
78         ];
79         levels = [
80           "none"
81           "error"
82           "notice"
83           "info"
84           "debug"
85         ];
86       in
87       lib.listToAttrs (
88         map (
89           area:
90           lib.nameValuePair area (
91             lib.mkOption {
92               type = lib.types.enum levels;
93               default = "notice";
94               example = "debug";
95               description = ''
96                 Only write log for matching `AREA`s (${lib.concatStringsSep "|" areas}) below or equal to `LEVEL` (${lib.concatStringsSep "|" levels})
97               '';
98             }
99           )
100         ) areas
101       );
103     mqtt = {
104       enable = lib.mkEnableOption "support for MQTT";
106       host = lib.mkOption {
107         type = lib.types.str;
108         default = "localhost";
109         description = ''
110           Connect to MQTT broker on HOST.
111         '';
112       };
114       port = lib.mkOption {
115         default = 1883;
116         type = lib.types.port;
117         description = ''
118           The port on which to connect to MQTT
119         '';
120       };
122       home-assistant = lib.mkOption {
123         type = lib.types.bool;
124         default = false;
125         description = ''
126           Adds the Home Assistant topics to MQTT, read more at [MQTT Integration](https://github.com/john30/ebusd/wiki/MQTT-integration)
127         '';
128       };
130       retain = lib.mkEnableOption "set the retain flag on all topics instead of only selected global ones";
132       user = lib.mkOption {
133         type = lib.types.str;
134         description = ''
135           The MQTT user to use
136         '';
137       };
139       password = lib.mkOption {
140         type = lib.types.str;
141         description = ''
142           The MQTT password.
143         '';
144       };
145     };
147     extraArguments = lib.mkOption {
148       type = lib.types.listOf lib.types.str;
149       default = [ ];
150       description = ''
151         Extra arguments to the ebus daemon
152       '';
153     };
154   };
156   config =
157     let
158       usesDev = lib.any (prefix: lib.hasPrefix prefix cfg.device) [
159         "/"
160         "ens:/"
161         "enh:/"
162       ];
163     in
164     lib.mkIf cfg.enable {
165       systemd.services.ebusd = {
166         description = "EBUSd Service";
167         wantedBy = [ "multi-user.target" ];
168         after = [ "network.target" ];
169         serviceConfig = {
170           ExecStart =
171             let
172               args = lib.cli.toGNUCommandLineShell { optionValueSeparator = "="; } (
173                 lib.foldr (a: b: a // b) { } [
174                   {
175                     inherit (cfg)
176                       device
177                       port
178                       configpath
179                       scanconfig
180                       readonly
181                       ;
182                     foreground = true;
183                     updatecheck = "off";
184                     log = lib.mapAttrsToList (name: value: "${name}:${value}") cfg.logs;
185                     mqttretain = cfg.mqtt.retain;
186                   }
187                   (lib.optionalAttrs cfg.mqtt.enable {
188                     mqtthost = cfg.mqtt.host;
189                     mqttport = cfg.mqtt.port;
190                     mqttuser = cfg.mqtt.user;
191                     mqttpass = cfg.mqtt.password;
192                   })
193                   (lib.optionalAttrs cfg.mqtt.home-assistant {
194                     mqttint = "${cfg.package}/etc/ebusd/mqtt-hassio.cfg";
195                     mqttjson = true;
196                   })
197                 ]
198               );
199             in
200             "${cfg.package}/bin/ebusd ${args} ${lib.escapeShellArgs cfg.extraArguments}";
202           DynamicUser = true;
203           Restart = "on-failure";
205           # Hardening
206           CapabilityBoundingSet = "";
207           DeviceAllow = lib.optionals usesDev [
208             (lib.removePrefix "ens:" (lib.removePrefix "enh:" cfg.device))
209           ];
210           DevicePolicy = "closed";
211           LockPersonality = true;
212           MemoryDenyWriteExecute = false;
213           NoNewPrivileges = true;
214           PrivateDevices = !usesDev;
215           PrivateUsers = true;
216           PrivateTmp = true;
217           ProtectClock = true;
218           ProtectControlGroups = true;
219           ProtectHome = true;
220           ProtectHostname = true;
221           ProtectKernelLogs = true;
222           ProtectKernelModules = true;
223           ProtectKernelTunables = true;
224           ProtectProc = "invisible";
225           ProcSubset = "pid";
226           ProtectSystem = "strict";
227           RemoveIPC = true;
228           RestrictAddressFamilies = [
229             "AF_INET"
230             "AF_INET6"
231           ];
232           RestrictNamespaces = true;
233           RestrictRealtime = true;
234           RestrictSUIDSGID = true;
235           SupplementaryGroups = [ "dialout" ];
236           SystemCallArchitectures = "native";
237           SystemCallFilter = [
238             "@system-service @pkey"
239             "~@privileged @resources"
240           ];
241           UMask = "0077";
242         };
243       };
244     };