Merge pull request #172237 from DeterminateSystems/bootspec-rfc
Support external bootloader backends (RFC-0125)
This commit is contained in:
commit
668a2b2f33
14 changed files with 536 additions and 0 deletions
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
|
@ -78,6 +78,8 @@
|
|||
/nixos/doc/manual/man-nixos-option.xml @nbp
|
||||
/nixos/modules/installer/tools/nixos-option.sh @nbp
|
||||
/nixos/modules/system @dasJ
|
||||
/nixos/modules/system/activation/bootspec.nix @grahamc @cole-h @raitobezarius
|
||||
/nixos/modules/system/activation/bootspec.cue @grahamc @cole-h @raitobezarius
|
||||
|
||||
# NixOS integration test driver
|
||||
/nixos/lib/test-driver @tfc
|
||||
|
|
36
nixos/doc/manual/development/bootspec.chapter.md
Normal file
36
nixos/doc/manual/development/bootspec.chapter.md
Normal file
|
@ -0,0 +1,36 @@
|
|||
# Experimental feature: Bootspec {#sec-experimental-bootspec}
|
||||
|
||||
Bootspec is a experimental feature, introduced in the [RFC-0125 proposal](https://github.com/NixOS/rfcs/pull/125), the reference implementation can be found [there](https://github.com/NixOS/nixpkgs/pull/172237) in order to standardize bootloader support
|
||||
and advanced boot workflows such as SecureBoot and potentially more.
|
||||
|
||||
You can enable the creation of bootspec documents through [`boot.bootspec.enable = true`](options.html#opt-boot.bootspec.enable), which will prompt a warning until [RFC-0125](https://github.com/NixOS/rfcs/pull/125) is officially merged.
|
||||
|
||||
## Schema {#sec-experimental-bootspec-schema}
|
||||
|
||||
The bootspec schema is versioned and validated against [a CUE schema file](https://cuelang.org/) which should considered as the source of truth for your applications.
|
||||
|
||||
You will find the current version [here](../../../modules/system/activation/bootspec.cue).
|
||||
|
||||
## Extensions mechanism {#sec-experimental-bootspec-extensions}
|
||||
|
||||
Bootspec cannot account for all usecases.
|
||||
|
||||
For this purpose, Bootspec offers a generic extension facility [`boot.bootspec.extensions`](options.html#opt-boot.bootspec.extensions) which can be used to inject any data needed for your usecases.
|
||||
|
||||
An example for SecureBoot is to get the Nix store path to `/etc/os-release` in order to bake it into a unified kernel image:
|
||||
|
||||
```nix
|
||||
{ config, lib, ... }: {
|
||||
boot.bootspec.extensions = {
|
||||
"org.secureboot.osRelease" = config.environment.etc."os-release".source;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
To reduce incompatibility and prevent names from clashing between applications, it is **highly recommended** to use a unique namespace for your extensions.
|
||||
|
||||
## External bootloaders {#sec-experimental-bootspec-external-bootloaders}
|
||||
|
||||
It is possible to enable your own bootloader through [`boot.loader.external.installHook`](options.html#opt-boot.loader.external.installHook) which can wrap an existing bootloader.
|
||||
|
||||
Currently, there is no good story to compose existing bootloaders to enrich their features, e.g. SecureBoot, etc. It will be necessary to reimplement or reuse existing parts.
|
|
@ -12,6 +12,7 @@
|
|||
<xi:include href="../from_md/development/sources.chapter.xml" />
|
||||
<xi:include href="../from_md/development/writing-modules.chapter.xml" />
|
||||
<xi:include href="../from_md/development/building-parts.chapter.xml" />
|
||||
<xi:include href="../from_md/development/bootspec.chapter.xml" />
|
||||
<xi:include href="../from_md/development/what-happens-during-a-system-switch.chapter.xml" />
|
||||
<xi:include href="../from_md/development/writing-documentation.chapter.xml" />
|
||||
<xi:include href="../from_md/development/nixos-tests.chapter.xml" />
|
||||
|
|
73
nixos/doc/manual/from_md/development/bootspec.chapter.xml
Normal file
73
nixos/doc/manual/from_md/development/bootspec.chapter.xml
Normal file
|
@ -0,0 +1,73 @@
|
|||
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-experimental-bootspec">
|
||||
<title>Experimental feature: Bootspec</title>
|
||||
<para>
|
||||
Bootspec is a experimental feature, introduced in the
|
||||
<link xlink:href="https://github.com/NixOS/rfcs/pull/125">RFC-0125
|
||||
proposal</link>, the reference implementation can be found
|
||||
<link xlink:href="https://github.com/NixOS/nixpkgs/pull/172237">there</link>
|
||||
in order to standardize bootloader support and advanced boot
|
||||
workflows such as SecureBoot and potentially more.
|
||||
</para>
|
||||
<para>
|
||||
You can enable the creation of bootspec documents through
|
||||
<link xlink:href="options.html#opt-boot.bootspec.enable"><literal>boot.bootspec.enable = true</literal></link>,
|
||||
which will prompt a warning until
|
||||
<link xlink:href="https://github.com/NixOS/rfcs/pull/125">RFC-0125</link>
|
||||
is officially merged.
|
||||
</para>
|
||||
<section xml:id="sec-experimental-bootspec-schema">
|
||||
<title>Schema</title>
|
||||
<para>
|
||||
The bootspec schema is versioned and validated against
|
||||
<link xlink:href="https://cuelang.org/">a CUE schema file</link>
|
||||
which should considered as the source of truth for your
|
||||
applications.
|
||||
</para>
|
||||
<para>
|
||||
You will find the current version
|
||||
<link xlink:href="../../../modules/system/activation/bootspec.cue">here</link>.
|
||||
</para>
|
||||
</section>
|
||||
<section xml:id="sec-experimental-bootspec-extensions">
|
||||
<title>Extensions mechanism</title>
|
||||
<para>
|
||||
Bootspec cannot account for all usecases.
|
||||
</para>
|
||||
<para>
|
||||
For this purpose, Bootspec offers a generic extension facility
|
||||
<link xlink:href="options.html#opt-boot.bootspec.extensions"><literal>boot.bootspec.extensions</literal></link>
|
||||
which can be used to inject any data needed for your usecases.
|
||||
</para>
|
||||
<para>
|
||||
An example for SecureBoot is to get the Nix store path to
|
||||
<literal>/etc/os-release</literal> in order to bake it into a
|
||||
unified kernel image:
|
||||
</para>
|
||||
<programlisting language="bash">
|
||||
{ config, lib, ... }: {
|
||||
boot.bootspec.extensions = {
|
||||
"org.secureboot.osRelease" = config.environment.etc."os-release".source;
|
||||
};
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
To reduce incompatibility and prevent names from clashing between
|
||||
applications, it is <emphasis role="strong">highly
|
||||
recommended</emphasis> to use a unique namespace for your
|
||||
extensions.
|
||||
</para>
|
||||
</section>
|
||||
<section xml:id="sec-experimental-bootspec-external-bootloaders">
|
||||
<title>External bootloaders</title>
|
||||
<para>
|
||||
It is possible to enable your own bootloader through
|
||||
<link xlink:href="options.html#opt-boot.loader.external.installHook"><literal>boot.loader.external.installHook</literal></link>
|
||||
which can wrap an existing bootloader.
|
||||
</para>
|
||||
<para>
|
||||
Currently, there is no good story to compose existing bootloaders
|
||||
to enrich their features, e.g. SecureBoot, etc. It will be
|
||||
necessary to reimplement or reuse existing parts.
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
|
@ -1246,6 +1246,7 @@
|
|||
./services/x11/xserver.nix
|
||||
./system/activation/activation-script.nix
|
||||
./system/activation/specialisation.nix
|
||||
./system/activation/bootspec.nix
|
||||
./system/activation/top-level.nix
|
||||
./system/boot/binfmt.nix
|
||||
./system/boot/emergency-mode.nix
|
||||
|
@ -1261,6 +1262,7 @@
|
|||
./system/boot/loader/grub/grub.nix
|
||||
./system/boot/loader/grub/ipxe.nix
|
||||
./system/boot/loader/grub/memtest.nix
|
||||
./system/boot/loader/external/external.nix
|
||||
./system/boot/loader/init-script/init-script.nix
|
||||
./system/boot/loader/loader.nix
|
||||
./system/boot/loader/raspberrypi/raspberrypi.nix
|
||||
|
|
17
nixos/modules/system/activation/bootspec.cue
Normal file
17
nixos/modules/system/activation/bootspec.cue
Normal file
|
@ -0,0 +1,17 @@
|
|||
#V1: {
|
||||
init: string
|
||||
initrd?: string
|
||||
initrdSecrets?: string
|
||||
kernel: string
|
||||
kernelParams: [...string]
|
||||
label: string
|
||||
toplevel: string
|
||||
specialisation?: {
|
||||
[=~"^"]: #V1
|
||||
}
|
||||
extensions?: {...}
|
||||
}
|
||||
|
||||
Document: {
|
||||
v1: #V1
|
||||
}
|
124
nixos/modules/system/activation/bootspec.nix
Normal file
124
nixos/modules/system/activation/bootspec.nix
Normal file
|
@ -0,0 +1,124 @@
|
|||
# Note that these schemas are defined by RFC-0125.
|
||||
# This document is considered a stable API, and is depended upon by external tooling.
|
||||
# Changes to the structure of the document, or the semantics of the values should go through an RFC.
|
||||
#
|
||||
# See: https://github.com/NixOS/rfcs/pull/125
|
||||
{ config
|
||||
, pkgs
|
||||
, lib
|
||||
, ...
|
||||
}:
|
||||
let
|
||||
cfg = config.boot.bootspec;
|
||||
children = lib.mapAttrs (childName: childConfig: childConfig.configuration.system.build.toplevel) config.specialisation;
|
||||
schemas = {
|
||||
v1 = rec {
|
||||
filename = "boot.json";
|
||||
json =
|
||||
pkgs.writeText filename
|
||||
(builtins.toJSON
|
||||
{
|
||||
v1 = {
|
||||
kernel = "${config.boot.kernelPackages.kernel}/${config.system.boot.loader.kernelFile}";
|
||||
kernelParams = config.boot.kernelParams;
|
||||
initrd = "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}";
|
||||
initrdSecrets = "${config.system.build.initialRamdiskSecretAppender}/bin/append-initrd-secrets";
|
||||
label = "NixOS ${config.system.nixos.codeName} ${config.system.nixos.label} (Linux ${config.boot.kernelPackages.kernel.modDirVersion})";
|
||||
|
||||
inherit (cfg) extensions;
|
||||
};
|
||||
});
|
||||
|
||||
generator =
|
||||
let
|
||||
# NOTE: Be careful to not introduce excess newlines at the end of the
|
||||
# injectors, as that may affect the pipes and redirects.
|
||||
|
||||
# Inject toplevel and init into the bootspec.
|
||||
# This can only be done here because we *cannot* depend on $out
|
||||
# referring to the toplevel, except by living in the toplevel itself.
|
||||
toplevelInjector = lib.escapeShellArgs [
|
||||
"${pkgs.jq}/bin/jq"
|
||||
''
|
||||
.v1.toplevel = $toplevel |
|
||||
.v1.init = $init
|
||||
''
|
||||
"--sort-keys"
|
||||
"--arg" "toplevel" "${placeholder "out"}"
|
||||
"--arg" "init" "${placeholder "out"}/init"
|
||||
] + " < ${json}";
|
||||
|
||||
# We slurp all specialisations and inject them as values, such that
|
||||
# `.specialisations.${name}` embeds the specialisation's bootspec
|
||||
# document.
|
||||
specialisationInjector =
|
||||
let
|
||||
specialisationLoader = (lib.mapAttrsToList
|
||||
(childName: childToplevel: lib.escapeShellArgs [ "--slurpfile" childName "${childToplevel}/bootspec/${filename}" ])
|
||||
children);
|
||||
in
|
||||
lib.escapeShellArgs [
|
||||
"${pkgs.jq}/bin/jq"
|
||||
"--sort-keys"
|
||||
".v1.specialisation = ($ARGS.named | map_values(. | first | .v1))"
|
||||
] + " ${lib.concatStringsSep " " specialisationLoader}";
|
||||
in
|
||||
''
|
||||
mkdir -p $out/bootspec
|
||||
|
||||
${toplevelInjector} | ${specialisationInjector} > $out/bootspec/${filename}
|
||||
'';
|
||||
|
||||
validator = pkgs.writeCueValidator ./bootspec.cue {
|
||||
document = "Document"; # Universal validator for any version as long the schema is correctly set.
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
options.boot.bootspec = {
|
||||
enable = lib.mkEnableOption (lib.mdDoc "Enable generation of RFC-0125 bootspec in $system/bootspec, e.g. /run/current-system/bootspec");
|
||||
|
||||
extensions = lib.mkOption {
|
||||
type = lib.types.attrs;
|
||||
default = { };
|
||||
description = lib.mdDoc ''
|
||||
User-defined data that extends the bootspec document.
|
||||
|
||||
To reduce incompatibility and prevent names from clashing
|
||||
between applications, it is **highly recommended** to use a
|
||||
unique namespace for your extensions.
|
||||
'';
|
||||
};
|
||||
|
||||
# This will be run as a part of the `systemBuilder` in ./top-level.nix. This
|
||||
# means `$out` points to the output of `config.system.build.toplevel` and can
|
||||
# be used for a variety of things (though, for now, it's only used to report
|
||||
# the path of the `toplevel` itself and the `init` executable).
|
||||
writer = lib.mkOption {
|
||||
internal = true;
|
||||
default = schemas.v1.generator;
|
||||
};
|
||||
|
||||
validator = lib.mkOption {
|
||||
internal = true;
|
||||
default = schemas.v1.validator;
|
||||
};
|
||||
|
||||
filename = lib.mkOption {
|
||||
internal = true;
|
||||
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.
|
||||
''
|
||||
];
|
||||
};
|
||||
}
|
|
@ -79,6 +79,11 @@ let
|
|||
|
||||
echo -n "$extraDependencies" > $out/extra-dependencies
|
||||
|
||||
${optionalString (!config.boot.isContainer && config.boot.bootspec.enable) ''
|
||||
${config.boot.bootspec.writer}
|
||||
${config.boot.bootspec.validator} "$out/bootspec/${config.boot.bootspec.filename}"
|
||||
''}
|
||||
|
||||
${config.system.extraSystemBuilderCmds}
|
||||
'';
|
||||
|
||||
|
|
26
nixos/modules/system/boot/loader/external/external.md
vendored
Normal file
26
nixos/modules/system/boot/loader/external/external.md
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
# External Bootloader Backends {#sec-bootloader-external}
|
||||
|
||||
NixOS has support for several bootloader backends by default: systemd-boot, grub, uboot, etc.
|
||||
The built-in bootloader backend support is generic and supports most use cases.
|
||||
Some users may prefer to create advanced workflows around managing the bootloader and bootable entries.
|
||||
|
||||
You can replace the built-in bootloader support with your own tooling using the "external" bootloader option.
|
||||
|
||||
Imagine you have created a new package called FooBoot.
|
||||
FooBoot provides a program at `${pkgs.fooboot}/bin/fooboot-install` which takes the system closure's path as its only argument and configures the system's bootloader.
|
||||
|
||||
You can enable FooBoot like this:
|
||||
|
||||
```nix
|
||||
{ pkgs, ... }: {
|
||||
boot.loader.external = {
|
||||
enable = true;
|
||||
installHook = "${pkgs.fooboot}/bin/fooboot-install";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Developing Custom Bootloader Backends
|
||||
|
||||
Bootloaders should use [RFC-0125](https://github.com/NixOS/rfcs/pull/125)'s Bootspec format and synthesis tools to identify the key properties for bootable system generations.
|
||||
|
38
nixos/modules/system/boot/loader/external/external.nix
vendored
Normal file
38
nixos/modules/system/boot/loader/external/external.nix
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.boot.loader.external;
|
||||
in
|
||||
{
|
||||
meta = {
|
||||
maintainers = with maintainers; [ cole-h grahamc raitobezarius ];
|
||||
# Don't edit the docbook xml directly, edit the md and generate it:
|
||||
# `pandoc external.md -t docbook --top-level-division=chapter --extract-media=media -f markdown+smart > external.xml`
|
||||
doc = ./external.xml;
|
||||
};
|
||||
|
||||
options.boot.loader.external = {
|
||||
enable = mkEnableOption (lib.mdDoc "use an external tool to install your bootloader");
|
||||
|
||||
installHook = mkOption {
|
||||
type = with types; path;
|
||||
description = lib.mdDoc ''
|
||||
The full path to a program of your choosing which performs the bootloader installation process.
|
||||
|
||||
The program will be called with an argument pointing to the output of the system's toplevel.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
boot.loader = {
|
||||
grub.enable = mkDefault false;
|
||||
systemd-boot.enable = mkDefault false;
|
||||
supportsInitrdSecrets = mkDefault false;
|
||||
};
|
||||
|
||||
system.build.installBootLoader = cfg.installHook;
|
||||
};
|
||||
}
|
41
nixos/modules/system/boot/loader/external/external.xml
vendored
Normal file
41
nixos/modules/system/boot/loader/external/external.xml
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-bootloader-external">
|
||||
<title>External Bootloader Backends</title>
|
||||
<para>
|
||||
NixOS has support for several bootloader backends by default:
|
||||
systemd-boot, grub, uboot, etc. The built-in bootloader backend
|
||||
support is generic and supports most use cases. Some users may
|
||||
prefer to create advanced workflows around managing the bootloader
|
||||
and bootable entries.
|
||||
</para>
|
||||
<para>
|
||||
You can replace the built-in bootloader support with your own
|
||||
tooling using the <quote>external</quote> bootloader option.
|
||||
</para>
|
||||
<para>
|
||||
Imagine you have created a new package called FooBoot. FooBoot
|
||||
provides a program at
|
||||
<literal>${pkgs.fooboot}/bin/fooboot-install</literal> which takes
|
||||
the system closure’s path as its only argument and configures the
|
||||
system’s bootloader.
|
||||
</para>
|
||||
<para>
|
||||
You can enable FooBoot like this:
|
||||
</para>
|
||||
<programlisting language="nix">
|
||||
{ pkgs, ... }: {
|
||||
boot.loader.external = {
|
||||
enable = true;
|
||||
installHook = "${pkgs.fooboot}/bin/fooboot-install";
|
||||
};
|
||||
}
|
||||
</programlisting>
|
||||
<section xml:id="developing-custom-bootloader-backends">
|
||||
<title>Developing Custom Bootloader Backends</title>
|
||||
<para>
|
||||
Bootloaders should use
|
||||
<link xlink:href="https://github.com/NixOS/rfcs/pull/125">RFC-0125</link>’s
|
||||
Bootspec format and synthesis tools to identify the key properties
|
||||
for bootable system generations.
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
144
nixos/tests/bootspec.nix
Normal file
144
nixos/tests/bootspec.nix
Normal file
|
@ -0,0 +1,144 @@
|
|||
{ system ? builtins.currentSystem,
|
||||
config ? {},
|
||||
pkgs ? import ../.. { inherit system config; }
|
||||
}:
|
||||
|
||||
with import ../lib/testing-python.nix { inherit system pkgs; };
|
||||
with pkgs.lib;
|
||||
|
||||
let
|
||||
baseline = {
|
||||
virtualisation.useBootLoader = true;
|
||||
};
|
||||
grub = {
|
||||
boot.loader.grub.enable = true;
|
||||
};
|
||||
systemd-boot = {
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
};
|
||||
uefi = {
|
||||
virtualisation.useEFIBoot = true;
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
boot.loader.grub.efiSupport = true;
|
||||
environment.systemPackages = [ pkgs.efibootmgr ];
|
||||
};
|
||||
standard = {
|
||||
boot.bootspec.enable = true;
|
||||
|
||||
imports = [
|
||||
baseline
|
||||
systemd-boot
|
||||
uefi
|
||||
];
|
||||
};
|
||||
in
|
||||
{
|
||||
basic = makeTest {
|
||||
name = "systemd-boot-with-bootspec";
|
||||
meta.maintainers = with pkgs.lib.maintainers; [ raitobezarius ];
|
||||
|
||||
nodes.machine = standard;
|
||||
|
||||
testScript = ''
|
||||
machine.start()
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
|
||||
machine.succeed("test -e /run/current-system/bootspec/boot.json")
|
||||
'';
|
||||
};
|
||||
|
||||
grub = makeTest {
|
||||
name = "grub-with-bootspec";
|
||||
meta.maintainers = with pkgs.lib.maintainers; [ raitobezarius ];
|
||||
|
||||
nodes.machine = {
|
||||
boot.bootspec.enable = true;
|
||||
|
||||
imports = [
|
||||
baseline
|
||||
grub
|
||||
uefi
|
||||
];
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
machine.start()
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
|
||||
machine.succeed("test -e /run/current-system/bootspec/boot.json")
|
||||
'';
|
||||
};
|
||||
|
||||
legacy-boot = makeTest {
|
||||
name = "legacy-boot-with-bootspec";
|
||||
meta.maintainers = with pkgs.lib.maintainers; [ raitobezarius ];
|
||||
|
||||
nodes.machine = {
|
||||
boot.bootspec.enable = true;
|
||||
|
||||
imports = [
|
||||
baseline
|
||||
grub
|
||||
];
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
machine.start()
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
|
||||
machine.succeed("test -e /run/current-system/bootspec/boot.json")
|
||||
'';
|
||||
};
|
||||
|
||||
# Check that specialisations create corresponding entries in bootspec.
|
||||
specialisation = makeTest {
|
||||
name = "bootspec-with-specialisation";
|
||||
meta.maintainers = with pkgs.lib.maintainers; [ raitobezarius ];
|
||||
|
||||
nodes.machine = {
|
||||
imports = [ standard ];
|
||||
environment.systemPackages = [ pkgs.jq ];
|
||||
specialisation.something.configuration = {};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
import json
|
||||
|
||||
machine.start()
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
|
||||
machine.succeed("test -e /run/current-system/bootspec/boot.json")
|
||||
machine.succeed("test -e /run/current-system/specialisation/something/bootspec/boot.json")
|
||||
|
||||
sp_in_parent = json.loads(machine.succeed("jq -r '.v1.specialisation.something' /run/current-system/bootspec/boot.json"))
|
||||
sp_in_fs = json.loads(machine.succeed("cat /run/current-system/specialisation/something/bootspec/boot.json"))
|
||||
|
||||
assert sp_in_parent == sp_in_fs['v1'], "Bootspecs of the same specialisation are different!"
|
||||
'';
|
||||
};
|
||||
|
||||
# Check that extensions are propagated.
|
||||
extensions = makeTest {
|
||||
name = "bootspec-with-extensions";
|
||||
meta.maintainers = with pkgs.lib.maintainers; [ raitobezarius ];
|
||||
|
||||
nodes.machine = { config, ... }: {
|
||||
imports = [ standard ];
|
||||
environment.systemPackages = [ pkgs.jq ];
|
||||
boot.bootspec.extensions = {
|
||||
osRelease = config.environment.etc."os-release".source;
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
machine.start()
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
|
||||
current_os_release = machine.succeed("cat /etc/os-release")
|
||||
bootspec_os_release = machine.succeed("cat $(jq -r '.v1.extensions.osRelease' /run/current-system/bootspec/boot.json)")
|
||||
|
||||
assert current_os_release == bootspec_os_release, "Filename referenced by extension has unexpected contents"
|
||||
'';
|
||||
};
|
||||
|
||||
}
|
25
pkgs/tools/misc/bootspec/default.nix
Normal file
25
pkgs/tools/misc/bootspec/default.nix
Normal file
|
@ -0,0 +1,25 @@
|
|||
{ lib
|
||||
, rustPlatform
|
||||
, fetchFromGitHub
|
||||
}:
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "bootspec";
|
||||
version = "unstable-2022-12-05";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "DeterminateSystems";
|
||||
repo = pname;
|
||||
rev = "67a617ab6b99211daa92e748d27ead3f78127cf8";
|
||||
hash = "sha256-GX6Tzs/ClTUV9OXLvPFw6uBhrpCWSMI+PfrViyFEIxs=";
|
||||
};
|
||||
|
||||
cargoHash = "sha256-N/hbfjsuvwCc0mxOpeVVcTxb5cA024lyLSEpVcrS7kA=";
|
||||
|
||||
meta = with lib; {
|
||||
description = "Implementation of RFC-0125's datatype and synthesis tooling";
|
||||
homepage = "https://github.com/DeterminateSystems/bootspec";
|
||||
license = licenses.mit;
|
||||
maintainers = teams.determinatesystems.members;
|
||||
platforms = platforms.unix;
|
||||
};
|
||||
}
|
|
@ -2705,6 +2705,8 @@ with pkgs;
|
|||
|
||||
brewtarget = libsForQt5.callPackage ../applications/misc/brewtarget { } ;
|
||||
|
||||
bootspec = callPackage ../tools/misc/bootspec { };
|
||||
|
||||
# Derivation's result is not used by nixpkgs. Useful for validation for
|
||||
# regressions of bootstrapTools on hydra and on ofborg. Example:
|
||||
# pkgsCross.aarch64-multiplatform.freshBootstrapTools.build
|
||||
|
|
Loading…
Reference in a new issue