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";