0
0
Fork 0
mirror of https://github.com/NixOS/nixpkgs.git synced 2025-07-14 06:00:33 +03:00

nixos/bootspec: adopt the merged RFC-0125

This removes the feature preview warning, enable by default bootspec,
adds a validation flag to prevent Go to go into build-time closure.

This will break all downstream users of bootspec as those changes are
not backward-compatible.
This commit is contained in:
Raito Bezarius 2023-03-18 20:42:09 +01:00 committed by Cole Helbling
parent b76b960e2e
commit bc502d0a14
5 changed files with 49 additions and 39 deletions

View file

@ -28,6 +28,8 @@ In addition to numerous new and upgraded packages, this release has the followin
- `libxcrypt`, the library providing the `crypt(3)` password hashing function, is now built without support for algorithms not flagged [`strong`](https://github.com/besser82/libxcrypt/blob/v4.4.33/lib/hashes.conf#L48). This affects the availability of password hashing algorithms used for system login (`login(1)`, `passwd(1)`), but also Apache2 Basic-Auth, Samba, OpenLDAP, Dovecot, and [many other packages](https://github.com/search?q=repo%3ANixOS%2Fnixpkgs%20libxcrypt&type=code). - `libxcrypt`, the library providing the `crypt(3)` password hashing function, is now built without support for algorithms not flagged [`strong`](https://github.com/besser82/libxcrypt/blob/v4.4.33/lib/hashes.conf#L48). This affects the availability of password hashing algorithms used for system login (`login(1)`, `passwd(1)`), but also Apache2 Basic-Auth, Samba, OpenLDAP, Dovecot, and [many other packages](https://github.com/search?q=repo%3ANixOS%2Fnixpkgs%20libxcrypt&type=code).
- `boot.bootspec.enable` (internal option) is now enabled by default because [RFC-0125](https://github.com/NixOS/rfcs/pull/125) was merged. This means you will have a bootspec document called `boot.json` generated for each system and specialisation in the top-level. This is useful to enable advanced boot usecases in NixOS such as SecureBoot.
## New Services {#sec-release-23.05-new-services} ## New Services {#sec-release-23.05-new-services}
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. --> <!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->

View file

@ -1,4 +1,6 @@
#V1: { import "struct"
#BootspecV1: {
system: string system: string
init: string init: string
initrd?: string initrd?: string
@ -7,12 +9,23 @@
kernelParams: [...string] kernelParams: [...string]
label: string label: string
toplevel: string toplevel: string
specialisation?: {
[=~"^"]: #V1
}
extensions?: {...}
} }
Document: { // A restricted document does not allow any official specialisation
v1: #V1 // information in it to avoid "recursive specialisations".
#RestrictedDocument: struct.MinFields(1) & {
"org.nixos.bootspec.v1": #BootspecV1
[=~"^"]: #BootspecExtension
}
// Specialisations are a hashmap of strings
#BootspecSpecialisationV1: [string]: #RestrictedDocument
// Bootspec extensions are defined by the extension author.
#BootspecExtension: {...}
// A "full" document allows official specialisation information
// in the top-level with a reserved namespaced key.
Document: #RestrictedDocument & {
"org.nixos.specialisation.v1"?: #BootspecSpecialisationV1
} }

View file

