···4545 else args';
46464747 # TODO: deprecate args.rustc in favour of args.rust after 23.05 is EOL.
4848- rust = assert !(args ? rust && args ? rustc); args.rust or args.rustc or {};
4848+ rust = args.rust or args.rustc or {};
49495050 final = {
5151 # Prefer to parse `config` as it is strictly more informative.
···168168169169 # TODO: remove after 23.05 is EOL, with an error pointing to the rust.* attrs.
170170 rustc = args.rustc or {};
171171-172172- rust = rust // {
173173- # Once args.rustc.platform.target-family is deprecated and
174174- # removed, there will no longer be any need to modify any
175175- # values from args.rust.platform, so we can drop all the
176176- # "args ? rust" etc. checks, and merge args.rust.platform in
177177- # /after/.
178178- platform = rust.platform or {} // {
179179- # https://doc.rust-lang.org/reference/conditional-compilation.html#target_arch
180180- arch =
181181- /**/ if rust ? platform then rust.platform.arch
182182- else if final.isAarch32 then "arm"
183183- else if final.isMips64 then "mips64" # never add "el" suffix
184184- else if final.isPower64 then "powerpc64" # never add "le" suffix
185185- else final.parsed.cpu.name;
186186-187187- # https://doc.rust-lang.org/reference/conditional-compilation.html#target_os
188188- os =
189189- /**/ if rust ? platform then rust.platform.os or "none"
190190- else if final.isDarwin then "macos"
191191- else final.parsed.kernel.name;
192192-193193- # https://doc.rust-lang.org/reference/conditional-compilation.html#target_family
194194- target-family =
195195- /**/ if args ? rust.platform.target-family then args.rust.platform.target-family
196196- else if args ? rustc.platform.target-family
197197- then
198198- (
199199- # Since https://github.com/rust-lang/rust/pull/84072
200200- # `target-family` is a list instead of single value.
201201- let
202202- f = args.rustc.platform.target-family;
203203- in
204204- if builtins.isList f then f else [ f ]
205205- )
206206- else lib.optional final.isUnix "unix"
207207- ++ lib.optional final.isWindows "windows";
208208-209209- # https://doc.rust-lang.org/reference/conditional-compilation.html#target_vendor
210210- vendor = let
211211- inherit (final.parsed) vendor;
212212- in rust.platform.vendor or {
213213- "w64" = "pc";
214214- }.${vendor.name} or vendor.name;
215215- };
216216-217217- # The name of the rust target, even if it is custom. Adjustments are
218218- # because rust has slightly different naming conventions than we do.
219219- rustcTarget = let
220220- inherit (final.parsed) cpu kernel abi;
221221- cpu_ = rust.platform.arch or {
222222- "armv7a" = "armv7";
223223- "armv7l" = "armv7";
224224- "armv6l" = "arm";
225225- "armv5tel" = "armv5te";
226226- "riscv64" = "riscv64gc";
227227- }.${cpu.name} or cpu.name;
228228- vendor_ = final.rust.platform.vendor;
229229- in rust.config
230230- or "${cpu_}-${vendor_}-${kernel.name}${lib.optionalString (abi.name != "unknown") "-${abi.name}"}";
231231-232232- # The name of the rust target if it is standard, or the json file
233233- # containing the custom target spec.
234234- rustcTargetSpec =
235235- /**/ if rust ? platform
236236- then builtins.toFile (final.rust.rustcTarget + ".json") (builtins.toJSON rust.platform)
237237- else final.rust.rustcTarget;
238238-239239- # The name of the rust target if it is standard, or the
240240- # basename of the file containing the custom target spec,
241241- # without the .json extension.
242242- #
243243- # This is the name used by Cargo for target subdirectories.
244244- cargoShortTarget =
245245- lib.removeSuffix ".json" (baseNameOf "${final.rust.rustcTargetSpec}");
246246-247247- # When used as part of an environment variable name, triples are
248248- # uppercased and have all hyphens replaced by underscores:
249249- #
250250- # https://github.com/rust-lang/cargo/pull/9169
251251- # https://github.com/rust-lang/cargo/issues/8285#issuecomment-634202431
252252- cargoEnvVarTarget =
253253- lib.strings.replaceStrings ["-"] ["_"]
254254- (lib.strings.toUpper final.rust.cargoShortTarget);
255255-256256- # True if the target is no_std
257257- # https://github.com/rust-lang/rust/blob/2e44c17c12cec45b6a682b1e53a04ac5b5fcc9d2/src/bootstrap/config.rs#L415-L421
258258- isNoStdTarget =
259259- builtins.any (t: lib.hasInfix t final.rust.rustcTarget) ["-none" "nvptx" "switch" "-uefi"];
260260- };
261171262172 linuxArch =
263173 if final.isAarch32 then "arm"
···356266357267 }) // mapAttrs (n: v: v final.parsed) inspect.predicates
358268 // mapAttrs (n: v: v final.gcc.arch or "default") architectures.predicates
359359- // args;
269269+ // args // {
270270+ rust = rust // {
271271+ # Once args.rustc.platform.target-family is deprecated and
272272+ # removed, there will no longer be any need to modify any
273273+ # values from args.rust.platform, so we can drop all the
274274+ # "args ? rust" etc. checks, and merge args.rust.platform in
275275+ # /after/.
276276+ platform = rust.platform or {} // {
277277+ # https://doc.rust-lang.org/reference/conditional-compilation.html#target_arch
278278+ arch =
279279+ /**/ if rust ? platform then rust.platform.arch
280280+ else if final.isAarch32 then "arm"
281281+ else if final.isMips64 then "mips64" # never add "el" suffix
282282+ else if final.isPower64 then "powerpc64" # never add "le" suffix
283283+ else final.parsed.cpu.name;
284284+285285+ # https://doc.rust-lang.org/reference/conditional-compilation.html#target_os
286286+ os =
287287+ /**/ if rust ? platform then rust.platform.os or "none"
288288+ else if final.isDarwin then "macos"
289289+ else final.parsed.kernel.name;
290290+291291+ # https://doc.rust-lang.org/reference/conditional-compilation.html#target_family
292292+ target-family =
293293+ /**/ if args ? rust.platform.target-family then args.rust.platform.target-family
294294+ else if args ? rustc.platform.target-family
295295+ then
296296+ (
297297+ # Since https://github.com/rust-lang/rust/pull/84072
298298+ # `target-family` is a list instead of single value.
299299+ let
300300+ f = args.rustc.platform.target-family;
301301+ in
302302+ if builtins.isList f then f else [ f ]
303303+ )
304304+ else lib.optional final.isUnix "unix"
305305+ ++ lib.optional final.isWindows "windows";
306306+307307+ # https://doc.rust-lang.org/reference/conditional-compilation.html#target_vendor
308308+ vendor = let
309309+ inherit (final.parsed) vendor;
310310+ in rust.platform.vendor or {
311311+ "w64" = "pc";
312312+ }.${vendor.name} or vendor.name;
313313+ };
314314+315315+ # The name of the rust target, even if it is custom. Adjustments are
316316+ # because rust has slightly different naming conventions than we do.
317317+ rustcTarget = let
318318+ inherit (final.parsed) cpu kernel abi;
319319+ cpu_ = rust.platform.arch or {
320320+ "armv7a" = "armv7";
321321+ "armv7l" = "armv7";
322322+ "armv6l" = "arm";
323323+ "armv5tel" = "armv5te";
324324+ "riscv64" = "riscv64gc";
325325+ }.${cpu.name} or cpu.name;
326326+ vendor_ = final.rust.platform.vendor;
327327+ in rust.config
328328+ or "${cpu_}-${vendor_}-${kernel.name}${lib.optionalString (abi.name != "unknown") "-${abi.name}"}";
329329+330330+ # The name of the rust target if it is standard, or the json file
331331+ # containing the custom target spec.
332332+ rustcTargetSpec = rust.rustcTargetSpec or (
333333+ /**/ if rust ? platform
334334+ then builtins.toFile (final.rust.rustcTarget + ".json") (builtins.toJSON rust.platform)
335335+ else final.rust.rustcTarget);
336336+337337+ # The name of the rust target if it is standard, or the
338338+ # basename of the file containing the custom target spec,
339339+ # without the .json extension.
340340+ #
341341+ # This is the name used by Cargo for target subdirectories.
342342+ cargoShortTarget =
343343+ lib.removeSuffix ".json" (baseNameOf "${final.rust.rustcTargetSpec}");
344344+345345+ # When used as part of an environment variable name, triples are
346346+ # uppercased and have all hyphens replaced by underscores:
347347+ #
348348+ # https://github.com/rust-lang/cargo/pull/9169
349349+ # https://github.com/rust-lang/cargo/issues/8285#issuecomment-634202431
350350+ cargoEnvVarTarget =
351351+ lib.strings.replaceStrings ["-"] ["_"]
352352+ (lib.strings.toUpper final.rust.cargoShortTarget);
353353+354354+ # True if the target is no_std
355355+ # https://github.com/rust-lang/rust/blob/2e44c17c12cec45b6a682b1e53a04ac5b5fcc9d2/src/bootstrap/config.rs#L415-L421
356356+ isNoStdTarget =
357357+ builtins.any (t: lib.hasInfix t final.rust.rustcTarget) ["-none" "nvptx" "switch" "-uefi"];
358358+ };
359359+ };
360360 in assert final.useAndroidPrebuilt -> final.isAndroid;
361361 assert lib.foldl
362362 (pass: { assertion, message }:
···316316317317- The binary of the package `cloud-sql-proxy` has changed from `cloud_sql_proxy` to `cloud-sql-proxy`.
318318319319+- The module `services.apache-kafka` was largely rewritten and has certain breaking changes. To be precise, this means that the following things have changed:
320320+321321+ - Most settings have been migrated to [services.apache-kafka.settings](#opt-services.apache-kafka.settings).
322322+ - Care must be taken when adapting an existing cluster to these changes, see [](#module-services-apache-kafka-migrating-to-settings).
323323+ - By virtue of being less opinionated, it is now possible to use the module to run Apache Kafka in KRaft mode instead of Zookeeper mode.
324324+ - [A few options](#module-services-apache-kafka-kraft) have been added to assist in this mode.
325325+319326- Garage has been upgraded to 0.9.x. `services.garage.package` now needs to be explicitly set, so version upgrades can be done in a controlled fashion. For this, we expose `garage_x_y` attributes which can be set here.
320327321328- `voms` and `xrootd` now moves the `$out/etc` content to the `$etc` output instead of `$out/etc.orig`, when input argument `externalEtc` is not `null`.
322329323330- The `woodpecker-*` CI packages have been updated to 1.0.0. This release is wildly incompatible with the 0.15.X versions that were previously packaged. Please read [upstream's documentation](https://woodpecker-ci.org/docs/next/migrations#100) to learn how to update your CI configurations.
331331+332332+- Meilisearch was updated from 1.3.1 to 1.5.0. The update has breaking changes about backslashes and filtering. See the [release announcement](https://blog.meilisearch.com/v1-4-release/) for more information.
324333325334- The Caddy module gained a new option named `services.caddy.enableReload` which is enabled by default. It allows reloading the service instead of restarting it, if only a config file has changed. This option must be disabled if you have turned off the [Caddy admin API](https://caddyserver.com/docs/caddyfile/options#admin). If you keep this option enabled, you should consider setting [`grace_period`](https://caddyserver.com/docs/caddyfile/options#grace-period) to a non-infinite value to prevent Caddy from delaying the reload indefinitely.
326335
···88 imports =
99 [
1010 # Include the default lxd configuration.
1111- "${modulesPath}/modules/virtualisation/lxc-container.nix"
1111+ "${modulesPath}/virtualisation/lxc-container.nix"
1212 # Include the container-specific autogenerated configuration.
1313 ./lxd.nix
1414 ];
+130-58
nixos/modules/services/misc/apache-kafka.nix
···55let
66 cfg = config.services.apache-kafka;
7788- serverProperties =
99- if cfg.serverProperties != null then
1010- cfg.serverProperties
1111- else
1212- ''
1313- # Generated by nixos
1414- broker.id=${toString cfg.brokerId}
1515- port=${toString cfg.port}
1616- host.name=${cfg.hostname}
1717- log.dirs=${concatStringsSep "," cfg.logDirs}
1818- zookeeper.connect=${cfg.zookeeper}
1919- ${toString cfg.extraProperties}
2020- '';
88+ # The `javaProperties` generator takes care of various escaping rules and
99+ # generation of the properties file, but we'll handle stringly conversion
1010+ # ourselves in mkPropertySettings and stringlySettings, since we know more
1111+ # about the specifically allowed format eg. for lists of this type, and we
1212+ # don't want to coerce-downsample values to str too early by having the
1313+ # coercedTypes from javaProperties directly in our NixOS option types.
1414+ #
1515+ # Make sure every `freeformType` and any specific option type in `settings` is
1616+ # supported here.
1717+1818+ mkPropertyString = let
1919+ render = {
2020+ bool = boolToString;
2121+ int = toString;
2222+ list = concatMapStringsSep "," mkPropertyString;
2323+ string = id;
2424+ };
2525+ in
2626+ v: render.${builtins.typeOf v} v;
21272222- serverConfig = pkgs.writeText "server.properties" serverProperties;
2323- logConfig = pkgs.writeText "log4j.properties" cfg.log4jProperties;
2828+ stringlySettings = mapAttrs (_: mkPropertyString)
2929+ (filterAttrs (_: v: v != null) cfg.settings);
24303131+ generator = (pkgs.formats.javaProperties {}).generate;
2532in {
26332734 options.services.apache-kafka = {
2828- enable = mkOption {
2929- description = lib.mdDoc "Whether to enable Apache Kafka.";
3030- default = false;
3131- type = types.bool;
3232- };
3535+ enable = mkEnableOption (lib.mdDoc "Apache Kafka event streaming broker");
33363434- brokerId = mkOption {
3535- description = lib.mdDoc "Broker ID.";
3636- default = -1;
3737- type = types.int;
3838- };
3737+ settings = mkOption {
3838+ description = lib.mdDoc ''
3939+ [Kafka broker configuration](https://kafka.apache.org/documentation.html#brokerconfigs)
4040+ {file}`server.properties`.
4141+4242+ Note that .properties files contain mappings from string to string.
4343+ Keys with dots are NOT represented by nested attrs in these settings,
4444+ but instead as quoted strings (ie. `settings."broker.id"`, NOT
4545+ `settings.broker.id`).
4646+ '';
4747+ type = types.submodule {
4848+ freeformType = with types; let
4949+ primitive = oneOf [bool int str];
5050+ in lazyAttrsOf (nullOr (either primitive (listOf primitive)));
5151+5252+ options = {
5353+ "broker.id" = mkOption {
5454+ description = lib.mdDoc "Broker ID. -1 or null to auto-allocate in zookeeper mode.";
5555+ default = null;
5656+ type = with types; nullOr int;
5757+ };
5858+5959+ "log.dirs" = mkOption {
6060+ description = lib.mdDoc "Log file directories.";
6161+ # Deliberaly leave out old default and use the rewrite opportunity
6262+ # to have users choose a safer value -- /tmp might be volatile and is a
6363+ # slightly scary default choice.
6464+ # default = [ "/tmp/apache-kafka" ];
6565+ type = with types; listOf path;
6666+ };
39674040- port = mkOption {
4141- description = lib.mdDoc "Port number the broker should listen on.";
4242- default = 9092;
4343- type = types.port;
6868+ "listeners" = mkOption {
6969+ description = lib.mdDoc ''
7070+ Kafka Listener List.
7171+ See [listeners](https://kafka.apache.org/documentation/#brokerconfigs_listeners).
7272+ '';
7373+ type = types.listOf types.str;
7474+ default = [ "PLAINTEXT://localhost:9092" ];
7575+ };
7676+ };
7777+ };
4478 };
45794646- hostname = mkOption {
4747- description = lib.mdDoc "Hostname the broker should bind to.";
4848- default = "localhost";
4949- type = types.str;
8080+ clusterId = mkOption {
8181+ description = lib.mdDoc ''
8282+ KRaft mode ClusterId used for formatting log directories. Can be generated with `kafka-storage.sh random-uuid`
8383+ '';
8484+ type = with types; nullOr str;
8585+ default = null;
5086 };
51875252- logDirs = mkOption {
5353- description = lib.mdDoc "Log file directories";
5454- default = [ "/tmp/kafka-logs" ];
5555- type = types.listOf types.path;
8888+ configFiles.serverProperties = mkOption {
8989+ description = lib.mdDoc ''
9090+ Kafka server.properties configuration file path.
9191+ Defaults to the rendered `settings`.
9292+ '';
9393+ type = types.path;
5694 };
57955858- zookeeper = mkOption {
5959- description = lib.mdDoc "Zookeeper connection string";
6060- default = "localhost:2181";
6161- type = types.str;
9696+ configFiles.log4jProperties = mkOption {
9797+ description = lib.mdDoc "Kafka log4j property configuration file path";
9898+ type = types.path;
9999+ default = pkgs.writeText "log4j.properties" cfg.log4jProperties;
100100+ defaultText = ''pkgs.writeText "log4j.properties" cfg.log4jProperties'';
62101 };
631026464- extraProperties = mkOption {
6565- description = lib.mdDoc "Extra properties for server.properties.";
6666- type = types.nullOr types.lines;
6767- default = null;
103103+ formatLogDirs = mkOption {
104104+ description = lib.mdDoc ''
105105+ Whether to format log dirs in KRaft mode if all log dirs are
106106+ unformatted, ie. they contain no meta.properties.
107107+ '';
108108+ type = types.bool;
109109+ default = false;
68110 };
691117070- serverProperties = mkOption {
112112+ formatLogDirsIgnoreFormatted = mkOption {
71113 description = lib.mdDoc ''
7272- Complete server.properties content. Other server.properties config
7373- options will be ignored if this option is used.
114114+ Whether to ignore already formatted log dirs when formatting log dirs,
115115+ instead of failing. Useful when replacing or adding disks.
74116 '';
7575- type = types.nullOr types.lines;
7676- default = null;
117117+ type = types.bool;
118118+ default = false;
77119 };
7812079121 log4jProperties = mkOption {
···112154 defaultText = literalExpression "pkgs.apacheKafka.passthru.jre";
113155 type = types.package;
114156 };
157157+ };
158158+159159+ imports = [
160160+ (mkRenamedOptionModule
161161+ [ "services" "apache-kafka" "brokerId" ]
162162+ [ "services" "apache-kafka" "settings" ''broker.id'' ])
163163+ (mkRenamedOptionModule
164164+ [ "services" "apache-kafka" "logDirs" ]
165165+ [ "services" "apache-kafka" "settings" ''log.dirs'' ])
166166+ (mkRenamedOptionModule
167167+ [ "services" "apache-kafka" "zookeeper" ]
168168+ [ "services" "apache-kafka" "settings" ''zookeeper.connect'' ])
115169116116- };
170170+ (mkRemovedOptionModule [ "services" "apache-kafka" "port" ]
171171+ "Please see services.apache-kafka.settings.listeners and its documentation instead")
172172+ (mkRemovedOptionModule [ "services" "apache-kafka" "hostname" ]
173173+ "Please see services.apache-kafka.settings.listeners and its documentation instead")
174174+ (mkRemovedOptionModule [ "services" "apache-kafka" "extraProperties" ]
175175+ "Please see services.apache-kafka.settings and its documentation instead")
176176+ (mkRemovedOptionModule [ "services" "apache-kafka" "serverProperties" ]
177177+ "Please see services.apache-kafka.settings and its documentation instead")
178178+ ];
117179118180 config = mkIf cfg.enable {
119119-120120- environment.systemPackages = [cfg.package];
181181+ services.apache-kafka.configFiles.serverProperties = generator "server.properties" stringlySettings;
121182122183 users.users.apache-kafka = {
123184 isSystemUser = true;
124185 group = "apache-kafka";
125186 description = "Apache Kafka daemon user";
126126- home = head cfg.logDirs;
127187 };
128188 users.groups.apache-kafka = {};
129189130130- systemd.tmpfiles.rules = map (logDir: "d '${logDir}' 0700 apache-kafka - - -") cfg.logDirs;
190190+ systemd.tmpfiles.rules = map (logDir: "d '${logDir}' 0700 apache-kafka - - -") cfg.settings."log.dirs";
131191132192 systemd.services.apache-kafka = {
133193 description = "Apache Kafka Daemon";
134194 wantedBy = [ "multi-user.target" ];
135195 after = [ "network.target" ];
196196+ preStart = mkIf cfg.formatLogDirs
197197+ (if cfg.formatLogDirsIgnoreFormatted then ''
198198+ ${cfg.package}/bin/kafka-storage.sh format -t "${cfg.clusterId}" -c ${cfg.configFiles.serverProperties} --ignore-formatted
199199+ '' else ''
200200+ if ${concatMapStringsSep " && " (l: ''[ ! -f "${l}/meta.properties" ]'') cfg.settings."log.dirs"}; then
201201+ ${cfg.package}/bin/kafka-storage.sh format -t "${cfg.clusterId}" -c ${cfg.configFiles.serverProperties}
202202+ fi
203203+ '');
136204 serviceConfig = {
137205 ExecStart = ''
138206 ${cfg.jre}/bin/java \
139207 -cp "${cfg.package}/libs/*" \
140140- -Dlog4j.configuration=file:${logConfig} \
208208+ -Dlog4j.configuration=file:${cfg.configFiles.log4jProperties} \
141209 ${toString cfg.jvmOptions} \
142210 kafka.Kafka \
143143- ${serverConfig}
211211+ ${cfg.configFiles.serverProperties}
144212 '';
145213 User = "apache-kafka";
146214 SuccessExitStatus = "0 143";
147215 };
148216 };
217217+ };
149218150150- };
219219+ meta.doc = ./kafka.md;
220220+ meta.maintainers = with lib.maintainers; [
221221+ srhb
222222+ ];
151223}
+63
nixos/modules/services/misc/kafka.md
···11+# Apache Kafka {#module-services-apache-kafka}
22+33+[Apache Kafka](https://kafka.apache.org/) is an open-source distributed event
44+streaming platform
55+66+## Basic Usage {#module-services-apache-kafka-basic-usage}
77+88+The Apache Kafka service is configured almost exclusively through its
99+[settings](#opt-services.apache-kafka.settings) option, with each attribute
1010+corresponding to the [upstream configuration
1111+manual](https://kafka.apache.org/documentation/#configuration) broker settings.
1212+1313+## KRaft {#module-services-apache-kafka-kraft}
1414+1515+Unlike in Zookeeper mode, Kafka in
1616+[KRaft](https://kafka.apache.org/documentation/#kraft) mode requires each log
1717+dir to be "formatted" (which means a cluster-specific a metadata file must
1818+exist in each log dir)
1919+2020+The upstream intention is for users to execute the [storage
2121+tool](https://kafka.apache.org/documentation/#kraft_storage) to achieve this,
2222+but this module contains a few extra options to automate this:
2323+2424+- [](#opt-services.apache-kafka.clusterId)
2525+- [](#opt-services.apache-kafka.formatLogDirs)
2626+- [](#opt-services.apache-kafka.formatLogDirsIgnoreFormatted)
2727+2828+## Migrating to settings {#module-services-apache-kafka-migrating-to-settings}
2929+3030+Migrating a cluster to the new `settings`-based changes requires adapting removed options to the corresponding upstream settings.
3131+3232+This means that the upstream [Broker Configs documentation](https://kafka.apache.org/documentation/#brokerconfigs) should be followed closely.
3333+3434+Note that dotted options in the upstream docs do _not_ correspond to nested Nix attrsets, but instead as quoted top level `settings` attributes, as in `services.apache-kafka.settings."broker.id"`, *NOT* `services.apache-kafka.settings.broker.id`.
3535+3636+Care should be taken, especially when migrating clusters from the old module, to ensure that the same intended configuration is reproduced faithfully via `settings`.
3737+3838+To assist in the comparison, the final config can be inspected by building the config file itself, ie. with: `nix-build <nixpkgs/nixos> -A config.services.apache-kafka.configFiles.serverProperties`.
3939+4040+Notable changes to be aware of include:
4141+4242+- Removal of `services.apache-kafka.extraProperties` and `services.apache-kafka.serverProperties`
4343+ - Translate using arbitrary properties using [](#opt-services.apache-kafka.settings)
4444+ - [Upstream docs](https://kafka.apache.org/documentation.html#brokerconfigs)
4545+ - The intention is for all broker properties to be fully representable via [](#opt-services.apache-kafka.settings).
4646+ - If this is not the case, please do consider raising an issue.
4747+ - Until it can be remedied, you *can* bail out by using [](#opt-services.apache-kafka.configFiles.serverProperties) to the path of a fully rendered properties file.
4848+4949+- Removal of `services.apache-kafka.hostname` and `services.apache-kafka.port`
5050+ - Translate using: `services.apache-kafka.settings.listeners`
5151+ - [Upstream docs](https://kafka.apache.org/documentation.html#brokerconfigs_listeners)
5252+5353+- Removal of `services.apache-kafka.logDirs`
5454+ - Translate using: `services.apache-kafka.settings."log.dirs"`
5555+ - [Upstream docs](https://kafka.apache.org/documentation.html#brokerconfigs_log.dirs)
5656+5757+- Removal of `services.apache-kafka.brokerId`
5858+ - Translate using: `services.apache-kafka.settings."broker.id"`
5959+ - [Upstream docs](https://kafka.apache.org/documentation.html#brokerconfigs_broker.id)
6060+6161+- Removal of `services.apache-kafka.zookeeper`
6262+ - Translate using: `services.apache-kafka.settings."zookeeper.connect"`
6363+ - [Upstream docs](https://kafka.apache.org/documentation.html#brokerconfigs_zookeeper.connect)
···6666 deprecatedNativeMessagingHost = option: pkg:
6767 if (cfg.${option} or false)
6868 then
6969- lib.warn "The cfg.${option} argument for `firefox.override` is deprecated, please add `pkgs.${pkg.pname}` to `nativeMessagingHosts` instead"
6969+ lib.warn "The cfg.${option} argument for `firefox.override` is deprecated, please add `pkgs.${pkg.pname}` to `nativeMessagingHosts.packages` instead"
7070 [pkg]
7171 else [];
7272