diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2441829..3ba880a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,15 @@
* New options `networking.hosts`, `networking.hostFiles` and
`networking.extraHosts` for `/etc/hosts` configuration.
+* Add option `nix.settings` to support
+ [structural `settings`](https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md)
+ for `nix.conf`.
+ `nix.substituters` and `nix.trustedPublicKeys` are now aliases of
+ `nix.settings.substituters` and `nix.settings.trusted-public-keys`,
+ respectively.
+ Nix Flakes functionality can now be enabled with
+ `nix.settings.experimental-features = [ "nix-command" "flakes" ];`
+
## Release 23.05
### New Options
diff --git a/modules/environment/login/nix-on-droid.nix.default b/modules/environment/login/nix-on-droid.nix.default
index 2ae962a..91db76f 100644
--- a/modules/environment/login/nix-on-droid.nix.default
+++ b/modules/environment/login/nix-on-droid.nix.default
@@ -31,9 +31,7 @@
system.stateVersion = "23.05";
# Set up nix for flakes
- #nix.extraOptions = ''
- # experimental-features = nix-command flakes
- #'';
+ #nix.settings.experimental-features = [ "nix-command" "flakes" ];
# Set your time zone
#time.timeZone = "Europe/Berlin";
diff --git a/modules/environment/nix.nix b/modules/environment/nix.nix
index c5295a9..a70c923 100644
--- a/modules/environment/nix.nix
+++ b/modules/environment/nix.nix
@@ -2,8 +2,11 @@
# Based on
# https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/misc/nix-daemon.nix
-# (Copyright (c) 2003-2022 Eelco Dolstra and the Nixpkgs/NixOS contributors,
-# licensed under MIT License as well)
+# (Copyright (c) 2003-2023 Eelco Dolstra and the Nixpkgs/NixOS contributors)
+# and
+# https://github.com/nix-community/home-manager/blob/master/modules/misc/nix.nix
+# (Copyright (c) 2017-2023 Home Manager contributors)
+# both licensed under MIT License as well)
{ config, lib, pkgs, ... }:
@@ -11,8 +14,81 @@ with lib;
let
cfg = config.nix;
+
renameNixOpt = old: new:
(mkRenamedOptionModule [ "nix" old ] [ "nix" new ]);
+
+ isNixAtLeast = versionAtLeast (getVersion cfg.package);
+
+ nixConf =
+ let
+
+ mkValueString = v:
+ if v == null then ""
+ else if isInt v then toString v
+ else if isBool v then boolToString v
+ else if isFloat v then floatToString v
+ else if isList v then toString v
+ else if isDerivation v then toString v
+ else if builtins.isPath v then toString v
+ else if isString v then v
+ else if strings.isConvertibleWithToString v then toString v
+ else abort "The nix conf value: ${toPretty {} v} can not be encoded";
+
+ mkKeyValue = k: v: "${escape [ "=" ] k} = ${mkValueString v}";
+
+ mkKeyValuePairs = attrs: concatStringsSep "\n" (mapAttrsToList mkKeyValue attrs);
+
+ in
+ pkgs.writeTextFile {
+ name = "nix.conf";
+ text = ''
+ # WARNING: this file is generated from the nix.* options in
+ # your NixOS configuration, typically
+ # /etc/nixos/configuration.nix. Do not edit it!
+ ${mkKeyValuePairs cfg.settings}
+ ${cfg.extraOptions}
+ '';
+ checkPhase = lib.optionalString cfg.checkConfig (
+ if pkgs.stdenv.hostPlatform != pkgs.stdenv.buildPlatform then ''
+ echo "Ignoring validation for cross-compilation"
+ ''
+ else ''
+ echo "Validating generated nix.conf"
+ ln -s $out ./nix.conf
+ set -e
+ set +o pipefail
+ NIX_CONF_DIR=$PWD \
+ ${cfg.package}/bin/nix show-config ${optionalString (isNixAtLeast "2.3pre") "--no-net"} \
+ ${optionalString (isNixAtLeast "2.4pre") "--option experimental-features nix-command"} \
+ |& sed -e 's/^warning:/error:/' \
+ | (! grep '${if cfg.checkAllErrors then "^error:" else "^error: unknown setting"}')
+ set -o pipefail
+ ''
+ );
+ };
+
+ legacyConfMappings = {
+ substituters = "substituters";
+ trustedPublicKeys = "trusted-public-keys";
+ };
+
+ semanticConfType = with types;
+ let
+ confAtom = nullOr
+ (oneOf [
+ bool
+ int
+ float
+ str
+ path
+ package
+ ]) // {
+ description = "Nix config atom (null, bool, int, float, str, path or package)";
+ };
+ in
+ attrsOf (either confAtom (listOf confAtom));
+
in
{
@@ -21,7 +97,7 @@ in
(renameNixOpt "binaryCaches" "substituters")
(renameNixOpt "binaryCachePublicKeys" "trustedPublicKeys")
(renameNixOpt "extraConfig" "extraOptions")
- ];
+ ] ++ mapAttrsToList (oldConf: newConf: mkRenamedOptionModule [ "nix" oldConf ] [ "nix" "settings" newConf ]) legacyConfMappings;
###### interface
@@ -104,30 +180,72 @@ in
description = "A system-wide flake registry.";
};
- substituters = mkOption {
- type = types.listOf types.str;
- default = [ ];
- description = ''
- A list of URLs of substituters. The official NixOS and Nix-on-Droid
- substituters are added by default.
- '';
- };
-
- trustedPublicKeys = mkOption {
- type = types.listOf types.str;
- default = [ ];
- description = ''
- A list of public keys. When paths are copied from another Nix store (such as a
- binary cache), they must be signed with one of these keys. The official NixOS
- and Nix-on-Droid public keys are added by default.
- '';
- };
-
extraOptions = mkOption {
type = types.lines;
default = "";
description = "Extra config to be appended to /etc/nix/nix.conf.";
};
+
+ checkConfig = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ If enabled, checks that Nix can parse the generated nix.conf.
+ '';
+ };
+
+ checkAllErrors = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ If enabled, checks the nix.conf parsing for any kind of error. When disabled, checks only for unknown settings.
+ '';
+ };
+
+ settings = mkOption {
+ type = types.submodule {
+ freeformType = semanticConfType;
+
+ options = {
+ substituters = mkOption {
+ type = types.listOf types.str;
+ description = ''
+ A list of URLs of substituters. The official NixOS and Nix-on-Droid
+ substituters are added by default.
+ '';
+ };
+
+ trusted-public-keys = mkOption {
+ type = types.listOf types.str;
+ description = ''
+ A list of public keys. When paths are copied from another Nix store (such as a
+ binary cache), they must be signed with one of these keys. The official NixOS
+ and Nix-on-Droid public keys are added by default.
+ '';
+ };
+ };
+ };
+ default = { };
+ example = literalExpression ''
+ {
+ experimental-fetures = [ "nix-commnd" "flake" ];
+ }
+ '';
+ description = ''
+ Configuration for Nix, see
+ or
+
+ nix.conf
+ 5
+ for available options.
+ The value declared here will be translated directly to the key-value pairs Nix expects.
+
+
+ Nix configurations defined under will be translated and applied to this
+ option. In addition, configuration specified in will be appended
+ verbatim to the resulting config file.
+ '';
+ };
};
};
@@ -138,25 +256,20 @@ in
config = mkMerge [
{
environment.etc = {
- "nix/nix.conf".text = ''
- sandbox = false
- substituters = ${concatStringsSep " " cfg.substituters}
- trusted-public-keys = ${concatStringsSep " " cfg.trustedPublicKeys}
- ${cfg.extraOptions}
- '';
-
+ "nix/nix.conf".source = nixConf;
"nix/registry.json".text = builtins.toJSON {
version = 2;
flakes = mapAttrsToList (_n: v: { inherit (v) from to exact; }) cfg.registry;
};
};
- nix = {
+ nix.settings = {
+ sandbox = false;
substituters = [
"https://cache.nixos.org"
"https://nix-on-droid.cachix.org"
];
- trustedPublicKeys = [
+ trusted-public-keys = [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
"nix-on-droid.cachix.org-1:56snoMJTXmDRC1Ei24CmKoUqvHJ9XCp+nidK7qkMQrU="
];
diff --git a/templates/advanced/nix-on-droid.nix b/templates/advanced/nix-on-droid.nix
index 686d786..cecc07a 100644
--- a/templates/advanced/nix-on-droid.nix
+++ b/templates/advanced/nix-on-droid.nix
@@ -31,9 +31,7 @@
system.stateVersion = "23.05";
# Set up nix for flakes
- nix.extraOptions = ''
- experimental-features = nix-command flakes
- '';
+ nix.settings.experimental-features = [ "nix-command" "flakes" ];
# Set your time zone
#time.timeZone = "Europe/Berlin";
diff --git a/templates/home-manager/nix-on-droid.nix b/templates/home-manager/nix-on-droid.nix
index 9b7d262..89ee423 100644
--- a/templates/home-manager/nix-on-droid.nix
+++ b/templates/home-manager/nix-on-droid.nix
@@ -31,9 +31,7 @@
system.stateVersion = "23.05";
# Set up nix for flakes
- nix.extraOptions = ''
- experimental-features = nix-command flakes
- '';
+ nix.settings.experimental-features = [ "nix-command" "flakes" ];
# Set your time zone
#time.timeZone = "Europe/Berlin";
diff --git a/templates/minimal/nix-on-droid.nix b/templates/minimal/nix-on-droid.nix
index b98b190..de6ed26 100644
--- a/templates/minimal/nix-on-droid.nix
+++ b/templates/minimal/nix-on-droid.nix
@@ -31,9 +31,7 @@
system.stateVersion = "23.05";
# Set up nix for flakes
- nix.extraOptions = ''
- experimental-features = nix-command flakes
- '';
+ nix.settings.experimental-features = [ "nix-command" "flakes" ];
# Set your time zone
#time.timeZone = "Europe/Berlin";