From 942dcd238b49ecd3020e75d0a193e9eedf45a0ab Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Wed, 28 Jul 2021 14:10:02 -0700 Subject: [PATCH 01/23] nixos/activation/bootspec: init bootspec support (RFC-0125) --- .github/CODEOWNERS | 1 + nixos/modules/system/activation/bootspec.nix | 50 +++++++++++++++++++ nixos/modules/system/activation/top-level.nix | 10 ++++ 3 files changed, 61 insertions(+) create mode 100644 nixos/modules/system/activation/bootspec.nix diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 41d539dd5f1d..582e1cfc5491 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -78,6 +78,7 @@ /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 # NixOS integration test driver /nixos/lib/test-driver @tfc diff --git a/nixos/modules/system/activation/bootspec.nix b/nixos/modules/system/activation/bootspec.nix new file mode 100644 index 000000000000..c38f675cea27 --- /dev/null +++ b/nixos/modules/system/activation/bootspec.nix @@ -0,0 +1,50 @@ +# 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, children }: +let + schemas = { + v1 = rec { + filename = "boot.v1.json"; + json = + pkgs.writeText filename + (builtins.toJSON + { + schemaVersion = 1; + + 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})"; + + specialisation = lib.mapAttrs + (childName: childToplevel: { + bootspec = "${childToplevel}/${filename}"; + }) + children; + }); + + generator = '' + ${pkgs.jq}/bin/jq ' + .toplevel = $toplevel | + .init = $init + ' \ + --sort-keys \ + --arg toplevel "$out" \ + --arg init "$out/init" \ + < ${json} \ + > $out/${filename} + ''; + }; + }; +in +{ + # 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 = schemas.v1.generator; +} diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix index 55ff98db5382..9237c1c2f6e5 100644 --- a/nixos/modules/system/activation/top-level.nix +++ b/nixos/modules/system/activation/top-level.nix @@ -9,6 +9,14 @@ let "${config.system.boot.loader.kernelFile}"; initrdPath = "${config.system.build.initialRamdisk}/" + "${config.system.boot.loader.initrdFile}"; + + bootSpec = import ./bootspec.nix { + inherit + config + pkgs + lib + children; + }; in '' mkdir $out @@ -79,6 +87,8 @@ let echo -n "${toString config.system.extraDependencies}" > $out/extra-dependencies + ${bootSpec.writer} + ${config.system.extraSystemBuilderCmds} ''; From 83d06ce16d3c0f8aa7fec4d6f8cf069c3b16205a Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Thu, 5 Aug 2021 12:33:13 -0700 Subject: [PATCH 02/23] nixos/boot/external: init This allows supporting external bootloader backends. --- .../bootloader-external.section.xml | 41 +++++++++++++++++++ nixos/modules/module-list.nix | 1 + .../system/boot/loader/external/external.md | 26 ++++++++++++ .../system/boot/loader/external/external.nix | 38 +++++++++++++++++ .../system/boot/loader/external/external.xml | 41 +++++++++++++++++++ 5 files changed, 147 insertions(+) create mode 100644 nixos/doc/manual/from_md/configuration/bootloader-external.section.xml create mode 100644 nixos/modules/system/boot/loader/external/external.md create mode 100644 nixos/modules/system/boot/loader/external/external.nix create mode 100644 nixos/modules/system/boot/loader/external/external.xml diff --git a/nixos/doc/manual/from_md/configuration/bootloader-external.section.xml b/nixos/doc/manual/from_md/configuration/bootloader-external.section.xml new file mode 100644 index 000000000000..9b7ed6ccdac3 --- /dev/null +++ b/nixos/doc/manual/from_md/configuration/bootloader-external.section.xml @@ -0,0 +1,41 @@ +
+ External Bootloader Backends + + 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 packaged 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: + + +{ pkgs, ... }: { + boot.loader.external = { + enable = true; + installHook = "${pkgs.fooboot}/bin/fooboot-install"; + }; +} + +
+ Developing Custom Bootloader Backends + + Bootloaders should use + RFC-0125’s + Bootspec format and synthesis tools to identify the key properties + for bootable system generations. + +
+
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 24dd30e15750..b2723f8df9a7 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1256,6 +1256,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 diff --git a/nixos/modules/system/boot/loader/external/external.md b/nixos/modules/system/boot/loader/external/external.md new file mode 100644 index 000000000000..a53ab55baf5b --- /dev/null +++ b/nixos/modules/system/boot/loader/external/external.md @@ -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 packaged 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. + diff --git a/nixos/modules/system/boot/loader/external/external.nix b/nixos/modules/system/boot/loader/external/external.nix new file mode 100644 index 000000000000..86f4eaaeba46 --- /dev/null +++ b/nixos/modules/system/boot/loader/external/external.nix @@ -0,0 +1,38 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.boot.loader.external; +in +{ + meta = { + maintainers = with maintainers; [ cole-h grahamc ]; + # 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 "use an external tool to install your bootloader"; + + installHook = mkOption { + type = with types; path; + description = '' + 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 = false; + }; + + system.build.installBootLoader = cfg.installHook; + }; +} diff --git a/nixos/modules/system/boot/loader/external/external.xml b/nixos/modules/system/boot/loader/external/external.xml new file mode 100644 index 000000000000..b024e7dd4031 --- /dev/null +++ b/nixos/modules/system/boot/loader/external/external.xml @@ -0,0 +1,41 @@ + + External Bootloader Backends + + 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 packaged 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: + + +{ pkgs, ... }: { + boot.loader.external = { + enable = true; + installHook = "${pkgs.fooboot}/bin/fooboot-install"; + }; +} + +
+ Developing Custom Bootloader Backends + + Bootloaders should use + RFC-0125’s + Bootspec format and synthesis tools to identify the key properties + for bootable system generations. + +
+
From 6c0e4e892ff70b2875da3fd04e37b7fe3019850d Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Mon, 16 May 2022 16:14:08 -0400 Subject: [PATCH 03/23] nixos/activation/bootspec: embed the entire contents of specialisation's bootspecs into the parent See: https://github.com/NixOS/rfcs/pull/125#discussion_r871222614 --- nixos/modules/system/activation/bootspec.nix | 38 +++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/nixos/modules/system/activation/bootspec.nix b/nixos/modules/system/activation/bootspec.nix index c38f675cea27..f14ec65137f3 100644 --- a/nixos/modules/system/activation/bootspec.nix +++ b/nixos/modules/system/activation/bootspec.nix @@ -19,25 +19,29 @@ let 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})"; - - specialisation = lib.mapAttrs - (childName: childToplevel: { - bootspec = "${childToplevel}/${filename}"; - }) - children; }); - generator = '' - ${pkgs.jq}/bin/jq ' - .toplevel = $toplevel | - .init = $init - ' \ - --sort-keys \ - --arg toplevel "$out" \ - --arg init "$out/init" \ - < ${json} \ - > $out/${filename} - ''; + generator = + let + specialisationLoader = (lib.mapAttrsToList + (childName: childToplevel: lib.escapeShellArgs [ "--slurpfile" childName "${childToplevel}/${filename}" ]) + children); + in + '' + ${pkgs.jq}/bin/jq ' + .toplevel = $toplevel | + .init = $init + ' \ + --sort-keys \ + --arg toplevel "$out" \ + --arg init "$out/init" \ + < ${json} \ + | ${pkgs.jq}/bin/jq \ + --sort-keys \ + '.specialisation = ($ARGS.named | map_values(. | first))' \ + ${lib.concatStringsSep " " specialisationLoader} \ + > $out/${filename} + ''; }; }; in From e9c85d6d0f5d76f82d99bfc90f672afefdadc358 Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Wed, 18 May 2022 15:46:29 -0400 Subject: [PATCH 04/23] nixos/activation/bootspec: embed the document into a bootspec subdir --- nixos/modules/system/activation/bootspec.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nixos/modules/system/activation/bootspec.nix b/nixos/modules/system/activation/bootspec.nix index f14ec65137f3..b11dc37521ca 100644 --- a/nixos/modules/system/activation/bootspec.nix +++ b/nixos/modules/system/activation/bootspec.nix @@ -28,6 +28,8 @@ let children); in '' + mkdir -p $out/bootspec + ${pkgs.jq}/bin/jq ' .toplevel = $toplevel | .init = $init @@ -40,7 +42,7 @@ let --sort-keys \ '.specialisation = ($ARGS.named | map_values(. | first))' \ ${lib.concatStringsSep " " specialisationLoader} \ - > $out/${filename} + > $out/bootspec/${filename} ''; }; }; From e69c37eae9b4b8fee2dc0397bec57163a732ea10 Mon Sep 17 00:00:00 2001 From: K900 Date: Fri, 12 Aug 2022 08:44:17 +0300 Subject: [PATCH 05/23] nixos/activation: don't generate bootspec for containers --- nixos/modules/system/activation/top-level.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix index 9237c1c2f6e5..9733bc55ae1b 100644 --- a/nixos/modules/system/activation/top-level.nix +++ b/nixos/modules/system/activation/top-level.nix @@ -87,7 +87,9 @@ let echo -n "${toString config.system.extraDependencies}" > $out/extra-dependencies - ${bootSpec.writer} + ${optionalString (!config.boot.isContainer) '' + ${bootSpec.writer} + ''} ${config.system.extraSystemBuilderCmds} ''; From ee27291b34cf97ca195797733045da1a1ad49ddb Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Wed, 30 Nov 2022 15:08:37 +0100 Subject: [PATCH 06/23] nixos/activation/bootspec: fix slurping specialisation bootspecs --- nixos/modules/system/activation/bootspec.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/modules/system/activation/bootspec.nix b/nixos/modules/system/activation/bootspec.nix index b11dc37521ca..ed5714d87cec 100644 --- a/nixos/modules/system/activation/bootspec.nix +++ b/nixos/modules/system/activation/bootspec.nix @@ -24,7 +24,7 @@ let generator = let specialisationLoader = (lib.mapAttrsToList - (childName: childToplevel: lib.escapeShellArgs [ "--slurpfile" childName "${childToplevel}/${filename}" ]) + (childName: childToplevel: lib.escapeShellArgs [ "--slurpfile" childName "${childToplevel}/bootspec/${filename}" ]) children); in '' From 9a431a57b1b0172e86729a2ed56f4c51bc6a8701 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Wed, 30 Nov 2022 15:15:52 +0100 Subject: [PATCH 07/23] nixos/activation/bootspec: add @raitobezarius as a code-owner --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 582e1cfc5491..3cb74a5dccec 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -78,7 +78,7 @@ /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 +/nixos/modules/system/activation/bootspec.nix @grahamc @cole-h @raitobezarius # NixOS integration test driver /nixos/lib/test-driver @tfc From 348ba1b33c039a3524dcda2a874c83fb44680f9c Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Wed, 30 Nov 2022 17:55:41 +0100 Subject: [PATCH 08/23] nixos/activation/bootspec: module-ify This does the following: * turns bootspec into a NixOS module * validates bootspecs with Cue * exposes internal knobs --- nixos/modules/module-list.nix | 1 + nixos/modules/system/activation/bootspec.cue | 23 +++++++ nixos/modules/system/activation/bootspec.nix | 69 +++++++++++++++---- nixos/modules/system/activation/top-level.nix | 11 +-- 4 files changed, 81 insertions(+), 23 deletions(-) create mode 100644 nixos/modules/system/activation/bootspec.cue diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index b2723f8df9a7..da56e7a8a692 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1241,6 +1241,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 diff --git a/nixos/modules/system/activation/bootspec.cue b/nixos/modules/system/activation/bootspec.cue new file mode 100644 index 000000000000..ad21ffcd28f9 --- /dev/null +++ b/nixos/modules/system/activation/bootspec.cue @@ -0,0 +1,23 @@ +#V1: { + init: string + initrd?: string + initrdSecrets?: string + kernel: string + kernelParams: [...string] + label: string + toplevel: string + specialisation?: { + [=~"^"]: #V1 + } + extensions?: {...} +} + +#SecureBootExtensions: #V1 & { + extensions: { + osRelease: string + } +} + +Document: { + v1: #V1 +} diff --git a/nixos/modules/system/activation/bootspec.nix b/nixos/modules/system/activation/bootspec.nix index ed5714d87cec..aa5928ddc153 100644 --- a/nixos/modules/system/activation/bootspec.nix +++ b/nixos/modules/system/activation/bootspec.nix @@ -3,23 +3,31 @@ # 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, children }: +{ 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.v1.json"; + filename = "boot.json"; json = pkgs.writeText filename (builtins.toJSON - { - schemaVersion = 1; - + { + 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 @@ -31,8 +39,8 @@ let mkdir -p $out/bootspec ${pkgs.jq}/bin/jq ' - .toplevel = $toplevel | - .init = $init + .v1.toplevel = $toplevel | + .v1.init = $init ' \ --sort-keys \ --arg toplevel "$out" \ @@ -40,17 +48,50 @@ let < ${json} \ | ${pkgs.jq}/bin/jq \ --sort-keys \ - '.specialisation = ($ARGS.named | map_values(. | first))' \ + '.v1.specialisation = ($ARGS.named | map_values(. | first | .v1))' \ ${lib.concatStringsSep " " specialisationLoader} \ > $out/bootspec/${filename} ''; + + validator = pkgs.writeCueValidator ./bootspec.cue { + document = "Document"; # Universal validator for any version as long the schema is correctly set. + }; }; }; in { - # 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 = schemas.v1.generator; + options.boot.bootspec = { + enable = lib.mkEnableOption "Enable generation of RFC-0125 bootspec in $system/bootspec, e.g. /run/current-system/bootspec"; + extensions = lib.mkOption { + type = lib.types.attrs; + default = {}; + }; + # 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. + Schema is not definitive and features are not stabilized 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. + '' + ]; + }; } diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix index 9733bc55ae1b..7d44d37a0fcf 100644 --- a/nixos/modules/system/activation/top-level.nix +++ b/nixos/modules/system/activation/top-level.nix @@ -9,14 +9,6 @@ let "${config.system.boot.loader.kernelFile}"; initrdPath = "${config.system.build.initialRamdisk}/" + "${config.system.boot.loader.initrdFile}"; - - bootSpec = import ./bootspec.nix { - inherit - config - pkgs - lib - children; - }; in '' mkdir $out @@ -88,7 +80,8 @@ let echo -n "${toString config.system.extraDependencies}" > $out/extra-dependencies ${optionalString (!config.boot.isContainer) '' - ${bootSpec.writer} + ${config.boot.bootspec.writer} + ${config.boot.bootspec.validator} "$out/bootspec/${config.boot.bootspec.filename}" ''} ${config.system.extraSystemBuilderCmds} From 092e6d39cd50f3282a2694b0a3000bf0d27012fe Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Wed, 30 Nov 2022 17:55:57 +0100 Subject: [PATCH 09/23] nixos/tests/bootspec: init This will test various scenarios of bootspec generation. --- nixos/tests/bootspec.nix | 143 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 nixos/tests/bootspec.nix diff --git a/nixos/tests/bootspec.nix b/nixos/tests/bootspec.nix new file mode 100644 index 000000000000..0d37d0e56574 --- /dev/null +++ b/nixos/tests/bootspec.nix @@ -0,0 +1,143 @@ +{ 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; + 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" + ''; + }; + +} From 980f50124f6b0b611c348aaa96292ffca0f25b37 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Wed, 30 Nov 2022 17:56:16 +0100 Subject: [PATCH 10/23] nixos/boot/external: add @raitobezarius as maintainer and allow initrd secrets --- nixos/modules/system/boot/loader/external/external.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nixos/modules/system/boot/loader/external/external.nix b/nixos/modules/system/boot/loader/external/external.nix index 86f4eaaeba46..300870430866 100644 --- a/nixos/modules/system/boot/loader/external/external.nix +++ b/nixos/modules/system/boot/loader/external/external.nix @@ -7,7 +7,7 @@ let in { meta = { - maintainers = with maintainers; [ cole-h grahamc ]; + 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; @@ -30,7 +30,7 @@ in boot.loader = { grub.enable = mkDefault false; systemd-boot.enable = mkDefault false; - supportsInitrdSecrets = false; + supportsInitrdSecrets = mkDefault false; }; system.build.installBootLoader = cfg.installHook; From 9832e3e9b9c88384d5c92f33bfd980ac0503e624 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Wed, 30 Nov 2022 18:00:24 +0100 Subject: [PATCH 11/23] nixos/activation/bootspec: remove SB extension example in Cue schema --- nixos/modules/system/activation/bootspec.cue | 6 ------ 1 file changed, 6 deletions(-) diff --git a/nixos/modules/system/activation/bootspec.cue b/nixos/modules/system/activation/bootspec.cue index ad21ffcd28f9..3fc9ca381df7 100644 --- a/nixos/modules/system/activation/bootspec.cue +++ b/nixos/modules/system/activation/bootspec.cue @@ -12,12 +12,6 @@ extensions?: {...} } -#SecureBootExtensions: #V1 & { - extensions: { - osRelease: string - } -} - Document: { v1: #V1 } From 11dfbee0a4a2309515608a890e91d4d1a2a43626 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Wed, 30 Nov 2022 18:12:13 +0100 Subject: [PATCH 12/23] nixos/activation/bootspec: add bootspec chapter in NixOS manual --- .../manual/development/bootspec.chapter.md | 36 +++++++++ nixos/doc/manual/development/development.xml | 1 + .../from_md/development/bootspec.chapter.xml | 73 +++++++++++++++++++ nixos/modules/system/activation/bootspec.nix | 2 +- 4 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 nixos/doc/manual/development/bootspec.chapter.md create mode 100644 nixos/doc/manual/from_md/development/bootspec.chapter.xml diff --git a/nixos/doc/manual/development/bootspec.chapter.md b/nixos/doc/manual/development/bootspec.chapter.md new file mode 100644 index 000000000000..96c12f24e7f1 --- /dev/null +++ b/nixos/doc/manual/development/bootspec.chapter.md @@ -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. diff --git a/nixos/doc/manual/development/development.xml b/nixos/doc/manual/development/development.xml index 624ee3931659..949468c9021d 100644 --- a/nixos/doc/manual/development/development.xml +++ b/nixos/doc/manual/development/development.xml @@ -12,6 +12,7 @@ + diff --git a/nixos/doc/manual/from_md/development/bootspec.chapter.xml b/nixos/doc/manual/from_md/development/bootspec.chapter.xml new file mode 100644 index 000000000000..acf8ca76bf5c --- /dev/null +++ b/nixos/doc/manual/from_md/development/bootspec.chapter.xml @@ -0,0 +1,73 @@ + + Experimental feature: Bootspec + + Bootspec is a experimental feature, introduced in the + RFC-0125 + proposal, the reference implementation can be found + there + 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, + which will prompt a warning until + RFC-0125 + is officially merged. + +
+ Schema + + The bootspec schema is versioned and validated against + a CUE schema file + which should considered as the source of truth for your + applications. + + + You will find the current version + here. + +
+
+ Extensions mechanism + + Bootspec cannot account for all usecases. + + + For this purpose, Bootspec offers a generic extension facility + 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: + + +{ 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 + + It is possible to enable your own bootloader through + 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. + +
+
diff --git a/nixos/modules/system/activation/bootspec.nix b/nixos/modules/system/activation/bootspec.nix index aa5928ddc153..170c07e7daf7 100644 --- a/nixos/modules/system/activation/bootspec.nix +++ b/nixos/modules/system/activation/bootspec.nix @@ -87,7 +87,7 @@ in config = lib.mkIf (cfg.enable) { warnings = [ ''RFC-0125 is not merged yet, this is a feature preview of bootspec. - Schema is not definitive and features are not stabilized until RFC-0125 is merged. + 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. From 680369e504e9c241fdbd1d7621a7c3011649edcc Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Wed, 30 Nov 2022 18:24:11 +0100 Subject: [PATCH 13/23] nixos/activation/bootspec: add some comments to explain the delicate manipulations --- nixos/modules/system/activation/bootspec.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nixos/modules/system/activation/bootspec.nix b/nixos/modules/system/activation/bootspec.nix index 170c07e7daf7..2d4f7158dd46 100644 --- a/nixos/modules/system/activation/bootspec.nix +++ b/nixos/modules/system/activation/bootspec.nix @@ -38,6 +38,9 @@ let '' mkdir -p $out/bootspec + # Inject toplevel and init in the bootspec. + # This can be done only here because we *cannot* depend on $out, except + # by living in $out itself. ${pkgs.jq}/bin/jq ' .v1.toplevel = $toplevel | .v1.init = $init @@ -47,7 +50,7 @@ let --arg init "$out/init" \ < ${json} \ | ${pkgs.jq}/bin/jq \ - --sort-keys \ + --sort-keys \ # Slurp all specialisations and inject them as values in .specialisations.{name} = {specialisation bootspec}. '.v1.specialisation = ($ARGS.named | map_values(. | first | .v1))' \ ${lib.concatStringsSep " " specialisationLoader} \ > $out/bootspec/${filename} From ad6ea546b4da50faff7961c2eb260a68aa1c65f6 Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Thu, 1 Dec 2022 16:21:46 -0800 Subject: [PATCH 14/23] nixos/boot/external: DocBook -> Markdown --- nixos/modules/system/boot/loader/external/external.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nixos/modules/system/boot/loader/external/external.nix b/nixos/modules/system/boot/loader/external/external.nix index 300870430866..5cf478e6c83c 100644 --- a/nixos/modules/system/boot/loader/external/external.nix +++ b/nixos/modules/system/boot/loader/external/external.nix @@ -14,11 +14,11 @@ in }; options.boot.loader.external = { - enable = mkEnableOption "use an external tool to install your bootloader"; + enable = mkEnableOption (lib.mdDoc "use an external tool to install your bootloader"); installHook = mkOption { type = with types; path; - description = '' + 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. From cc63293b50cbc33c3e0519690fbaaec1b2434289 Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Thu, 1 Dec 2022 16:24:33 -0800 Subject: [PATCH 15/23] nixos/boot/external: fixup typo in generated docs, regenerate docs --- nixos/modules/system/boot/loader/external/external.md | 2 +- nixos/modules/system/boot/loader/external/external.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/nixos/modules/system/boot/loader/external/external.md b/nixos/modules/system/boot/loader/external/external.md index a53ab55baf5b..ba1dfd4d9b9a 100644 --- a/nixos/modules/system/boot/loader/external/external.md +++ b/nixos/modules/system/boot/loader/external/external.md @@ -6,7 +6,7 @@ Some users may prefer to create advanced workflows around managing the bootloade You can replace the built-in bootloader support with your own tooling using the "external" bootloader option. -Imagine you have created a new packaged called FooBoot. +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: diff --git a/nixos/modules/system/boot/loader/external/external.xml b/nixos/modules/system/boot/loader/external/external.xml index b024e7dd4031..39ab2156bc8c 100644 --- a/nixos/modules/system/boot/loader/external/external.xml +++ b/nixos/modules/system/boot/loader/external/external.xml @@ -12,7 +12,7 @@ tooling using the external bootloader option. - Imagine you have created a new packaged called FooBoot. FooBoot + 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 @@ -21,7 +21,7 @@ You can enable FooBoot like this: - + { pkgs, ... }: { boot.loader.external = { enable = true; From 97f657c742a60ff272881528268b1af7b10b6938 Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Thu, 1 Dec 2022 16:29:18 -0800 Subject: [PATCH 16/23] nixos/activation/bootspec: DocBook -> Markdown, add description for extensions field --- nixos/modules/system/activation/bootspec.nix | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/nixos/modules/system/activation/bootspec.nix b/nixos/modules/system/activation/bootspec.nix index 2d4f7158dd46..cf74244b43b4 100644 --- a/nixos/modules/system/activation/bootspec.nix +++ b/nixos/modules/system/activation/bootspec.nix @@ -64,11 +64,20 @@ let in { options.boot.bootspec = { - enable = lib.mkEnableOption "Enable generation of RFC-0125 bootspec in $system/bootspec, e.g. /run/current-system/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 = {}; + 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 @@ -77,10 +86,12 @@ in internal = true; default = schemas.v1.generator; }; + validator = lib.mkOption { internal = true; default = schemas.v1.validator; }; + filename = lib.mkOption { internal = true; default = schemas.v1.filename; From 38e50898148a137bfbd97ed9acf52b87af37f19e Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Fri, 2 Dec 2022 11:43:07 -0800 Subject: [PATCH 17/23] nixos/activation/bootspec: drop problematic comment, only generate bootspec when bootspec is enabled --- nixos/modules/system/activation/bootspec.nix | 2 +- nixos/modules/system/activation/top-level.nix | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nixos/modules/system/activation/bootspec.nix b/nixos/modules/system/activation/bootspec.nix index cf74244b43b4..59b9f4733965 100644 --- a/nixos/modules/system/activation/bootspec.nix +++ b/nixos/modules/system/activation/bootspec.nix @@ -50,7 +50,7 @@ let --arg init "$out/init" \ < ${json} \ | ${pkgs.jq}/bin/jq \ - --sort-keys \ # Slurp all specialisations and inject them as values in .specialisations.{name} = {specialisation bootspec}. + --sort-keys \ '.v1.specialisation = ($ARGS.named | map_values(. | first | .v1))' \ ${lib.concatStringsSep " " specialisationLoader} \ > $out/bootspec/${filename} diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix index 7d44d37a0fcf..a12a565af1f7 100644 --- a/nixos/modules/system/activation/top-level.nix +++ b/nixos/modules/system/activation/top-level.nix @@ -79,7 +79,7 @@ let echo -n "${toString config.system.extraDependencies}" > $out/extra-dependencies - ${optionalString (!config.boot.isContainer) '' + ${optionalString (!config.boot.isContainer && config.boot.bootspec.enable) '' ${config.boot.bootspec.writer} ${config.boot.bootspec.validator} "$out/bootspec/${config.boot.bootspec.filename}" ''} From dce9add02b24d8ee02a2afb79ce972a9ebc0aaa3 Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Fri, 2 Dec 2022 13:19:35 -0800 Subject: [PATCH 18/23] nixos/activation/bootspec: refactor the generator script We separate the different steps (injecting the toplevel and injecting the specialisations) so that it's easy to document what each snippet is actually doing. --- nixos/modules/system/activation/bootspec.nix | 51 ++++++++++++-------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/nixos/modules/system/activation/bootspec.nix b/nixos/modules/system/activation/bootspec.nix index 59b9f4733965..99cc6f537497 100644 --- a/nixos/modules/system/activation/bootspec.nix +++ b/nixos/modules/system/activation/bootspec.nix @@ -31,29 +31,42 @@ let generator = let - specialisationLoader = (lib.mapAttrsToList - (childName: childToplevel: lib.escapeShellArgs [ "--slurpfile" childName "${childToplevel}/bootspec/${filename}" ]) - children); + # 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" "$out" + "--arg" "init" "$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 - # Inject toplevel and init in the bootspec. - # This can be done only here because we *cannot* depend on $out, except - # by living in $out itself. - ${pkgs.jq}/bin/jq ' - .v1.toplevel = $toplevel | - .v1.init = $init - ' \ - --sort-keys \ - --arg toplevel "$out" \ - --arg init "$out/init" \ - < ${json} \ - | ${pkgs.jq}/bin/jq \ - --sort-keys \ - '.v1.specialisation = ($ARGS.named | map_values(. | first | .v1))' \ - ${lib.concatStringsSep " " specialisationLoader} \ - > $out/bootspec/${filename} + ${toplevelInjector} | ${specialisationInjector} > $out/bootspec/${filename} ''; validator = pkgs.writeCueValidator ./bootspec.cue { From fc88e4cf7d4e86657042d0da7bf91446d19c8d43 Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Sat, 3 Dec 2022 16:08:13 -0800 Subject: [PATCH 19/23] nixos/boot/external: drop duplicated external bootloader documentation The documentation is generated thanks to `meta.doc`, and was out of date anyways. --- .../bootloader-external.section.xml | 41 ------------------- 1 file changed, 41 deletions(-) delete mode 100644 nixos/doc/manual/from_md/configuration/bootloader-external.section.xml diff --git a/nixos/doc/manual/from_md/configuration/bootloader-external.section.xml b/nixos/doc/manual/from_md/configuration/bootloader-external.section.xml deleted file mode 100644 index 9b7ed6ccdac3..000000000000 --- a/nixos/doc/manual/from_md/configuration/bootloader-external.section.xml +++ /dev/null @@ -1,41 +0,0 @@ -
- External Bootloader Backends - - 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 packaged 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: - - -{ pkgs, ... }: { - boot.loader.external = { - enable = true; - installHook = "${pkgs.fooboot}/bin/fooboot-install"; - }; -} - -
- Developing Custom Bootloader Backends - - Bootloaders should use - RFC-0125’s - Bootspec format and synthesis tools to identify the key properties - for bootable system generations. - -
-
From b37cee3dba9401b264ee9fd91e9848260503f0ef Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Mon, 5 Dec 2022 09:32:54 -0800 Subject: [PATCH 20/23] bootspec: init at unstable-2022-12-05 The bootspec package provides synthesis and validation tooling for RFC-0125 compliant bootspec documents. --- pkgs/tools/misc/bootspec/default.nix | 25 +++++++++++++++++++++++++ pkgs/top-level/all-packages.nix | 2 ++ 2 files changed, 27 insertions(+) create mode 100644 pkgs/tools/misc/bootspec/default.nix diff --git a/pkgs/tools/misc/bootspec/default.nix b/pkgs/tools/misc/bootspec/default.nix new file mode 100644 index 000000000000..789f438de50e --- /dev/null +++ b/pkgs/tools/misc/bootspec/default.nix @@ -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; + }; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 888ab409ad53..4f0310d61217 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -2694,6 +2694,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 From 5af481f67f2967bf7db0a05053331c4b9d4906f7 Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Mon, 5 Dec 2022 09:57:20 -0800 Subject: [PATCH 21/23] nixos/activation/bootspec: fixup improper $out substitution --- nixos/modules/system/activation/bootspec.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nixos/modules/system/activation/bootspec.nix b/nixos/modules/system/activation/bootspec.nix index 99cc6f537497..da76bf9084af 100644 --- a/nixos/modules/system/activation/bootspec.nix +++ b/nixos/modules/system/activation/bootspec.nix @@ -44,8 +44,8 @@ let .v1.init = $init '' "--sort-keys" - "--arg" "toplevel" "$out" - "--arg" "init" "$out/init" + "--arg" "toplevel" "${placeholder "out"}" + "--arg" "init" "${placeholder "out"}/init" ] + " < ${json}"; # We slurp all specialisations and inject them as values, such that From 6eb04c578d69b3d719743ccaa40103fc62ec72ea Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Mon, 5 Dec 2022 11:08:38 -0800 Subject: [PATCH 22/23] nixos/activation/bootspec: bootspec owners also own the cue file --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3cb74a5dccec..32e0313cf8db 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -79,6 +79,7 @@ /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 From aac4134f430fb15386a174c6556ca0116616d2ea Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Sat, 17 Dec 2022 02:13:45 +0100 Subject: [PATCH 23/23] nixos/tests/bootspec: add EFI support for GRUB test --- nixos/tests/bootspec.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/nixos/tests/bootspec.nix b/nixos/tests/bootspec.nix index 0d37d0e56574..13360bb1eaa2 100644 --- a/nixos/tests/bootspec.nix +++ b/nixos/tests/bootspec.nix @@ -19,6 +19,7 @@ let uefi = { virtualisation.useEFIBoot = true; boot.loader.efi.canTouchEfiVariables = true; + boot.loader.grub.efiSupport = true; environment.systemPackages = [ pkgs.efibootmgr ]; }; standard = {