@ -16,20 +16,20 @@ let
filename = "boot.json"; filename = "boot.json";
json = json =
pkgs.writeText filename pkgs.writeText filename
(builtins.toJSON (builtins.toJSON
# Merge extensions first to not let them shadow NixOS bootspec data.
(cfg.extensions //
{ {
v1 = { "org.nixos.bootspec.v1" = {
system = config.boot.kernelPackages.stdenv.hostPlatform.system; system = config.boot.kernelPackages.stdenv.hostPlatform.system;
kernel = "${config.boot.kernelPackages.kernel}/${config.system.boot.loader.kernelFile}"; kernel = "${config.boot.kernelPackages.kernel}/${config.system.boot.loader.kernelFile}";
kernelParams = config.boot.kernelParams; kernelParams = config.boot.kernelParams;
label = "${config.system.nixos.distroName} ${config.system.nixos.codeName} ${config.system.nixos.label} (Linux ${config.boot.kernelPackages.kernel.modDirVersion})"; label = "${config.system.nixos.distroName} ${config.system.nixos.codeName} ${config.system.nixos.label} (Linux ${config.boot.kernelPackages.kernel.modDirVersion})";
inherit (cfg) extensions;
} // lib.optionalAttrs config.boot.initrd.enable { } // lib.optionalAttrs config.boot.initrd.enable {
initrd = "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}"; initrd = "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}";
initrdSecrets = "${config.system.build.initialRamdiskSecretAppender}/bin/append-initrd-secrets"; initrdSecrets = "${config.system.build.initialRamdiskSecretAppender}/bin/append-initrd-secrets";
}; };
}); }));
generator = generator =
let let
@ -42,8 +42,8 @@ let
toplevelInjector = lib.escapeShellArgs [ toplevelInjector = lib.escapeShellArgs [
"${pkgs.jq}/bin/jq" "${pkgs.jq}/bin/jq"
'' ''
.v1.toplevel = $toplevel | ."org.nixos.bootspec.v1".toplevel = $toplevel |
.v1.init = $init ."org.nixos.bootspec.v1".init = $init
'' ''
"--sort-keys" "--sort-keys"
"--arg" "toplevel" "${placeholder "out"}" "--arg" "toplevel" "${placeholder "out"}"
@ -62,14 +62,10 @@ let
lib.escapeShellArgs [ lib.escapeShellArgs [
"${pkgs.jq}/bin/jq" "${pkgs.jq}/bin/jq"
"--sort-keys" "--sort-keys"
".v1.specialisation = ($ARGS.named | map_values(. | first | .v1))" ''."org.nixos.specialisation.v1" = ($ARGS.named | map_values(. | first))''
] + " ${lib.concatStringsSep " " specialisationLoader}"; ] + " ${lib.concatStringsSep " " specialisationLoader}";
in in
'' "${toplevelInjector} | ${specialisationInjector} > $out/${filename}";
mkdir -p $out/bootspec
${toplevelInjector} | ${specialisationInjector} > $out/${filename}
'';
validator = pkgs.writeCueValidator ./bootspec.cue { validator = pkgs.writeCueValidator ./bootspec.cue {
document = "Document"; # Universal validator for any version as long the schema is correctly set. document = "Document"; # Universal validator for any version as long the schema is correctly set.
@ -79,10 +75,17 @@ let
in in
{ {
options.boot.bootspec = { options.boot.bootspec = {
enable = lib.mkEnableOption (lib.mdDoc "Enable generation of RFC-0125 bootspec in $system/bootspec, e.g. /run/current-system/bootspec"); enable = lib.mkEnableOption (lib.mdDoc "the generation of RFC-0125 bootspec in $system/boot.json, e.g. /run/current-system/boot.json")
// { default = true; internal = true; };
enableValidation = lib.mkEnableOption (lib.mdDoc ''the validation of bootspec documents for each build.
This will introduce Go in the build-time closure as we are relying on [Cuelang](https://cuelang.org/) for schema validation.
Enable this option if you want to ascertain that your documents are correct.
''
);
extensions = lib.mkOption { extensions = lib.mkOption {
type = lib.types.attrsOf lib.types.attrs; # <namespace>: { ...namespace-specific fields } # NOTE(RaitoBezarius): this is not enough to validate: extensions."osRelease" = drv; those are picked up by cue validation.
type = lib.types.attrsOf lib.types.anything; # <namespace>: { ...namespace-specific fields }
default = { }; default = { };
description = lib.mdDoc '' description = lib.mdDoc ''
User-defined data that extends the bootspec document. User-defined data that extends the bootspec document.
@ -112,15 +115,4 @@ in
default = schemas.v1.filename; default = schemas.v1.filename;
}; };
}; };
config = lib.mkIf (cfg.enable) {
warnings = [
''RFC-0125 is not merged yet, this is a feature preview of bootspec.
The schema is not definitive and features are not guaranteed to be stable until RFC-0125 is merged.
See:
- https://github.com/NixOS/nixpkgs/pull/172237 to track merge status in nixpkgs.
- https://github.com/NixOS/rfcs/pull/125 to track RFC status.
''
];
};
} }

View file

@ -82,7 +82,8 @@ let
${optionalString (!config.boot.isContainer && config.boot.bootspec.enable) '' ${optionalString (!config.boot.isContainer && config.boot.bootspec.enable) ''
${config.boot.bootspec.writer} ${config.boot.bootspec.writer}
${config.boot.bootspec.validator} "$out/${config.boot.bootspec.filename}" ${optionalString config.boot.bootspec.enableValidation
''${config.boot.bootspec.validator} "$out/${config.boot.bootspec.filename}"''}
''} ''}
${config.system.extraSystemBuilderCmds} ${config.system.extraSystemBuilderCmds}

View file

@ -110,7 +110,7 @@ in
machine.succeed("test -e /run/current-system/boot.json") machine.succeed("test -e /run/current-system/boot.json")
bootspec = json.loads(machine.succeed("jq -r '.v1' /run/current-system/boot.json")) bootspec = json.loads(machine.succeed("jq -r '.\"org.nixos.bootspec.v1\"' /run/current-system/boot.json"))
assert all(key in bootspec for key in ('initrd', 'initrdSecrets')), "Bootspec should contain initrd or initrdSecrets field when initrd is enabled" assert all(key in bootspec for key in ('initrd', 'initrdSecrets')), "Bootspec should contain initrd or initrdSecrets field when initrd is enabled"
''; '';
@ -136,10 +136,10 @@ in
machine.succeed("test -e /run/current-system/boot.json") machine.succeed("test -e /run/current-system/boot.json")
machine.succeed("test -e /run/current-system/specialisation/something/boot.json") machine.succeed("test -e /run/current-system/specialisation/something/boot.json")
sp_in_parent = json.loads(machine.succeed("jq -r '.v1.specialisation.something' /run/current-system/boot.json")) sp_in_parent = json.loads(machine.succeed("jq -r '.\"org.nixos.specialisation.v1\".something' /run/current-system/boot.json"))
sp_in_fs = json.loads(machine.succeed("cat /run/current-system/specialisation/something/boot.json")) sp_in_fs = json.loads(machine.succeed("cat /run/current-system/specialisation/something/boot.json"))
assert sp_in_parent == sp_in_fs['v1'], "Bootspecs of the same specialisation are different!" assert sp_in_parent['org.nixos.bootspec.v1'] == sp_in_fs['org.nixos.bootspec.v1'], "Bootspecs of the same specialisation are different!"
''; '';
}; };
@ -152,7 +152,9 @@ in
imports = [ standard ]; imports = [ standard ];
environment.systemPackages = [ pkgs.jq ]; environment.systemPackages = [ pkgs.jq ];
boot.bootspec.extensions = { boot.bootspec.extensions = {
osRelease = config.environment.etc."os-release".source; "org.nix-tests.product" = {
osRelease = config.environment.etc."os-release".source;
};
}; };
}; };
@ -161,7 +163,7 @@ in
machine.wait_for_unit("multi-user.target") machine.wait_for_unit("multi-user.target")
current_os_release = machine.succeed("cat /etc/os-release") current_os_release = machine.succeed("cat /etc/os-release")
bootspec_os_release = machine.succeed("cat $(jq -r '.v1.extensions.osRelease' /run/current-system/boot.json)") bootspec_os_release = machine.succeed("cat $(jq -r '.\"org.nix-tests.product\".osRelease' /run/current-system/boot.json)")
assert current_os_release == bootspec_os_release, "Filename referenced by extension has unexpected contents" assert current_os_release == bootspec_os_release, "Filename referenced by extension has unexpected contents"
''; '';