···538538 When adding yourself as maintainer, in the same pull request, make a separate
539539 commit with the message `maintainers: add <handle>`.
540540 Add the commit before those making changes to the package or module.
541541- See [Nixpkgs Maintainers](../maintainers/README.md) for details.
541541+ See [Nixpkgs Maintainers](./maintainers/README.md) for details.
542542543543### Writing good commit messages
544544
+1
doc/README.md
···33This directory houses the sources files for the Nixpkgs manual.
4455You can find the [rendered documentation for Nixpkgs `unstable` on nixos.org](https://nixos.org/manual/nixpkgs/unstable/).
66+The rendering tool is [nixos-render-docs](../pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs), sometimes abbreviated `nrd`.
6778[Docs for Nixpkgs stable](https://nixos.org/manual/nixpkgs/stable/) are also available.
89
+2-2
lib/fileset/internal.nix
···172172 else if ! isPath value then
173173 if isStringLike value then
174174 throw ''
175175- ${context} ("${toString value}") is a string-like value, but it should be a path instead.
175175+ ${context} ("${toString value}") is a string-like value, but it should be a file set or a path instead.
176176 Paths represented as strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.''
177177 else
178178 throw ''
179179- ${context} is of type ${typeOf value}, but it should be a path instead.''
179179+ ${context} is of type ${typeOf value}, but it should be a file set or a path instead.''
180180 else if ! pathExists value then
181181 throw ''
182182 ${context} (${toString value}) does not exist.''
+2-2
lib/fileset/tests.sh
···355355rm -rf *
356356357357# Path coercion only works for paths
358358-expectFailure 'toSource { root = ./.; fileset = 10; }' 'lib.fileset.toSource: `fileset` is of type int, but it should be a path instead.'
359359-expectFailure 'toSource { root = ./.; fileset = "/some/path"; }' 'lib.fileset.toSource: `fileset` \("/some/path"\) is a string-like value, but it should be a path instead.
358358+expectFailure 'toSource { root = ./.; fileset = 10; }' 'lib.fileset.toSource: `fileset` is of type int, but it should be a file set or a path instead.'
359359+expectFailure 'toSource { root = ./.; fileset = "/some/path"; }' 'lib.fileset.toSource: `fileset` \("/some/path"\) is a string-like value, but it should be a file set or a path instead.
360360\s*Paths represented as strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'
361361362362# Path coercion errors for non-existent paths
+64-26
lib/options.nix
···109109110110 The package is specified in the third argument under `default` as a list of strings
111111 representing its attribute path in nixpkgs (or another package set).
112112- Because of this, you need to pass nixpkgs itself (or a subset) as the first argument.
112112+ Because of this, you need to pass nixpkgs itself (usually `pkgs` in a module;
113113+ alternatively to nixpkgs itself, another package set) as the first argument.
114114+115115+ If you pass another package set you should set the `pkgsText` option.
116116+ This option is used to display the expression for the package set. It is `"pkgs"` by default.
117117+ If your expression is complex you should parenthesize it, as the `pkgsText` argument
118118+ is usually immediately followed by an attribute lookup (`.`).
113119114120 The second argument may be either a string or a list of strings.
115121 It provides the display name of the package in the description of the generated option
···118124119125 To include extra information in the description, pass `extraDescription` to
120126 append arbitrary text to the generated description.
127127+121128 You can also pass an `example` value, either a literal string or an attribute path.
122129123123- The default argument can be omitted if the provided name is
124124- an attribute of pkgs (if name is a string) or a
125125- valid attribute path in pkgs (if name is a list).
130130+ The `default` argument can be omitted if the provided name is
131131+ an attribute of pkgs (if `name` is a string) or a valid attribute path in pkgs (if `name` is a list).
132132+ You can also set `default` to just a string in which case it is interpreted as an attribute name
133133+ (a singleton attribute path, if you will).
126134127135 If you wish to explicitly provide no default, pass `null` as `default`.
128136129129- Type: mkPackageOption :: pkgs -> (string|[string]) -> { default? :: [string], example? :: null|string|[string], extraDescription? :: string } -> option
137137+ If you want users to be able to set no package, pass `nullable = true`.
138138+ In this mode a `default = null` will not be interpreted as no default and is interpreted literally.
139139+140140+ Type: mkPackageOption :: pkgs -> (string|[string]) -> { nullable? :: bool, default? :: string|[string], example? :: null|string|[string], extraDescription? :: string, pkgsText? :: string } -> option
130141131142 Example:
132143 mkPackageOption pkgs "hello" { }
133133- => { _type = "option"; default = «derivation /nix/store/3r2vg51hlxj3cx5vscp0vkv60bqxkaq0-hello-2.10.drv»; defaultText = { ... }; description = "The hello package to use."; type = { ... }; }
144144+ => { ...; default = pkgs.hello; defaultText = literalExpression "pkgs.hello"; description = "The hello package to use."; type = package; }
134145135146 Example:
136147 mkPackageOption pkgs "GHC" {
137148 default = [ "ghc" ];
138149 example = "pkgs.haskell.packages.ghc92.ghc.withPackages (hkgs: [ hkgs.primes ])";
139150 }
140140- => { _type = "option"; default = «derivation /nix/store/jxx55cxsjrf8kyh3fp2ya17q99w7541r-ghc-8.10.7.drv»; defaultText = { ... }; description = "The GHC package to use."; example = { ... }; type = { ... }; }
151151+ => { ...; default = pkgs.ghc; defaultText = literalExpression "pkgs.ghc"; description = "The GHC package to use."; example = literalExpression "pkgs.haskell.packages.ghc92.ghc.withPackages (hkgs: [ hkgs.primes ])"; type = package; }
141152142153 Example:
143143- mkPackageOption pkgs [ "python39Packages" "pytorch" ] {
154154+ mkPackageOption pkgs [ "python3Packages" "pytorch" ] {
144155 extraDescription = "This is an example and doesn't actually do anything.";
145156 }
146146- => { _type = "option"; default = «derivation /nix/store/gvqgsnc4fif9whvwd9ppa568yxbkmvk8-python3.9-pytorch-1.10.2.drv»; defaultText = { ... }; description = "The pytorch package to use. This is an example and doesn't actually do anything."; type = { ... }; }
157157+ => { ...; default = pkgs.python3Packages.pytorch; defaultText = literalExpression "pkgs.python3Packages.pytorch"; description = "The pytorch package to use. This is an example and doesn't actually do anything."; type = package; }
147158159159+ Example:
160160+ mkPackageOption pkgs "nushell" {
161161+ nullable = true;
162162+ }
163163+ => { ...; default = pkgs.nushell; defaultText = literalExpression "pkgs.nushell"; description = "The nushell package to use."; type = nullOr package; }
164164+165165+ Example:
166166+ mkPackageOption pkgs "coreutils" {
167167+ default = null;
168168+ }
169169+ => { ...; description = "The coreutils package to use."; type = package; }
170170+171171+ Example:
172172+ mkPackageOption pkgs "dbus" {
173173+ nullable = true;
174174+ default = null;
175175+ }
176176+ => { ...; default = null; description = "The dbus package to use."; type = nullOr package; }
177177+178178+ Example:
179179+ mkPackageOption pkgs.javaPackages "OpenJFX" {
180180+ default = "openjfx20";
181181+ pkgsText = "pkgs.javaPackages";
182182+ }
183183+ => { ...; default = pkgs.javaPackages.openjfx20; defaultText = literalExpression "pkgs.javaPackages.openjfx20"; description = "The OpenJFX package to use."; type = package; }
148184 */
149185 mkPackageOption =
150150- # Package set (a specific version of nixpkgs or a subset)
186186+ # Package set (an instantiation of nixpkgs such as pkgs in modules or another package set)
151187 pkgs:
152188 # Name for the package, shown in option description
153189 name:
154190 {
155155- # Whether the package can be null, for example to disable installing a package altogether.
191191+ # Whether the package can be null, for example to disable installing a package altogether (defaults to false)
156192 nullable ? false,
157157- # The attribute path where the default package is located (may be omitted)
193193+ # The attribute path where the default package is located (may be omitted, in which case it is copied from `name`)
158194 default ? name,
159195 # A string or an attribute path to use as an example (may be omitted)
160196 example ? null,
161197 # Additional text to include in the option description (may be omitted)
162198 extraDescription ? "",
199199+ # Representation of the package set passed as pkgs (defaults to `"pkgs"`)
200200+ pkgsText ? "pkgs"
163201 }:
164202 let
165203 name' = if isList name then last name else name;
166166- in mkOption ({
167167- type = with lib.types; (if nullable then nullOr else lib.id) package;
204204+ default' = if isList default then default else [ default ];
205205+ defaultText = concatStringsSep "." default';
206206+ defaultValue = attrByPath default'
207207+ (throw "${defaultText} cannot be found in ${pkgsText}") pkgs;
208208+ defaults = if default != null then {
209209+ default = defaultValue;
210210+ defaultText = literalExpression ("${pkgsText}." + defaultText);
211211+ } else optionalAttrs nullable {
212212+ default = null;
213213+ };
214214+ in mkOption (defaults // {
168215 description = "The ${name'} package to use."
169216 + (if extraDescription == "" then "" else " ") + extraDescription;
170170- } // (if default != null then let
171171- default' = if isList default then default else [ default ];
172172- defaultPath = concatStringsSep "." default';
173173- defaultValue = attrByPath default'
174174- (throw "${defaultPath} cannot be found in pkgs") pkgs;
175175- in {
176176- default = defaultValue;
177177- defaultText = literalExpression ("pkgs." + defaultPath);
178178- } else if nullable then {
179179- default = null;
180180- } else { }) // lib.optionalAttrs (example != null) {
217217+ type = with lib.types; (if nullable then nullOr else lib.id) package;
218218+ } // optionalAttrs (example != null) {
181219 example = literalExpression
182182- (if isList example then "pkgs." + concatStringsSep "." example else example);
220220+ (if isList example then "${pkgsText}." + concatStringsSep "." example else example);
183221 });
184222185223 /* Alias of mkPackageOption. Previously used to create options with markdown
+8
lib/tests/modules.sh
···227227228228# Check mkPackageOption
229229checkConfigOutput '^"hello"$' config.package.pname ./declare-mkPackageOption.nix
230230+checkConfigOutput '^"hello"$' config.namedPackage.pname ./declare-mkPackageOption.nix
231231+checkConfigOutput '^".*Hello.*"$' options.namedPackage.description ./declare-mkPackageOption.nix
232232+checkConfigOutput '^"hello"$' config.pathPackage.pname ./declare-mkPackageOption.nix
233233+checkConfigOutput '^"pkgs\.hello\.override \{ stdenv = pkgs\.clangStdenv; \}"$' options.packageWithExample.example.text ./declare-mkPackageOption.nix
234234+checkConfigOutput '^".*Example extra description\..*"$' options.packageWithExtraDescription.description ./declare-mkPackageOption.nix
230235checkConfigError 'The option .undefinedPackage. is used but not defined' config.undefinedPackage ./declare-mkPackageOption.nix
231236checkConfigOutput '^null$' config.nullablePackage ./declare-mkPackageOption.nix
237237+checkConfigOutput '^"null or package"$' options.nullablePackageWithDefault.type.description ./declare-mkPackageOption.nix
238238+checkConfigOutput '^"myPkgs\.hello"$' options.packageWithPkgsText.defaultText.text ./declare-mkPackageOption.nix
239239+checkConfigOutput '^"hello-other"$' options.packageFromOtherSet.default.pname ./declare-mkPackageOption.nix
232240233241# submoduleWith
234242
···66666767- [Prometheus MySQL exporter](https://github.com/prometheus/mysqld_exporter), a MySQL server exporter for Prometheus. Available as [services.prometheus.exporters.mysqld](#opt-services.prometheus.exporters.mysqld.enable).
68686969+- [LibreNMS](https://www.librenms.org), a auto-discovering PHP/MySQL/SNMP based network monitoring. Available as [services.librenms](#opt-services.librenms.enable).
7070+6971- [sitespeed-io](https://sitespeed.io), a tool that can generate metrics (timings, diagnostics) for websites. Available as [services.sitespeed-io](#opt-services.sitespeed-io.enable).
70727173- [stalwart-mail](https://stalw.art), an all-in-one email server (SMTP, IMAP, JMAP). Available as [services.stalwart-mail](#opt-services.stalwart-mail.enable).
···90929193- [Honk](https://humungus.tedunangst.com/r/honk), a complete ActivityPub server with minimal setup and support costs.
9294 Available as [services.honk](#opt-services.honk.enable).
9595+9696+- [ferretdb](https://www.ferretdb.io/), an open-source proxy, converting the MongoDB 6.0+ wire protocol queries to PostgreSQL or SQLite. Available as [services.ferretdb](options.html#opt-services.ferretdb.enable).
93979498- [NNCP](http://www.nncpgo.org/). Added nncp-daemon and nncp-caller services. Configuration is set with [programs.nncp.settings](#opt-programs.nncp.settings) and the daemons are enabled at [services.nncp](#opt-services.nncp.caller.enable).
9599···271275- Package `noto-fonts-emoji` was renamed to `noto-fonts-color-emoji`;
272276 see [#221181](https://github.com/NixOS/nixpkgs/issues/221181).
273277278278+- Package `cloud-sql-proxy` was renamed to `google-cloud-sql-proxy` as it cannot be used with other cloud providers.;
279279+274280- Package `pash` was removed due to being archived upstream. Use `powershell` as an alternative.
275281276282- `security.sudo.extraRules` now includes `root`'s default rule, with ordering
···294300- Setting `nixpkgs.config` options while providing an external `pkgs` instance will now raise an error instead of silently ignoring the options. NixOS modules no longer set `nixpkgs.config` to accomodate this. This specifically affects `services.locate`, `services.xserver.displayManager.lightdm.greeters.tiny` and `programs.firefox` NixOS modules. No manual intervention should be required in most cases, however, configurations relying on those modules affecting packages outside the system environment should switch to explicit overlays.
295301296302- `service.borgmatic.settings.location` and `services.borgmatic.configurations.<name>.location` are deprecated, please move your options out of sections to the global scope.
303303+304304+- `dagger` was removed because using a package called `dagger` and packaging it from source violates their trademark policy.
297305298306## Other Notable Changes {#sec-release-23.11-notable-changes}
299307
···7272 inherit (cfg) plugins;
7373 };
74747575- logConfig = logName: {
7575+ defaultCommonLogConfig = {
7676 version = 1;
7777 formatters.journal_fmt.format = "%(name)s: [%(request)s] %(message)s";
7878 handlers.journal = {
7979 class = "systemd.journal.JournalHandler";
8080 formatter = "journal_fmt";
8181- SYSLOG_IDENTIFIER = logName;
8281 };
8382 root = {
8483 level = "INFO";
···8685 };
8786 disable_existing_loggers = false;
8887 };
8888+8989+ defaultCommonLogConfigText = generators.toPretty { } defaultCommonLogConfig;
9090+8991 logConfigText = logName:
9090- let
9191- expr = ''
9292- {
9393- version = 1;
9494- formatters.journal_fmt.format = "%(name)s: [%(request)s] %(message)s";
9595- handlers.journal = {
9696- class = "systemd.journal.JournalHandler";
9797- formatter = "journal_fmt";
9898- SYSLOG_IDENTIFIER = "${logName}";
9999- };
100100- root = {
101101- level = "INFO";
102102- handlers = [ "journal" ];
103103- };
104104- disable_existing_loggers = false;
105105- };
106106- '';
107107- in
10892 lib.literalMD ''
10993 Path to a yaml file generated from this Nix expression:
1109411195 ```
112112- ${expr}
9696+ ${generators.toPretty { } (
9797+ recursiveUpdate defaultCommonLogConfig { handlers.journal.SYSLOG_IDENTIFIER = logName; }
9898+ )}
11399 ```
114100 '';
115115- genLogConfigFile = logName: format.generate "synapse-log-${logName}.yaml" (logConfig logName);
101101+102102+ genLogConfigFile = logName: format.generate
103103+ "synapse-log-${logName}.yaml"
104104+ (cfg.log // optionalAttrs (cfg.log?handlers.journal) {
105105+ handlers.journal = cfg.log.handlers.journal // {
106106+ SYSLOG_IDENTIFIER = logName;
107107+ };
108108+ });
116109in {
117110118111 imports = [
···393386 description = lib.mdDoc ''
394387 The directory where matrix-synapse stores its stateful data such as
395388 certificates, media and uploads.
389389+ '';
390390+ };
391391+392392+ log = mkOption {
393393+ type = types.attrsOf format.type;
394394+ defaultText = literalExpression defaultCommonLogConfigText;
395395+ description = mdDoc ''
396396+ Default configuration for the loggers used by `matrix-synapse` and its workers.
397397+ The defaults are added with the default priority which means that
398398+ these will be merged with additional declarations. These additional
399399+ declarations also take precedence over the defaults when declared
400400+ with at least normal priority. For instance
401401+ the log-level for synapse and its workers can be changed like this:
402402+403403+ ```nix
404404+ { lib, ... }: {
405405+ services.matrix-synapse.log.root.level = "WARNING";
406406+ }
407407+ ```
408408+409409+ And another field can be added like this:
410410+411411+ ```nix
412412+ {
413413+ services.matrix-synapse.log = {
414414+ loggers."synapse.http.matrixfederationclient".level = "DEBUG";
415415+ };
416416+ }
417417+ ```
418418+419419+ Additionally, the field `handlers.journal.SYSLOG_IDENTIFIER` will be added to
420420+ each log config, i.e.
421421+ * `synapse` for `matrix-synapse.service`
422422+ * `synapse-<worker name>` for `matrix-synapse-worker-<worker name>.service`
423423+424424+ This is only done if this option has a `handlers.journal` field declared.
425425+426426+ To discard all settings declared by this option for each worker and synapse,
427427+ `lib.mkForce` can be used.
428428+429429+ To discard all settings declared by this option for a single worker or synapse only,
430430+ [](#opt-services.matrix-synapse.workers._name_.worker_log_config) or
431431+ [](#opt-services.matrix-synapse.settings.log_config) can be used.
396432 '';
397433 };
398434···99210289931029 # default them, so they are additive
9941030 services.matrix-synapse.extras = defaultExtras;
10311031+10321032+ services.matrix-synapse.log = mapAttrsRecursive (const mkDefault) defaultCommonLogConfig;
99510339961034 users.users.matrix-synapse = {
9971035 group = "matrix-synapse";
+624
nixos/modules/services/monitoring/librenms.nix
···11+{ config, lib, pkgs, ... }:
22+33+let
44+ cfg = config.services.librenms;
55+ settingsFormat = pkgs.formats.json {};
66+ configJson = settingsFormat.generate "librenms-config.json" cfg.settings;
77+88+ package = pkgs.librenms.override {
99+ logDir = cfg.logDir;
1010+ dataDir = cfg.dataDir;
1111+ };
1212+1313+ phpOptions = ''
1414+ log_errors = on
1515+ post_max_size = 100M
1616+ upload_max_filesize = 100M
1717+ date.timezone = "${config.time.timeZone}"
1818+ '';
1919+ phpIni = pkgs.runCommand "php.ini" {
2020+ inherit (package) phpPackage;
2121+ inherit phpOptions;
2222+ preferLocalBuild = true;
2323+ passAsFile = [ "phpOptions" ];
2424+ } ''
2525+ cat $phpPackage/etc/php.ini $phpOptionsPath > $out
2626+ '';
2727+2828+ artisanWrapper = pkgs.writeShellScriptBin "librenms-artisan" ''
2929+ cd ${package}
3030+ sudo=exec
3131+ if [[ "$USER" != ${cfg.user} ]]; then
3232+ sudo='exec /run/wrappers/bin/sudo -u ${cfg.user}'
3333+ fi
3434+ $sudo ${package}/artisan $*
3535+ '';
3636+3737+ lnmsWrapper = pkgs.writeShellScriptBin "lnms" ''
3838+ cd ${package}
3939+ exec ${package}/lnms $*
4040+ '';
4141+4242+ configFile = pkgs.writeText "config.php" ''
4343+ <?php
4444+ $new_config = json_decode(file_get_contents("${cfg.dataDir}/config.json"), true);
4545+ $config = ($config == null) ? $new_config : array_merge($config, $new_config);
4646+4747+ ${lib.optionalString (cfg.extraConfig != null) cfg.extraConfig}
4848+ '';
4949+5050+in {
5151+ options.services.librenms = with lib; {
5252+ enable = mkEnableOption "LibreNMS network monitoring system";
5353+5454+ user = mkOption {
5555+ type = types.str;
5656+ default = "librenms";
5757+ description = ''
5858+ Name of the LibreNMS user.
5959+ '';
6060+ };
6161+6262+ group = mkOption {
6363+ type = types.str;
6464+ default = "librenms";
6565+ description = ''
6666+ Name of the LibreNMS group.
6767+ '';
6868+ };
6969+7070+ hostname = mkOption {
7171+ type = types.str;
7272+ default = config.networking.fqdnOrHostName;
7373+ defaultText = literalExpression "config.networking.fqdnOrHostName";
7474+ description = ''
7575+ The hostname to serve LibreNMS on.
7676+ '';
7777+ };
7878+7979+ pollerThreads = mkOption {
8080+ type = types.int;
8181+ default = 16;
8282+ description = ''
8383+ Amount of threads of the cron-poller.
8484+ '';
8585+ };
8686+8787+ enableOneMinutePolling = mkOption {
8888+ type = types.bool;
8989+ default = false;
9090+ description = ''
9191+ Enables the [1-Minute Polling](https://docs.librenms.org/Support/1-Minute-Polling/).
9292+ Changing this option will automatically convert your existing rrd files.
9393+ '';
9494+ };
9595+9696+ useDistributedPollers = mkOption {
9797+ type = types.bool;
9898+ default = false;
9999+ description = ''
100100+ Enables (distributed pollers)[https://docs.librenms.org/Extensions/Distributed-Poller/]
101101+ for this LibreNMS instance. This will enable a local `rrdcached` and `memcached` server.
102102+103103+ To use this feature, make sure to configure your firewall that the distributed pollers
104104+ can reach the local `mysql`, `rrdcached` and `memcached` ports.
105105+ '';
106106+ };
107107+108108+ distributedPoller = {
109109+ enable = mkOption {
110110+ type = types.bool;
111111+ default = false;
112112+ description = ''
113113+ Configure this LibreNMS instance as a (distributed poller)[https://docs.librenms.org/Extensions/Distributed-Poller/].
114114+ This will disable all web features and just configure the poller features.
115115+ Use the `mysql` database of your main LibreNMS instance in the database settings.
116116+ '';
117117+ };
118118+119119+ name = mkOption {
120120+ type = types.nullOr types.str;
121121+ default = null;
122122+ description = ''
123123+ Custom name of this poller.
124124+ '';
125125+ };
126126+127127+ group = mkOption {
128128+ type = types.str;
129129+ default = "0";
130130+ example = "1,2";
131131+ description = ''
132132+ Group(s) of this poller.
133133+ '';
134134+ };
135135+136136+ distributedBilling = mkOption {
137137+ type = types.bool;
138138+ default = false;
139139+ description = ''
140140+ Enable distributed billing on this poller.
141141+ '';
142142+ };
143143+144144+ memcachedHost = mkOption {
145145+ type = types.str;
146146+ description = ''
147147+ Hostname or IP of the `memcached` server.
148148+ '';
149149+ };
150150+151151+ memcachedPort = mkOption {
152152+ type = types.port;
153153+ default = 11211;
154154+ description = ''
155155+ Port of the `memcached` server.
156156+ '';
157157+ };
158158+159159+ rrdcachedHost = mkOption {
160160+ type = types.str;
161161+ description = ''
162162+ Hostname or IP of the `rrdcached` server.
163163+ '';
164164+ };
165165+166166+ rrdcachedPort = mkOption {
167167+ type = types.port;
168168+ default = 42217;
169169+ description = ''
170170+ Port of the `memcached` server.
171171+ '';
172172+ };
173173+ };
174174+175175+ poolConfig = mkOption {
176176+ type = with types; attrsOf (oneOf [ str int bool ]);
177177+ default = {
178178+ "pm" = "dynamic";
179179+ "pm.max_children" = 32;
180180+ "pm.start_servers" = 2;
181181+ "pm.min_spare_servers" = 2;
182182+ "pm.max_spare_servers" = 4;
183183+ "pm.max_requests" = 500;
184184+ };
185185+ description = ''
186186+ Options for the LibreNMS PHP pool. See the documentation on `php-fpm.conf`
187187+ for details on configuration directives.
188188+ '';
189189+ };
190190+191191+ nginx = mkOption {
192192+ type = types.submodule (
193193+ recursiveUpdate
194194+ (import ../web-servers/nginx/vhost-options.nix { inherit config lib; }) {}
195195+ );
196196+ default = { };
197197+ example = literalExpression ''
198198+ {
199199+ serverAliases = [
200200+ "librenms.''${config.networking.domain}"
201201+ ];
202202+ # To enable encryption and let let's encrypt take care of certificate
203203+ forceSSL = true;
204204+ enableACME = true;
205205+ # To set the LibreNMS virtualHost as the default virtualHost;
206206+ default = true;
207207+ }
208208+ '';
209209+ description = ''
210210+ With this option, you can customize the nginx virtualHost settings.
211211+ '';
212212+ };
213213+214214+ dataDir = mkOption {
215215+ type = types.path;
216216+ default = "/var/lib/librenms";
217217+ description = ''
218218+ Path of the LibreNMS state directory.
219219+ '';
220220+ };
221221+222222+ logDir = mkOption {
223223+ type = types.path;
224224+ default = "/var/log/librenms";
225225+ description = ''
226226+ Path of the LibreNMS logging directory.
227227+ '';
228228+ };
229229+230230+ database = {
231231+ createLocally = mkOption {
232232+ type = types.bool;
233233+ default = false;
234234+ description = ''
235235+ Whether to create a local database automatically.
236236+ '';
237237+ };
238238+239239+ host = mkOption {
240240+ default = "localhost";
241241+ description = ''
242242+ Hostname or IP of the MySQL/MariaDB server.
243243+ '';
244244+ };
245245+246246+ port = mkOption {
247247+ type = types.port;
248248+ default = 3306;
249249+ description = ''
250250+ Port of the MySQL/MariaDB server.
251251+ '';
252252+ };
253253+254254+ database = mkOption {
255255+ type = types.str;
256256+ default = "librenms";
257257+ description = ''
258258+ Name of the database on the MySQL/MariaDB server.
259259+ '';
260260+ };
261261+262262+ username = mkOption {
263263+ type = types.str;
264264+ default = "librenms";
265265+ description = ''
266266+ Name of the user on the MySQL/MariaDB server.
267267+ '';
268268+ };
269269+270270+ passwordFile = mkOption {
271271+ type = types.path;
272272+ example = "/run/secrets/mysql.pass";
273273+ description = ''
274274+ A file containing the password for the user of the MySQL/MariaDB server.
275275+ Must be readable for the LibreNMS user.
276276+ '';
277277+ };
278278+ };
279279+280280+ environmentFile = mkOption {
281281+ type = types.nullOr types.str;
282282+ default = null;
283283+ description = ''
284284+ File containing env-vars to be substituted into the final config. Useful for secrets.
285285+ Does not apply to settings defined in `extraConfig`.
286286+ '';
287287+ };
288288+289289+ settings = mkOption {
290290+ type = types.submodule {
291291+ freeformType = settingsFormat.type;
292292+ options = {};
293293+ };
294294+ description = ''
295295+ Attrset of the LibreNMS configuration.
296296+ See https://docs.librenms.org/Support/Configuration/ for reference.
297297+ All possible options are listed [here](https://github.com/librenms/librenms/blob/master/misc/config_definitions.json).
298298+ See https://docs.librenms.org/Extensions/Authentication/ for setting other authentication methods.
299299+ '';
300300+ default = { };
301301+ example = {
302302+ base_url = "/librenms/";
303303+ top_devices = true;
304304+ top_ports = false;
305305+ };
306306+ };
307307+308308+ extraConfig = mkOption {
309309+ type = types.nullOr types.str;
310310+ default = null;
311311+ description = ''
312312+ Additional config for LibreNMS that will be appended to the `config.php`. See
313313+ https://github.com/librenms/librenms/blob/master/misc/config_definitions.json
314314+ for possible options. Useful if you want to use PHP-Functions in your config.
315315+ '';
316316+ };
317317+ };
318318+319319+ config = lib.mkIf cfg.enable {
320320+ assertions = [
321321+ {
322322+ assertion = config.time.timeZone != null;
323323+ message = "You must set `time.timeZone` to use the LibreNMS module.";
324324+ }
325325+ {
326326+ assertion = cfg.database.createLocally -> cfg.database.host == "localhost";
327327+ message = "The database host must be \"localhost\" if services.librenms.database.createLocally is set to true.";
328328+ }
329329+ {
330330+ assertion = !(cfg.useDistributedPollers && cfg.distributedPoller.enable);
331331+ message = "The LibreNMS instance can't be a distributed poller and a full instance at the same time.";
332332+ }
333333+ ];
334334+335335+ users.users.${cfg.user} = {
336336+ group = "${cfg.group}";
337337+ isSystemUser = true;
338338+ };
339339+340340+ users.groups.${cfg.group} = { };
341341+342342+ services.librenms.settings = {
343343+ # basic configs
344344+ "user" = cfg.user;
345345+ "own_hostname" = cfg.hostname;
346346+ "base_url" = lib.mkDefault "/";
347347+ "auth_mechanism" = lib.mkDefault "mysql";
348348+349349+ # disable auto update function (won't work with NixOS)
350350+ "update" = false;
351351+352352+ # enable fast ping by default
353353+ "ping_rrd_step" = 60;
354354+355355+ # one minute polling
356356+ "rrd.step" = if cfg.enableOneMinutePolling then 60 else 300;
357357+ "rrd.heartbeat" = if cfg.enableOneMinutePolling then 120 else 600;
358358+ } // (lib.optionalAttrs cfg.distributedPoller.enable {
359359+ "distributed_poller" = true;
360360+ "distributed_poller_name" = lib.mkIf (cfg.distributedPoller.name != null) cfg.distributedPoller.name;
361361+ "distributed_poller_group" = cfg.distributedPoller.group;
362362+ "distributed_billing" = cfg.distributedPoller.distributedBilling;
363363+ "distributed_poller_memcached_host" = cfg.distributedPoller.memcachedHost;
364364+ "distributed_poller_memcached_port" = cfg.distributedPoller.memcachedPort;
365365+ "rrdcached" = "${cfg.distributedPoller.rrdcachedHost}:${toString cfg.distributedPoller.rrdcachedPort}";
366366+ }) // (lib.optionalAttrs cfg.useDistributedPollers {
367367+ "distributed_poller" = true;
368368+ # still enable a local poller with distributed polling
369369+ "distributed_poller_group" = lib.mkDefault "0";
370370+ "distributed_billing" = lib.mkDefault true;
371371+ "distributed_poller_memcached_host" = "localhost";
372372+ "distributed_poller_memcached_port" = 11211;
373373+ "rrdcached" = "localhost:42217";
374374+ });
375375+376376+ services.memcached = lib.mkIf cfg.useDistributedPollers {
377377+ enable = true;
378378+ listen = "0.0.0.0";
379379+ };
380380+381381+ systemd.services.rrdcached = lib.mkIf cfg.useDistributedPollers {
382382+ description = "rrdcached";
383383+ after = [ "librenms-setup.service" ];
384384+ wantedBy = [ "multi-user.target" ];
385385+ serviceConfig = {
386386+ Type = "forking";
387387+ User = cfg.user;
388388+ Group = cfg.group;
389389+ LimitNOFILE = 16384;
390390+ RuntimeDirectory = "rrdcached";
391391+ PidFile = "/run/rrdcached/rrdcached.pid";
392392+ # rrdcached params from https://docs.librenms.org/Extensions/Distributed-Poller/#config-sample
393393+ ExecStart = "${pkgs.rrdtool}/bin/rrdcached -l 0:42217 -R -j ${cfg.dataDir}/rrdcached-journal/ -F -b ${cfg.dataDir}/rrd -B -w 1800 -z 900 -p /run/rrdcached/rrdcached.pid";
394394+ };
395395+ };
396396+397397+ services.mysql = lib.mkIf cfg.database.createLocally {
398398+ enable = true;
399399+ package = lib.mkDefault pkgs.mariadb;
400400+ settings.mysqld = {
401401+ innodb_file_per_table = 1;
402402+ lower_case_table_names = 0;
403403+ } // (lib.optionalAttrs cfg.useDistributedPollers {
404404+ bind-address = "0.0.0.0";
405405+ });
406406+ ensureDatabases = [ cfg.database.database ];
407407+ ensureUsers = [
408408+ {
409409+ name = cfg.database.username;
410410+ ensurePermissions = {
411411+ "${cfg.database.database}.*" = "ALL PRIVILEGES";
412412+ };
413413+ }
414414+ ];
415415+ initialScript = lib.mkIf cfg.useDistributedPollers (pkgs.writeText "mysql-librenms-init" ''
416416+ CREATE USER IF NOT EXISTS '${cfg.database.username}'@'%';
417417+ GRANT ALL PRIVILEGES ON ${cfg.database.database}.* TO '${cfg.database.username}'@'%';
418418+ '');
419419+ };
420420+421421+ services.nginx = lib.mkIf (!cfg.distributedPoller.enable) {
422422+ enable = true;
423423+ virtualHosts."${cfg.hostname}" = lib.mkMerge [
424424+ cfg.nginx
425425+ {
426426+ root = lib.mkForce "${package}/html";
427427+ locations."/" = {
428428+ index = "index.php";
429429+ tryFiles = "$uri $uri/ /index.php?$query_string";
430430+ };
431431+ locations."~ .php$".extraConfig = ''
432432+ fastcgi_pass unix:${config.services.phpfpm.pools."librenms".socket};
433433+ fastcgi_split_path_info ^(.+\.php)(/.+)$;
434434+ '';
435435+ }
436436+ ];
437437+ };
438438+439439+ services.phpfpm.pools.librenms = lib.mkIf (!cfg.distributedPoller.enable) {
440440+ user = cfg.user;
441441+ group = cfg.group;
442442+ inherit (package) phpPackage;
443443+ inherit phpOptions;
444444+ settings = {
445445+ "listen.mode" = "0660";
446446+ "listen.owner" = config.services.nginx.user;
447447+ "listen.group" = config.services.nginx.group;
448448+ } // cfg.poolConfig;
449449+ };
450450+451451+ systemd.services.librenms-scheduler = {
452452+ description = "LibreNMS Scheduler";
453453+ path = [ pkgs.unixtools.whereis ];
454454+ serviceConfig = {
455455+ Type = "oneshot";
456456+ WorkingDirectory = package;
457457+ User = cfg.user;
458458+ Group = cfg.group;
459459+ ExecStart = "${artisanWrapper}/bin/librenms-artisan schedule:run";
460460+ };
461461+ };
462462+463463+ systemd.timers.librenms-scheduler = {
464464+ description = "LibreNMS Scheduler";
465465+ wantedBy = [ "timers.target" ];
466466+ timerConfig = {
467467+ OnCalendar = "minutely";
468468+ AccuracySec = "1second";
469469+ };
470470+ };
471471+472472+ systemd.services.librenms-setup = {
473473+ description = "Preparation tasks for LibreNMS";
474474+ before = [ "phpfpm-librenms.service" ];
475475+ after = [ "systemd-tmpfiles-setup.service" ]
476476+ ++ (lib.optional (cfg.database.host == "localhost") "mysql.service");
477477+ wantedBy = [ "multi-user.target" ];
478478+ restartTriggers = [ package configFile ];
479479+ path = [ pkgs.mariadb pkgs.unixtools.whereis pkgs.gnused ];
480480+ serviceConfig = {
481481+ Type = "oneshot";
482482+ RemainAfterExit = true;
483483+ EnvironmentFile = lib.mkIf (cfg.environmentFile != null) [ cfg.environmentFile ];
484484+ User = cfg.user;
485485+ Group = cfg.group;
486486+ ExecStartPre = lib.mkIf cfg.database.createLocally [ "!${pkgs.writeShellScript "librenms-db-init" ''
487487+ DB_PASSWORD=$(cat ${cfg.database.passwordFile} | tr -d '\n')
488488+ echo "ALTER USER '${cfg.database.username}'@'localhost' IDENTIFIED BY '$DB_PASSWORD';" | ${pkgs.mariadb}/bin/mysql
489489+ ${lib.optionalString cfg.useDistributedPollers ''
490490+ echo "ALTER USER '${cfg.database.username}'@'%' IDENTIFIED BY '$DB_PASSWORD';" | ${pkgs.mariadb}/bin/mysql
491491+ ''}
492492+ ''}"];
493493+ };
494494+ script = ''
495495+ set -euo pipefail
496496+497497+ # config setup
498498+ ln -sf ${configFile} ${cfg.dataDir}/config.php
499499+ ${pkgs.envsubst}/bin/envsubst -i ${configJson} -o ${cfg.dataDir}/config.json
500500+ export PHPRC=${phpIni}
501501+502502+ if [[ ! -s ${cfg.dataDir}/.env ]]; then
503503+ # init .env file
504504+ echo "APP_KEY=" > ${cfg.dataDir}/.env
505505+ ${artisanWrapper}/bin/librenms-artisan key:generate --ansi
506506+ ${artisanWrapper}/bin/librenms-artisan webpush:vapid
507507+ echo "" >> ${cfg.dataDir}/.env
508508+ echo -n "NODE_ID=" >> ${cfg.dataDir}/.env
509509+ ${package.phpPackage}/bin/php -r "echo uniqid();" >> ${cfg.dataDir}/.env
510510+ echo "" >> ${cfg.dataDir}/.env
511511+ else
512512+ # .env file already exists --> only update database and cache config
513513+ ${pkgs.gnused}/bin/sed -i /^DB_/d ${cfg.dataDir}/.env
514514+ ${pkgs.gnused}/bin/sed -i /^CACHE_DRIVER/d ${cfg.dataDir}/.env
515515+ fi
516516+ ${lib.optionalString (cfg.useDistributedPollers || cfg.distributedPoller.enable) ''
517517+ echo "CACHE_DRIVER=memcached" >> ${cfg.dataDir}/.env
518518+ ''}
519519+ echo "DB_HOST=${cfg.database.host}" >> ${cfg.dataDir}/.env
520520+ echo "DB_PORT=${toString cfg.database.port}" >> ${cfg.dataDir}/.env
521521+ echo "DB_DATABASE=${cfg.database.database}" >> ${cfg.dataDir}/.env
522522+ echo "DB_USERNAME=${cfg.database.username}" >> ${cfg.dataDir}/.env
523523+ echo -n "DB_PASSWORD=" >> ${cfg.dataDir}/.env
524524+ cat ${cfg.database.passwordFile} >> ${cfg.dataDir}/.env
525525+526526+ # clear cache after update
527527+ OLD_VERSION=$(cat ${cfg.dataDir}/version)
528528+ if [[ $OLD_VERSION != "${package.version}" ]]; then
529529+ rm -r ${cfg.dataDir}/cache/*
530530+ echo "${package.version}" > ${cfg.dataDir}/version
531531+ fi
532532+533533+ # convert rrd files when the oneMinutePolling option is changed
534534+ OLD_ENABLED=$(cat ${cfg.dataDir}/one_minute_enabled)
535535+ if [[ $OLD_ENABLED != "${lib.boolToString cfg.enableOneMinutePolling}" ]]; then
536536+ ${package}/scripts/rrdstep.php -h all
537537+ echo "${lib.boolToString cfg.enableOneMinutePolling}" > ${cfg.dataDir}/one_minute_enabled
538538+ fi
539539+540540+ # migrate db
541541+ ${artisanWrapper}/bin/librenms-artisan migrate --force --no-interaction
542542+ '';
543543+ };
544544+545545+ programs.mtr.enable = true;
546546+547547+ services.logrotate = {
548548+ enable = true;
549549+ settings."${cfg.logDir}/librenms.log" = {
550550+ su = "${cfg.user} ${cfg.group}";
551551+ create = "0640 ${cfg.user} ${cfg.group}";
552552+ rotate = 6;
553553+ frequency = "weekly";
554554+ compress = true;
555555+ delaycompress = true;
556556+ missingok = true;
557557+ notifempty = true;
558558+ };
559559+ };
560560+561561+ services.cron = {
562562+ enable = true;
563563+ systemCronJobs = let
564564+ env = "PHPRC=${phpIni}";
565565+ in [
566566+ # based on crontab provided by LibreNMS
567567+ "33 */6 * * * ${cfg.user} ${env} ${package}/cronic ${package}/discovery-wrapper.py 1"
568568+ "*/5 * * * * ${cfg.user} ${env} ${package}/discovery.php -h new >> /dev/null 2>&1"
569569+570570+ "${if cfg.enableOneMinutePolling then "*" else "*/5"} * * * * ${cfg.user} ${env} ${package}/cronic ${package}/poller-wrapper.py ${toString cfg.pollerThreads}"
571571+ "* * * * * ${cfg.user} ${env} ${package}/alerts.php >> /dev/null 2>&1"
572572+573573+ "*/5 * * * * ${cfg.user} ${env} ${package}/poll-billing.php >> /dev/null 2>&1"
574574+ "01 * * * * ${cfg.user} ${env} ${package}/billing-calculate.php >> /dev/null 2>&1"
575575+ "*/5 * * * * ${cfg.user} ${env} ${package}/check-services.php >> /dev/null 2>&1"
576576+577577+ # extra: fast ping
578578+ "* * * * * ${cfg.user} ${env} ${package}/ping.php >> /dev/null 2>&1"
579579+580580+ # daily.sh tasks are split to exclude update
581581+ "19 0 * * * ${cfg.user} ${env} ${package}/daily.sh cleanup >> /dev/null 2>&1"
582582+ "19 0 * * * ${cfg.user} ${env} ${package}/daily.sh notifications >> /dev/null 2>&1"
583583+ "19 0 * * * ${cfg.user} ${env} ${package}/daily.sh peeringdb >> /dev/null 2>&1"
584584+ "19 0 * * * ${cfg.user} ${env} ${package}/daily.sh mac_oui >> /dev/null 2>&1"
585585+ ];
586586+ };
587587+588588+ security.wrappers = {
589589+ fping = {
590590+ setuid = true;
591591+ owner = "root";
592592+ group = "root";
593593+ source = "${pkgs.fping}/bin/fping";
594594+ };
595595+ };
596596+597597+ environment.systemPackages = [ artisanWrapper lnmsWrapper ];
598598+599599+ systemd.tmpfiles.rules = [
600600+ "d ${cfg.logDir} 0750 ${cfg.user} ${cfg.group} - -"
601601+ "f ${cfg.logDir}/librenms.log 0640 ${cfg.user} ${cfg.group} - -"
602602+ "d ${cfg.dataDir} 0750 ${cfg.user} ${cfg.group} - -"
603603+ "f ${cfg.dataDir}/.env 0600 ${cfg.user} ${cfg.group} - -"
604604+ "f ${cfg.dataDir}/version 0600 ${cfg.user} ${cfg.group} - -"
605605+ "f ${cfg.dataDir}/one_minute_enabled 0600 ${cfg.user} ${cfg.group} - -"
606606+ "f ${cfg.dataDir}/config.json 0600 ${cfg.user} ${cfg.group} - -"
607607+ "d ${cfg.dataDir}/storage 0700 ${cfg.user} ${cfg.group} - -"
608608+ "d ${cfg.dataDir}/storage/app 0700 ${cfg.user} ${cfg.group} - -"
609609+ "d ${cfg.dataDir}/storage/debugbar 0700 ${cfg.user} ${cfg.group} - -"
610610+ "d ${cfg.dataDir}/storage/framework 0700 ${cfg.user} ${cfg.group} - -"
611611+ "d ${cfg.dataDir}/storage/framework/cache 0700 ${cfg.user} ${cfg.group} - -"
612612+ "d ${cfg.dataDir}/storage/framework/sessions 0700 ${cfg.user} ${cfg.group} - -"
613613+ "d ${cfg.dataDir}/storage/framework/views 0700 ${cfg.user} ${cfg.group} - -"
614614+ "d ${cfg.dataDir}/storage/logs 0700 ${cfg.user} ${cfg.group} - -"
615615+ "d ${cfg.dataDir}/rrd 0700 ${cfg.user} ${cfg.group} - -"
616616+ "d ${cfg.dataDir}/cache 0700 ${cfg.user} ${cfg.group} - -"
617617+ ] ++ lib.optionals cfg.useDistributedPollers [
618618+ "d ${cfg.dataDir}/rrdcached-journal 0700 ${cfg.user} ${cfg.group} - -"
619619+ ];
620620+621621+ };
622622+623623+ meta.maintainers = lib.teams.wdz.members;
624624+}
+125
nixos/modules/services/networking/deconz.nix
···11+{ config, lib, pkgs, ... }:
22+33+let
44+ cfg = config.services.deconz;
55+ name = "deconz";
66+ stateDir = "/var/lib/${name}";
77+ # ref. upstream deconz.service
88+ capabilities =
99+ lib.optionals (cfg.httpPort < 1024 || cfg.wsPort < 1024) [ "CAP_NET_BIND_SERVICE" ]
1010+ ++ lib.optionals (cfg.allowRebootSystem) [ "CAP_SYS_BOOT" ]
1111+ ++ lib.optionals (cfg.allowRestartService) [ "CAP_KILL" ]
1212+ ++ lib.optionals (cfg.allowSetSystemTime) [ "CAP_SYS_TIME" ];
1313+in
1414+{
1515+ options.services.deconz = {
1616+1717+ enable = lib.mkEnableOption "deCONZ, a Zigbee gateway for use with ConBee hardware (https://phoscon.de/en/conbee2)";
1818+1919+ package = lib.mkOption {
2020+ type = lib.types.package;
2121+ default = pkgs.deconz;
2222+ defaultText = lib.literalExpression "pkgs.deconz";
2323+ description = "Which deCONZ package to use.";
2424+ };
2525+2626+ device = lib.mkOption {
2727+ type = lib.types.nullOr lib.types.str;
2828+ default = null;
2929+ description = ''
3030+ Force deCONZ to use a specific USB device (e.g. /dev/ttyACM0). By
3131+ default it does a search.
3232+ '';
3333+ };
3434+3535+ listenAddress = lib.mkOption {
3636+ type = lib.types.str;
3737+ default = "127.0.0.1";
3838+ description = ''
3939+ Pin deCONZ to the network interface specified through the provided IP
4040+ address. This applies for the webserver as well as the websocket
4141+ notifications.
4242+ '';
4343+ };
4444+4545+ httpPort = lib.mkOption {
4646+ type = lib.types.port;
4747+ default = 80;
4848+ description = "TCP port for the web server.";
4949+ };
5050+5151+ wsPort = lib.mkOption {
5252+ type = lib.types.port;
5353+ default = 443;
5454+ description = "TCP port for the WebSocket.";
5555+ };
5656+5757+ openFirewall = lib.mkEnableOption "open up the service ports in the firewall";
5858+5959+ allowRebootSystem = lib.mkEnableOption "allow rebooting the system";
6060+6161+ allowRestartService = lib.mkEnableOption "allow killing/restarting processes";
6262+6363+ allowSetSystemTime = lib.mkEnableOption "allow setting the system time";
6464+6565+ extraArgs = lib.mkOption {
6666+ type = lib.types.listOf lib.types.str;
6767+ default = [ ];
6868+ example = [
6969+ "--dbg-info=1"
7070+ "--dbg-err=2"
7171+ ];
7272+ description = ''
7373+ Extra command line arguments for deCONZ, see
7474+ https://github.com/dresden-elektronik/deconz-rest-plugin/wiki/deCONZ-command-line-parameters.
7575+ '';
7676+ };
7777+ };
7878+7979+ config = lib.mkIf cfg.enable {
8080+8181+ networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [
8282+ cfg.httpPort
8383+ cfg.wsPort
8484+ ];
8585+8686+ services.udev.packages = [ cfg.package ];
8787+8888+ systemd.services.deconz = {
8989+ description = "deCONZ Zigbee gateway";
9090+ wantedBy = [ "multi-user.target" ];
9191+ preStart = ''
9292+ # The service puts a nix store path reference in here, and that path can
9393+ # be garbage collected. Ensure the file gets "refreshed" on every start.
9494+ rm -f ${stateDir}/.local/share/dresden-elektronik/deCONZ/zcldb.txt
9595+ '';
9696+ environment = {
9797+ HOME = stateDir;
9898+ XDG_RUNTIME_DIR = "/run/${name}";
9999+ };
100100+ serviceConfig = {
101101+ ExecStart =
102102+ "${lib.getExe cfg.package}"
103103+ + " -platform minimal"
104104+ + " --http-listen=${cfg.listenAddress}"
105105+ + " --http-port=${toString cfg.httpPort}"
106106+ + " --ws-port=${toString cfg.wsPort}"
107107+ + " --auto-connect=1"
108108+ + (lib.optionalString (cfg.device != null) " --dev=${cfg.device}")
109109+ + " " + (lib.escapeShellArgs cfg.extraArgs);
110110+ Restart = "on-failure";
111111+ AmbientCapabilities = capabilities;
112112+ CapabilityBoundingSet = capabilities;
113113+ UMask = "0027";
114114+ DynamicUser = true;
115115+ RuntimeDirectory = name;
116116+ RuntimeDirectoryMode = "0700";
117117+ StateDirectory = name;
118118+ WorkingDirectory = stateDir;
119119+ # For access to /dev/ttyACM0 (ConBee).
120120+ SupplementaryGroups = [ "dialout" ];
121121+ ProtectHome = true;
122122+ };
123123+ };
124124+ };
125125+}
···66 "auth required pam_deny.so",
77 "auth sufficient @@pam_ccreds@@/lib/security/pam_ccreds.so action=store use_first_pass",
88 "auth sufficient pam_rootok.so",
99- "auth sufficient pam_unix.so likeauth try_first_pass",
99+ "auth sufficient pam_unix.so likeauth try_first_pass",
1010 "password sufficient @@pam_krb5@@/lib/security/pam_krb5.so use_first_pass",
1111 "password sufficient pam_unix.so nullok yescrypt",
1212 "session optional @@pam_krb5@@/lib/security/pam_krb5.so",
···1515}
1616actual_lines = set(machine.succeed("cat /etc/pam.d/chfn").splitlines())
17171818-missing_lines = expected_lines - actual_lines
1919-extra_lines = actual_lines - expected_lines
2020-non_functional_lines = set([line for line in extra_lines if (line == "" or line.startswith("#"))])
1818+stripped_lines = set([line.split("#")[0].rstrip() for line in actual_lines])
1919+missing_lines = expected_lines - stripped_lines
2020+extra_lines = stripped_lines - expected_lines
2121+non_functional_lines = set([line for line in extra_lines if line == ""])
2122unexpected_functional_lines = extra_lines - non_functional_lines
22232324with subtest("All expected lines are in the file"):
-10
nixos/tests/systemd-repart.nix
···2929 "+32M",
3030 ])
31313232- # Fix the GPT table by moving the backup table to the end of the enlarged
3333- # disk image. This is necessary because we increased the size of the disk
3434- # before. The disk needs to be a raw disk because sgdisk can only run on
3535- # raw images.
3636- subprocess.run([
3737- "${pkgs.gptfdisk}/bin/sgdisk",
3838- "--move-second-header",
3939- tmp_disk_image.name,
4040- ])
4141-4232 # Set NIX_DISK_IMAGE so that the qemu script finds the right disk image.
4333 os.environ['NIX_DISK_IMAGE'] = tmp_disk_image.name
4434 '';
···55 stampYmd ? 0, stampHms ? 0,
66 gambit-support,
77 optimizationSetting ? "-O1",
88- gambit-params ? pkgs.gambit-support.stable-params }:
88+ gambit-params ? pkgs.gambit-support.stable-params,
99+ rev ? git-version }:
9101011# Note that according to a benchmark run by Marc Feeley on May 2018,
1112# clang is 10x (with default settings) to 15% (with -O2) slower than GCC at compiling
···3031 inherit src version git-version;
3132 bootstrap = gambit-support.gambit-bootstrap;
32333434+ passthru = {
3535+ inherit src version git-version rev stampYmd stampHms optimizationSetting openssl;
3636+ };
3737+3838+3339 nativeBuildInputs = [ git autoconf ];
34403541 # TODO: if/when we can get all the library packages we depend on to have static versions,
···4753 "--enable-c-opt=${optimizationSetting}"
4854 "--enable-c-opt-rts=-O2"
4955 "--enable-gcc-opts"
5656+ "--enable-trust-c-tco"
5057 "--enable-shared"
5158 "--enable-absolute-shared-libs" # Yes, NixOS will want an absolute path, and fix it.
5259 "--enable-openssl"
···7077 # "--enable-char-size=1" # default is 4
7178 # "--enable-march=native" # Nope, makes it not work on machines older than the builder
7279 ] ++ gambit-params.extraOptions
8080+ # TODO: pick an appropriate architecture to optimize on on x86-64?
8181+ # https://gcc.gnu.org/onlinedocs/gcc-4.8.4/gcc/i386-and-x86-64-Options.html#i386-and-x86-64-Options
8282+ # ++ lib.optional pkgs.stdenv.isx86_64 "--enable-march=core-avx2"
7383 # Do not enable poll on darwin due to https://github.com/gambit/gambit/issues/498
7484 ++ lib.optional (!gccStdenv.isDarwin) "--enable-poll";
7585
···180180@@ -1,10 +1,10 @@
181181 #!/bin/sh
182182183183- if command -v gtk-update-icon-cache >/dev/null && test -d "$1/exports/share/icons/hicolor"; then
183183+-if command -v gtk-update-icon-cache >/dev/null && test -d "$1/exports/share/icons/hicolor"; then
184184- cp /usr/share/icons/hicolor/index.theme "$1/exports/share/icons/hicolor/"
185185-+ cp @hicolorIconTheme@/share/icons/hicolor/index.theme "$1/exports/share/icons/hicolor/"
185185++if test -d "$1/exports/share/icons/hicolor"; then
186186++ @coreutils@/bin/cp -f @hicolorIconTheme@/share/icons/hicolor/index.theme "$1/exports/share/icons/hicolor/"
186187 for dir in "$1"/exports/share/icons/*; do
187188 if test -f "$dir/index.theme"; then
188189- if ! gtk-update-icon-cache --quiet "$dir"; then
190190+- echo "Failed to run gtk-update-icon-cache for $dir"
189191+ if ! @gtk3@/bin/gtk-update-icon-cache --quiet "$dir"; then
190190- echo "Failed to run gtk-update-icon-cache for $dir"
192192++ @coreutils@/bin/echo "Failed to run gtk-update-icon-cache for $dir"
191193 exit 1
192194 fi
193195diff --git a/triggers/mime-database.trigger b/triggers/mime-database.trigger
···3838 buildHashes = builtins.fromJSON (builtins.readFile ./hashes.json);
39394040 # our version of buck2; this should be a git tag
4141- version = "2023-10-01";
4141+ version = "2023-10-15";
42424343 # the platform-specific, statically linked binary — which is also
4444 # zstd-compressed
···6363 # tooling
6464 prelude-src =
6565 let
6666- prelude-hash = "75aa81a92edd2bf477538f9a3f0fe6a47e811842";
6666+ prelude-hash = "880be565178cf1e08ce9badef52b215f91e48479";
6767 name = "buck2-prelude-${version}.tar.gz";
6868 hash = buildHashes."_prelude";
6969 url = "https://github.com/facebook/buck2-prelude/archive/${prelude-hash}.tar.gz";
···11-{ fetchurl, lib, stdenv, SDL, SDL_image, SDL_mixer, SDL_ttf, guile, gettext }:
22-33-stdenv.mkDerivation rec {
44- pname = "ballandpaddle";
55- version = "0.8.1";
66-77- src = fetchurl {
88- url = "mirror://gnu/ballandpaddle/ballandpaddle-${version}.tar.gz";
99- sha256 = "0zgpydad0mj7fbkippw3n9hlda6nac084dq5xfbsks9jn1xd30ny";
1010- };
1111-1212- buildInputs = [ SDL SDL_image SDL_mixer SDL_ttf guile gettext ];
1313-1414- patches = [ ./getenv-decl.patch ];
1515-1616- preConfigure = ''
1717- sed -i "Makefile.in" \
1818- -e "s|desktopdir *=.*$|desktopdir = $out/share/applications|g ;
1919- s|pixmapsdir *=.*$|pixmapsdir = $out/share/pixmaps|g"
2020- '';
2121-2222- meta = {
2323- description = "GNU Ball and Paddle, an old-fashioned ball and paddle game";
2424-2525- longDescription = ''
2626- GNU Ball and Paddle is an old-fashioned ball and paddle game
2727- with a set amount of blocks to destroy on each level, while
2828- moving a paddle left and right at the bottom of the
2929- screen. Various powerups may make different things occur.
3030-3131- It now uses GNU Guile for extension and the levels are written
3232- with Guile. Follow the example level sets and the documentation.
3333- '';
3434-3535- license = lib.licenses.gpl3Plus;
3636-3737- homepage = "https://www.gnu.org/software/ballandpaddle/";
3838-3939- maintainers = [ ];
4040-4141- platforms = lib.platforms.unix;
4242-4343- hydraPlatforms = lib.platforms.linux; # sdl-config times out on darwin
4444- };
4545-}
-13
pkgs/games/ball-and-paddle/getenv-decl.patch
···11-Make the getenv(3) declaration visible.
22-33---- ballandpaddle-0.8.1/src/settingsmanager.cpp 2009-07-08 02:13:16.000000000 +0200
44-+++ ballandpaddle-0.8.1/src/settingsmanager.cpp 2009-07-16 23:30:28.000000000 +0200
55-@@ -17,6 +17,7 @@
66- * along with this program. If not, see <http://www.gnu.org/licenses/>.
77- **/
88-99-+#include <stdlib.h>
1010- #include "settingsmanager.h"
1111-1212- SettingsManager::SettingsManager ()
1313-
···11+{ lib
22+, buildGoModule
33+, fetchFromGitHub
44+}:
55+66+buildGoModule rec {
77+ pname = "google-cloud-bigtable-tool";
88+ version = "0.12.0";
99+1010+ src = fetchFromGitHub {
1111+ owner = "googleapis";
1212+ repo = "cloud-bigtable-cbt-cli";
1313+ rev = "v.${version}";
1414+ hash = "sha256-N5nbWMj7kLIdRiwBUWFz4Rat88Wx01i3hceMxAvSjaA=";
1515+ };
1616+1717+ vendorHash = "sha256-kwvEfvHs6XF84bB3Ss1307OjId0nh/0Imih1fRFdY0M=";
1818+1919+ preCheck = ''
2020+ buildFlagsArray+="-short"
2121+ '';
2222+2323+ meta = with lib; {
2424+ description = "Google Cloud Bigtable Tool";
2525+ longDescription = ''
2626+ `cbt` is the Google Cloud Bigtable Tool. A CLI utility to interact with Google Cloud Bigtable.
2727+ The cbt CLI is a command-line interface for performing several different operations on Cloud Bigtable.
2828+ It is written in Go using the Go client library for Cloud Bigtable.
2929+ An overview of its usage can be found in the [Google Cloud docs](https://cloud.google.com/bigtable/docs/cbt-overview).
3030+ For information about Bigtable in general, see the [overview of Bigtable](https://cloud.google.com/bigtable/docs/overview).
3131+ '';
3232+ homepage = "https://github.com/googleapis/cloud-bigtable-cbt-cli";
3333+ license = licenses.asl20;
3434+ maintainers = with maintainers; [ totoroot ];
3535+ mainProgram = "cbt";
3636+ };
3737+}
···11+{ lib
22+, buildGoModule
33+, fetchFromGitHub
44+}:
55+66+buildGoModule rec {
77+ pname = "google-cloud-sql-proxy";
88+ version = "2.7.0";
99+1010+ src = fetchFromGitHub {
1111+ owner = "GoogleCloudPlatform";
1212+ repo = "cloud-sql-proxy";
1313+ rev = "v${version}";
1414+ hash = "sha256-4PB9Eaqb8teF+gmiHD2VAIFnxqiK2Nb0u+xSNAM8iMs=";
1515+ };
1616+1717+ subPackages = [ "." ];
1818+1919+ vendorHash = "sha256-LaI7IdSyB7ETTjqIcIPDf3noEbvwlN3+KqrkSm8B6m8=";
2020+2121+ preCheck = ''
2222+ buildFlagsArray+="-short"
2323+ '';
2424+2525+ meta = with lib; {
2626+ description = "Utility for ensuring secure connections to Google Cloud SQL instances";
2727+ longDescription = ''
2828+ The Cloud SQL Auth Proxy is a utility for ensuring secure connections to your Cloud SQL instances.
2929+ It provides IAM authorization, allowing you to control who can connect to your instance through IAM permissions,
3030+ and TLS 1.3 encryption, without having to manage certificates.
3131+ See the [Connecting Overview](https://cloud.google.com/sql/docs/mysql/connect-overview) page for more information
3232+ on connecting to a Cloud SQL instance, or the [About the Proxy](https://cloud.google.com/sql/docs/mysql/sql-proxy)
3333+ page for details on how the Cloud SQL Proxy works.
3434+ '';
3535+ homepage = "https://github.com/GoogleCloudPlatform/cloud-sql-proxy";
3636+ license = licenses.asl20;
3737+ maintainers = with maintainers; [ nicknovitski totoroot ];
3838+ mainProgram = "cloud-sql-proxy";
3939+ };
4040+}
···11-{ fetchurl, lib, stdenv, parted, libuuid, gettext, guile }:
11+{ lib
22+, stdenv
33+, fetchurl
44+, gettext
55+, guile
66+, libuuid
77+, parted
88+}:
29310stdenv.mkDerivation rec {
411 pname = "gnufdisk";
55- version = "2.0.0a"; # .0a1 seems broken, see https://lists.gnu.org/archive/html/bug-fdisk/2012-09/msg00000.html
1212+ version = "2.0.0a1";
613714 src = fetchurl {
815 url = "mirror://gnu/fdisk/gnufdisk-${version}.tar.gz";
99- sha256 = "04nd7civ561x2lwcmxhsqbprml3178jfc58fy1v7hzqg5k4nbhy3";
1616+ hash = "sha256-yWPYTf8RxBIQ//mUdC6fkKct/csEgbzEtTAiPtNRH7U=";
1017 };
11181212- buildInputs = [ parted libuuid gettext guile ];
1919+ postPatch = ''
2020+ sed -i "s/gnufdisk-common.h .*/\n/g" backend/configure
2121+ '';
2222+2323+ strictDeps = true;
2424+2525+ nativeBuildInputs = [
2626+ gettext
2727+ guile
2828+ ];
2929+3030+ buildInputs = [
3131+ guile
3232+ libuuid
3333+ parted
3434+ ];
3535+3636+ env.NIX_CFLAGS_COMPILE = lib.concatStringsSep " " [
3737+ "-I../common/include"
3838+ "-I../debug/include"
3939+ "-I../exception/include"
4040+ ];
13411442 doCheck = true;
15431644 meta = {
1745 description = "A command-line disk partitioning tool";
1818-1946 longDescription = ''
2020- GNU fdisk provides alternatives to util-linux fdisk and util-linux
2121- cfdisk. It uses GNU Parted.
4747+ GNU fdisk provides a GNU version of the common disk partitioning tool
4848+ fdisk. fdisk is used for the creation and manipulation of disk partition
4949+ tables, and it understands a variety of different formats.
2250 '';
2323-2424- license = lib.licenses.gpl3Plus;
2525-2651 homepage = "https://www.gnu.org/software/fdisk/";
2727-5252+ license = lib.licenses.gpl3Plus;
5353+ mainProgram = "gnufdisk";
5454+ maintainers = [ lib.maintainers.wegank ];
2855 platforms = lib.platforms.linux;
2956 };
3057}
+7
pkgs/top-level/aliases.nix
···83838484 badtouch = authoscope; # Project was renamed, added 20210626
8585 baget = throw "'baget' has been removed due to being unmaintained";
8686+ ballAndPaddle = throw "'ballAndPaddle' has been removed because it was broken and abandoned upstream"; # Added 2023-10-16
8687 bashInteractive_5 = bashInteractive; # Added 2021-08-20
8788 bash_5 = bash; # Added 2021-08-20
8889 bazel_3 = throw "bazel 3 is past end of life as it is not an lts version"; # Added 2023-02-02
8990 bedup = throw "bedup was removed because it was broken and abandoned upstream"; # added 2023-02-04
9091 bird2 = bird; # Added 2022-02-21
9292+ bitwig-studio1 = throw "bitwig-studio1 has been removed, you can upgrade to 'bitwig-studio'"; # Added 2023-01-03
9393+ bitwig-studio2 = throw "bitwig-studio2 has been removed, you can upgrade to 'bitwig-studio'"; # Added 2023-01-03
9194 ddclient = throw "ddclient has been removed on the request of the upstream maintainer because it is unmaintained and has bugs. Please switch to a different software like `inadyn` or `knsupdate`."; # Added 2023-07-04
9295 bluezFull = throw "'bluezFull' has been renamed to/replaced by 'bluez'"; # Converted to throw 2023-09-10
9396 boost168 = throw "boost168 has been deprecated in favor of the latest version"; # Added 2023-06-08
···163166164167 ### D ###
165168169169+ dagger = throw "'dagger' has been removed from nixpkgs, as the trademark policy of the upstream project is incompatible"; # Added 2023-10-16
166170 dart_stable = dart; # Added 2020-01-15
167171 dat = nodePackages.dat;
168172 deadpixi-sam = deadpixi-sam-unstable;
···329333 gr-rds = throw "'gr-rds' has been renamed to/replaced by 'gnuradio3_7.pkgs.rds'"; # Converted to throw 2023-09-10
330334 grub2_full = grub2; # Added 2022-11-18
331335 grub = throw "grub1 was removed after not being maintained upstream for a decade. Please switch to another bootloader"; # Added 2023-04-11
336336+ guile-lint = throw "'guile-lint' has been removed, please use 'guild lint' instead"; # Added 2023-10-16
332337333338 ### H ###
334339···452457 libwnck3 = libwnck;
453458 libyamlcpp = yaml-cpp; # Added 2023-01-29
454459 libyamlcpp_0_3 = yaml-cpp_0_3; # Added 2023-01-29
460460+ libxkbcommon_7 = throw "libxkbcommon_7 has been removed because it is impacted by security issues and not used in nixpkgs, move to 'libxkbcommon'"; # Added 2023-01-03
455461 lightdm_gtk_greeter = lightdm-gtk-greeter; # Added 2022-08-01
456462 llama = walk; # Added 2023-01-23
457463···793799 shhgit = throw "shhgit is broken and is no longer maintained. See https://github.com/eth0izzle/shhgit#-shhgit-is-no-longer-maintained-" ; # Added 2023-08-08
794800 shipyard = jumppad; # Added 2023-06-06
795801 signumone-ks = throw "signumone-ks has been removed from nixpkgs because the developers stopped offering the binaries"; # Added 2023-08-17
802802+ simplenote = throw "'simplenote' has been removed because it is no longer maintained and insecure"; # Added 2023-10-09
796803 slack-dark = slack; # Added 2020-03-27
797804 slmenu = throw "slmenu has been removed (upstream is gone)"; # Added 2023-04-06
798805 slurm-llnl = slurm; # renamed July 2017