From ea5e2ba437b20513af857a633f662b43573328aa Mon Sep 17 00:00:00 2001 From: Mia Kanashi Date: Fri, 17 Mar 2023 21:36:12 +0200 Subject: [PATCH] nixos-module: add settings key for the loader.conf This commit adds settings key for configuring systemd-boot to the lanzaboot nixos module. The are couple of the default values that are set from the usual nixos boot.loader.systemd-boot options, they are merged with the user defined configuration. This commit modifies default loader.conf to boot into the latest nixos generation by default, for when you have other operating systems installed. Primary reason behind this PR is to allow extensible loader configuration. Co-authored-by: Raito Bezarius --- nix/modules/lanzaboote.nix | 55 ++++++++++++++++++++++++++++++++------ nix/tests/lanzaboote.nix | 8 +++--- 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/nix/modules/lanzaboote.nix b/nix/modules/lanzaboote.nix index 1d8792e..fabfca1 100644 --- a/nix/modules/lanzaboote.nix +++ b/nix/modules/lanzaboote.nix @@ -2,52 +2,91 @@ with lib; let cfg = config.boot.lanzaboote; + sbctlWithPki = pkgs.sbctl.override { databasePath = "/tmp/pki"; }; - configurationLimit = if cfg.configurationLimit == null then 0 else cfg.configurationLimit; - timeout = if config.boot.loader.timeout == null then 0 else config.boot.loader.timeout; + loaderSettingsFormat = pkgs.formats.keyValue { + mkKeyValue = k: v: if v == null then "" else + lib.generators.mkKeyValueDefault { } " " k v; + }; - systemdBootLoaderConfig = pkgs.writeText "loader.conf" '' - timeout ${toString timeout} - console-mode ${config.boot.loader.systemd-boot.consoleMode} - ''; + loaderConfigFile = loaderSettingsFormat.generate "loader.conf" cfg.settings; + + configurationLimit = if cfg.configurationLimit == null then 0 else cfg.configurationLimit; in { options.boot.lanzaboote = { enable = mkEnableOption "Enable the LANZABOOTE"; + enrollKeys = mkEnableOption "Automatic enrollment of the keys using sbctl"; + configurationLimit = mkOption { - default = null; + default = config.boot.loader.systemd-boot.configurationLimit; example = 120; type = types.nullOr types.int; description = lib.mdDoc '' Maximum number of latest generations in the boot menu. Useful to prevent boot partition running out of disk space. + `null` means no limit i.e. all generations that were not garbage collected yet. ''; }; + pkiBundle = mkOption { type = types.nullOr types.path; description = "PKI bundle containing db, PK, KEK"; }; + publicKeyFile = mkOption { type = types.path; default = "${cfg.pkiBundle}/keys/db/db.pem"; description = "Public key to sign your boot files"; }; + privateKeyFile = mkOption { type = types.path; default = "${cfg.pkiBundle}/keys/db/db.key"; description = "Private key to sign your boot files"; }; + package = mkOption { type = types.package; default = pkgs.lzbt; description = "Lanzaboote tool (lzbt) package"; }; + + settings = mkOption rec { + type = types.submodule { + freeformType = loaderSettingsFormat.type; + }; + + apply = recursiveUpdate default; + + default = { + timeout = config.boot.loader.timeout; + console-mode = config.boot.loader.systemd-boot.consoleMode; + editor = config.boot.loader.systemd-boot.editor; + default = "nixos-*"; + }; + + example = literalExpression '' + { + editor = null; # null value removes line from the loader.conf + beep = true; + default = "@saved"; + timeout = 10; + } + ''; + + description = '' + Configuration for the `systemd-boot` + + See `loader.conf(5)` for supported values. + ''; + }; }; config = mkIf cfg.enable { @@ -66,7 +105,7 @@ in ${cfg.package}/bin/lzbt install \ --systemd ${config.systemd.package} \ - --systemd-boot-loader-config ${systemdBootLoaderConfig} \ + --systemd-boot-loader-config ${loaderConfigFile} \ --public-key ${cfg.publicKeyFile} \ --private-key ${cfg.privateKeyFile} \ --configuration-limit ${toString configurationLimit} \ diff --git a/nix/tests/lanzaboote.nix b/nix/tests/lanzaboote.nix index d748ac1..87509b5 100644 --- a/nix/tests/lanzaboote.nix +++ b/nix/tests/lanzaboote.nix @@ -249,11 +249,11 @@ in testScript = '' machine.start() - actual_loader_config = machine.succeed("cat /boot/loader/loader.conf") - expected_loader_config = "timeout 0\nconsole-mode auto\n" + actual_loader_config = machine.succeed("cat /boot/loader/loader.conf").split("\n") + expected_loader_config = ["timeout 0", "console-mode auto"] - assert actual_loader_config == expected_loader_config, \ - f"Actual: '{actual_loader_config}' is not equal to expected: '{expected_loader_config}'" + assert all(cfg in actual_loader_config for cfg in expected_loader_config), \ + f"Expected: {expected_loader_config} is not included in actual config: '{actual_loader_config}'" ''; }; }