formats: add nixConf

adds `nixConf` (to generate `nix.conf` files) as a file format to
`lib.formats`, and uses it for serializing `nix.settings`.

this makes it easier to 'manually' serialize `nix.settings`, which is
relevant in e.g. safely handling sensitive values such as that of
`nix.settings.access-tokens`.

Signed-off-by: cinereal <cinereal@riseup.net>
This commit is contained in:
cinereal
2025-09-06 13:25:52 +02:00
parent 44db9c3ace
commit c30b9ec953
3 changed files with 140 additions and 88 deletions
+11 -87
View File
@@ -16,40 +16,21 @@
let
inherit (lib)
concatStringsSep
boolToString
escape
filterAttrs
floatToString
getVersion
hasPrefix
isBool
isDerivation
isFloat
isInt
isList
isString
literalExpression
mapAttrsToList
mkAfter
mkIf
mkOption
mkRenamedOptionModuleWith
optionalString
optionals
strings
systems
toPretty
types
versionAtLeast
;
cfg = config.nix;
nixPackage = cfg.package.out;
isNixAtLeast = versionAtLeast (getVersion nixPackage);
defaultSystemFeatures = [
"nixos-test"
"benchmark"
@@ -98,74 +79,17 @@ let
attrsOf (either confAtom (listOf confAtom));
nixConf =
assert isNixAtLeast "2.2";
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);
isExtra = key: hasPrefix "extra-" key;
in
pkgs.writeTextFile {
name = "nix.conf";
# workaround for https://github.com/NixOS/nix/issues/9487
# extra-* settings must come after their non-extra counterpart
text = ''
# WARNING: this file is generated from the nix.* options in
# your NixOS configuration, typically
# /etc/nixos/configuration.nix. Do not edit it!
${mkKeyValuePairs (filterAttrs (key: value: !(isExtra key)) cfg.settings)}
${mkKeyValuePairs (filterAttrs (key: value: isExtra key) cfg.settings)}
${cfg.extraOptions}
'';
checkPhase = lib.optionalString cfg.checkConfig (
if pkgs.stdenv.hostPlatform != pkgs.stdenv.buildPlatform then
''
echo "Ignoring validation for cross-compilation"
''
else
let
showCommand = if isNixAtLeast "2.20pre" then "config show" else "show-config";
in
''
echo "Validating generated nix.conf"
ln -s $out ./nix.conf
set -e
set +o pipefail
NIX_CONF_DIR=$PWD \
${cfg.package}/bin/nix ${showCommand} ${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
''
);
};
(pkgs.formats.nixConf {
inherit (cfg)
package
checkAllErrors
checkConfig
extraOptions
;
inherit (nixPackage) version;
}).generate
"nix.conf"
cfg.settings;
in
{
+104 -1
View File
@@ -1,11 +1,16 @@
{ lib, pkgs }:
let
inherit (lib)
boolToString
concatStringsSep
escape
filterAttrs
flatten
hasPrefix
id
isAttrs
isBool
isDerivation
isFloat
isInt
isList
@@ -16,8 +21,11 @@ let
optionalAttrs
optionalString
pipe
types
singleton
strings
toPretty
types
versionAtLeast
warn
;
@@ -863,6 +871,101 @@ optionalAttrs allowAliases aliases
lib.mkRaw = lib.mkLuaInline;
};
nixConf =
{
package,
version,
extraOptions ? "",
checkAllErrors ? true,
checkConfig ? true,
}:
let
isNixAtLeast = versionAtLeast version;
in
assert isNixAtLeast "2.2";
{
type =
let
atomType = nullOr (oneOf [
bool
int
float
str
path
package
]);
in
attrsOf atomType;
generate =
name: value:
let
# note that list type has been omitted here as the separator varies, see `nix.settings.*`
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
strings.floatToString 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);
isExtra = key: hasPrefix "extra-" key;
in
pkgs.writeTextFile {
inherit name;
# workaround for https://github.com/NixOS/nix/issues/9487
# extra-* settings must come after their non-extra counterpart
text = ''
# WARNING: this file is generated from the nix.* options in
# your NixOS configuration, typically
# /etc/nixos/configuration.nix. Do not edit it!
${mkKeyValuePairs (filterAttrs (key: _: !(isExtra key)) value)}
${mkKeyValuePairs (filterAttrs (key: _: isExtra key) value)}
${extraOptions}
'';
checkPhase = lib.optionalString checkConfig (
if pkgs.stdenv.hostPlatform != pkgs.stdenv.buildPlatform then
''
echo "Ignoring validation for cross-compilation"
''
else
let
showCommand = if isNixAtLeast "2.20pre" then "config show" else "show-config";
in
''
echo "Validating generated nix.conf"
ln -s $out ./nix.conf
set -e
set +o pipefail
NIX_CONF_DIR=$PWD \
${package}/bin/nix ${showCommand} ${optionalString (isNixAtLeast "2.3pre") "--no-net"} \
${optionalString (isNixAtLeast "2.4pre") "--option experimental-features nix-command"} \
|& sed -e 's/^warning:/error:/' \
| (! grep '${if checkAllErrors then "^error:" else "^error: unknown setting"}')
set -o pipefail
''
);
};
};
# Outputs a succession of Python variable assignments
# Useful for many Django-based services
pythonVars =
+25
View File
@@ -850,6 +850,31 @@ runBuildTests {
'';
};
nixConfAtoms = shouldPass {
format = formats.nixConf {
package = pkgs.nix;
version = pkgs.nix.version;
extraOptions = ''ignore-try = false'';
};
input = {
auto-optimise-store = true;
cores = 0;
store = "auto";
};
# note that null type is hard to test here,
# as it involves a trailing space our formatter will remove here
expected = ''
# WARNING: this file is generated from the nix.* options in
# your NixOS configuration, typically
# /etc/nixos/configuration.nix. Do not edit it!
auto-optimise-store = true
cores = 0
store = auto
ignore-try = false
'';
};
phpAtoms = shouldPass rec {
format = formats.php { finalVariable = "config"; };
input = {