From b4a5a3d28f06bb80b99ab5b54382a83d3232fe87 Mon Sep 17 00:00:00 2001 From: Arian van Putten Date: Thu, 25 Jun 2026 09:53:18 +0200 Subject: [PATCH] nixos/virtualisation/nspawn-container: add virtualisation.credentials support Assisted-by: Claude --- .../virtualisation/credentials-options.nix | 63 +++++++++++++ .../nspawn-container/default.nix | 7 +- nixos/modules/virtualisation/qemu-vm.nix | 88 +++---------------- 3 files changed, 83 insertions(+), 75 deletions(-) create mode 100644 nixos/modules/virtualisation/credentials-options.nix diff --git a/nixos/modules/virtualisation/credentials-options.nix b/nixos/modules/virtualisation/credentials-options.nix new file mode 100644 index 000000000000..3345f6933784 --- /dev/null +++ b/nixos/modules/virtualisation/credentials-options.nix @@ -0,0 +1,63 @@ +{ lib, pkgs, ... }: +{ + options.virtualisation.credentials = lib.mkOption { + description = '' + Credentials to pass to the VM or container using systemd's credential system. + + See {manpage}`systemd.exec(5)`, {manpage}`systemd-creds(1)` and https://systemd.io/CREDENTIALS/ for more + information about systemd credentials. + ''; + default = { }; + example = lib.literalExpression '' + { + database-password = { + text = "my-secret-password"; + }; + ssl-cert = { + source = "./cert.pem"; + }; + binary-key = { + source = "./private.der"; + }; + } + ''; + type = lib.types.attrsOf ( + lib.types.submodule ( + { + name, + options, + config, + ... + }: + { + options = { + source = lib.mkOption { + type = lib.types.nullOr (lib.types.pathWith { }); + default = null; + description = '' + Source file on the host containing the credential data. + ''; + }; + text = lib.mkOption { + default = null; + type = lib.types.nullOr lib.types.str; + description = '' + Text content of the credential. + + For binary data or when the credential content should come from + an existing file, use `source` instead. + + ::: {.warning} + The text here is stored in the host's nix store as a file. + ::: + ''; + }; + }; + config.source = lib.mkIf (config.text != null) ( + lib.mkDerivedConfig options.text (pkgs.writeText name) + ); + } + ) + ); + }; +} diff --git a/nixos/modules/virtualisation/nspawn-container/default.nix b/nixos/modules/virtualisation/nspawn-container/default.nix index 9100b580768b..82a06929e925 100644 --- a/nixos/modules/virtualisation/nspawn-container/default.nix +++ b/nixos/modules/virtualisation/nspawn-container/default.nix @@ -21,6 +21,10 @@ let cfg = config.virtualisation; in { + imports = [ + ../credentials-options.nix + ]; + options = { virtualisation.cmdline = lib.mkOption { @@ -131,7 +135,8 @@ in # Send a READY=1 notification to a socket when the container is fully booted. "--notify-ready=yes" - ]; + ] + ++ lib.mapAttrsToList (name: cred: "--load-credential=${name}:${cred.source}") cfg.credentials; system.build.nspawn = let diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix index 8d2817c23bf0..8230da280b50 100644 --- a/nixos/modules/virtualisation/qemu-vm.nix +++ b/nixos/modules/virtualisation/qemu-vm.nix @@ -399,6 +399,7 @@ in imports = [ ../profiles/qemu-guest.nix ./disk-size-option.nix + ./credentials-options.nix (mkRenamedOptionModule [ "virtualisation" @@ -1126,81 +1127,20 @@ in }; virtualisation.credentials = mkOption { - description = '' - Credentials to pass to the VM using systemd's credential system. - - See {manpage}`systemd.exec(5)` , {manpage}`systemd-creds(1)` and https://systemd.io/CREDENTIALS/ for more - information about systemd credentials. - ''; - default = { }; - example = { - database-password = { - text = "my-secret-password"; - }; - ssl-cert = { - source = "./cert.pem"; - }; - binary-key = { - mechanism = "fw_cfg"; - source = "./private.der"; - }; - config-file = { - mechanism = "smbios"; - text = '' - [database] - host=localhost - port=5432 - ''; - }; - }; type = types.attrsOf ( - lib.types.submodule ( - { - name, - options, - config, - ... - }: - { - options = { - mechanism = lib.mkOption { - type = lib.types.enum [ - "fw_cfg" - "smbios" - ]; - default = if pkgs.stdenv.hostPlatform.isx86 then "smbios" else "fw_cfg"; - defaultText = lib.literalExpression ''if pkgs.stdenv.hostPlatform.isx86 then "smbios" else "fw_cfg"''; - description = '' - The mechanism used to pass the credential to the VM. - ''; - }; - source = lib.mkOption { - type = lib.types.nullOr (lib.types.pathWith { }); - default = null; - description = '' - Source file on the host containing the credential data. - ''; - }; - text = lib.mkOption { - default = null; - type = lib.types.nullOr lib.types.str; - description = '' - Text content of the credential. - - For binary data or when the credential content should come from - an existing file, use `source` instead. - - ::: {.warning} - The text here is stored in the host's nix store as a file. - ::: - ''; - }; - }; - config.source = lib.mkIf (config.text != null) ( - lib.mkDerivedConfig options.text (pkgs.writeText name) - ); - } - ) + lib.types.submodule { + options.mechanism = lib.mkOption { + type = lib.types.enum [ + "fw_cfg" + "smbios" + ]; + default = if pkgs.stdenv.hostPlatform.isx86 then "smbios" else "fw_cfg"; + defaultText = lib.literalExpression ''if pkgs.stdenv.hostPlatform.isx86 then "smbios" else "fw_cfg"''; + description = '' + The mechanism used to pass the credential to the VM. + ''; + }; + } ); };