about summary refs log tree commit diff
path: root/nixos/modules/system
diff options
context:
space:
mode:
authorRaito Bezarius <masterancpp@gmail.com>2022-11-30 17:55:41 +0100
committerCole Helbling <cole.e.helbling@outlook.com>2022-12-08 13:50:04 -0800
commit348ba1b33c039a3524dcda2a874c83fb44680f9c (patch)
tree913c697e47d29579579fadbcbaa18e6cfdd22437 /nixos/modules/system
parent9a431a57b1b0172e86729a2ed56f4c51bc6a8701 (diff)
nixos/activation/bootspec: module-ify
This does the following:

* turns bootspec into a NixOS module
* validates bootspecs with Cue
* exposes internal knobs
Diffstat (limited to 'nixos/modules/system')
-rw-r--r--nixos/modules/system/activation/bootspec.cue23
-rw-r--r--nixos/modules/system/activation/bootspec.nix69
-rw-r--r--nixos/modules/system/activation/top-level.nix11
3 files changed, 80 insertions, 23 deletions
diff --git a/nixos/modules/system/activation/bootspec.cue b/nixos/modules/system/activation/bootspec.cue
new file mode 100644
index 0000000000000..ad21ffcd28f92
--- /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 ed5714d87cec1..aa5928ddc1538 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 9733bc55ae1bb..7d44d37a0fcf9 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}