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:
parent
b76b960e2e
commit
bc502d0a14
5 changed files with 49 additions and 39 deletions
|
@ -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. -->
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
|
||||||
''
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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"
|
||||||
'';
|
'';
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue