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}'" ''; }; }