nixos/libvirtd: Make all OVMF images from QEMU package available
- Make OVMF firmware images distributed with QEMU available under /run/libvirt/nix-ovmf directory - Repackage OVMF firmware metadata JSON files from QEMU package, patching the image file locations to point to stable /run/libvirt/nix-ovmf rather than the nix store path of QEMU package. And make them available at /var/lib/qemu/firmware, the path libvirt uses to verify domain configuration. - Remove now obsolete `nvram` entry from qemu.conf. It was removed by upstream in Nov 2019. Eliminates log spam from libvirtd.service. Fixes #378894
This commit is contained in:
@@ -144,6 +144,22 @@
|
|||||||
|
|
||||||
- `virtualisation.lxd` has been removed due to lack of Nixpkgs maintenance. Users can migrate to `virtualisation.incus`, a fork of LXD, as a replacement. See [Incus migration documentation](https://linuxcontainers.org/incus/docs/main/howto/server_migrate_lxd/) for migration information.
|
- `virtualisation.lxd` has been removed due to lack of Nixpkgs maintenance. Users can migrate to `virtualisation.incus`, a fork of LXD, as a replacement. See [Incus migration documentation](https://linuxcontainers.org/incus/docs/main/howto/server_migrate_lxd/) for migration information.
|
||||||
|
|
||||||
|
- `virtualisation.libvirtd` now uses OVMF images shipped with QEMU for UEFI machines. `virtualisation.libvirtd.qemu.ovmf` has been removed.
|
||||||
|
- OVMF images from underlying QEMU package are now made available under '/run/libvirt/nix-ovmf', fixing prior issues when using QEMU's automatic EFI firmware and feature handling, relied upon by GNOME Boxes, virsh, virt-manager, etc.
|
||||||
|
- Domains that rely on automatic firmware and feature handling, i.e. `<os firmware='efi'>` need to trigger an update to `<loader>` and `<nvram>` entries.
|
||||||
|
Using `virsh edit <domain>` and deleting aforementioned tags will cause libvirt to replace them with the new paths.
|
||||||
|
- Configurations that relied on `virtualisation.libvirtd.qemu.ovmf` and had domains that did not use automatic firmware and feature handling, require a manual change to their domain configuration, updating `<loader>` and `<nvram>` entries from old path to the new path.
|
||||||
|
| Old Path | New Path |
|
||||||
|
|----------------------------------------|--------------------------------------------------|
|
||||||
|
| /run/libvirt/nix-ovmf/OVMF_CODE.fd | /run/libvirt/nix-ovmf/edk2-x86_64-code.fd |
|
||||||
|
| /run/libvirt/nix-ovmf/OVMF_VARS.fd | /run/libvirt/nix-ovmf/edk2-i386-vars.fd |
|
||||||
|
| /run/libvirt/nix-ovmf/OVMF_CODE.ms.fd | /run/libvirt/nix-ovmf/edk2-x86_64-secure-code.fd |
|
||||||
|
| /run/libvirt/nix-ovmf/OVMF_VARS.ms.fd | /run/libvirt/nix-ovmf/edk2-i386-vars.fd |
|
||||||
|
| /run/libvirt/nix-ovmf/AAVMF_CODE.fd | /run/libvirt/nix-ovmf/edk2-aarch64-code.fd |
|
||||||
|
| /run/libvirt/nix-ovmf/AAVMF_VARS.fd | /run/libvirt/nix-ovmf/edk2-arm-vars.fd |
|
||||||
|
| /run/libvirt/nix-ovmf/AAVMF_CODE.ms.fd | /run/libvirt/nix-ovmf/edk2-aarch64-code.fd |
|
||||||
|
| /run/libvirt/nix-ovmf/AAVMF_VARS.ms.fd | /run/libvirt/nix-ovmf/edk2-arm-vars.fd |
|
||||||
|
|
||||||
- The non-LTS Forgejo package (`forgejo`) has been updated to 12.0.0. This release contains breaking changes, see the [release blog post](https://forgejo.org/2025-07-release-v12-0/)
|
- The non-LTS Forgejo package (`forgejo`) has been updated to 12.0.0. This release contains breaking changes, see the [release blog post](https://forgejo.org/2025-07-release-v12-0/)
|
||||||
for all the details and how to ensure smooth upgrades.
|
for all the details and how to ensure smooth upgrades.
|
||||||
|
|
||||||
|
|||||||
@@ -17,14 +17,6 @@ let
|
|||||||
${cfg.extraConfig}
|
${cfg.extraConfig}
|
||||||
'';
|
'';
|
||||||
qemuConfigFile = pkgs.writeText "qemu.conf" ''
|
qemuConfigFile = pkgs.writeText "qemu.conf" ''
|
||||||
${optionalString cfg.qemu.ovmf.enable ''
|
|
||||||
nvram = [
|
|
||||||
"/run/libvirt/nix-ovmf/AAVMF_CODE.fd:/run/libvirt/nix-ovmf/AAVMF_VARS.fd",
|
|
||||||
"/run/libvirt/nix-ovmf/AAVMF_CODE.ms.fd:/run/libvirt/nix-ovmf/AAVMF_VARS.ms.fd",
|
|
||||||
"/run/libvirt/nix-ovmf/OVMF_CODE.fd:/run/libvirt/nix-ovmf/OVMF_VARS.fd",
|
|
||||||
"/run/libvirt/nix-ovmf/OVMF_CODE.ms.fd:/run/libvirt/nix-ovmf/OVMF_VARS.ms.fd"
|
|
||||||
]
|
|
||||||
''}
|
|
||||||
${optionalString (!cfg.qemu.runAsRoot) ''
|
${optionalString (!cfg.qemu.runAsRoot) ''
|
||||||
user = "qemu-libvirtd"
|
user = "qemu-libvirtd"
|
||||||
group = "qemu-libvirtd"
|
group = "qemu-libvirtd"
|
||||||
@@ -38,36 +30,6 @@ let
|
|||||||
dirName = "libvirt";
|
dirName = "libvirt";
|
||||||
subDirs = list: [ dirName ] ++ map (e: "${dirName}/${e}") list;
|
subDirs = list: [ dirName ] ++ map (e: "${dirName}/${e}") list;
|
||||||
|
|
||||||
ovmfModule = types.submodule {
|
|
||||||
options = {
|
|
||||||
enable = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = ''
|
|
||||||
Allows libvirtd to take advantage of OVMF when creating new
|
|
||||||
QEMU VMs with UEFI boot.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# mkRemovedOptionModule does not work in submodules, do it manually
|
|
||||||
package = mkOption {
|
|
||||||
type = types.nullOr types.package;
|
|
||||||
default = null;
|
|
||||||
internal = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
packages = mkOption {
|
|
||||||
type = types.listOf types.package;
|
|
||||||
default = [ pkgs.OVMF.fd ];
|
|
||||||
defaultText = literalExpression "[ pkgs.OVMF.fd ]";
|
|
||||||
example = literalExpression "[ pkgs.OVMFFull.fd pkgs.pkgsCross.aarch64-multiplatform.OVMF.fd ]";
|
|
||||||
description = ''
|
|
||||||
List of OVMF packages to use. Each listed package must contain files names FV/OVMF_CODE.fd and FV/OVMF_VARS.fd or FV/AAVMF_CODE.fd and FV/AAVMF_VARS.fd
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
swtpmModule = types.submodule {
|
swtpmModule = types.submodule {
|
||||||
options = {
|
options = {
|
||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
@@ -116,11 +78,28 @@ let
|
|||||||
};
|
};
|
||||||
|
|
||||||
ovmf = mkOption {
|
ovmf = mkOption {
|
||||||
type = ovmfModule;
|
type = types.submodule {
|
||||||
|
options = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = types.nullOr types.bool;
|
||||||
|
default = null;
|
||||||
|
internal = true;
|
||||||
|
};
|
||||||
|
package = mkOption {
|
||||||
|
type = types.nullOr types.package;
|
||||||
|
default = null;
|
||||||
|
internal = true;
|
||||||
|
};
|
||||||
|
packages = mkOption {
|
||||||
|
type = types.nullOr (types.listOf types.package);
|
||||||
|
default = null;
|
||||||
|
internal = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
default = { };
|
default = { };
|
||||||
description = ''
|
internal = true;
|
||||||
QEMU's OVMF options.
|
description = "This submodule is deprecated and has been removed";
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
swtpm = mkOption {
|
swtpm = mkOption {
|
||||||
@@ -220,6 +199,21 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
qemuOvmfMetadata = pkgs.stdenv.mkDerivation {
|
||||||
|
name = "qemu-ovmf-metadata";
|
||||||
|
version = cfg.qemu.package.version;
|
||||||
|
nativeBuildInputs = [ cfg.qemu.package ];
|
||||||
|
dontBuild = true;
|
||||||
|
dontUnpack = true;
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out
|
||||||
|
cp ${cfg.qemu.package}/share/qemu/firmware/*.json $out
|
||||||
|
substituteInPlace $out/*.json \
|
||||||
|
--replace-fail "${cfg.qemu.package}/share/qemu/" "/run/${dirName}/nix-ovmf/"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -241,17 +235,16 @@ in
|
|||||||
[ "virtualisation" "libvirtd" "qemuVerbatimConfig" ]
|
[ "virtualisation" "libvirtd" "qemuVerbatimConfig" ]
|
||||||
[ "virtualisation" "libvirtd" "qemu" "verbatimConfig" ]
|
[ "virtualisation" "libvirtd" "qemu" "verbatimConfig" ]
|
||||||
)
|
)
|
||||||
(mkRenamedOptionModule
|
|
||||||
[ "virtualisation" "libvirtd" "qemuOvmf" ]
|
|
||||||
[ "virtualisation" "libvirtd" "qemu" "ovmf" "enable" ]
|
|
||||||
)
|
|
||||||
(mkRemovedOptionModule [ "virtualisation" "libvirtd" "qemuOvmfPackage" ]
|
|
||||||
"If this option was set to `foo`, set the option `virtualisation.libvirtd.qemu.ovmf.packages' to `[foo.fd]` instead."
|
|
||||||
)
|
|
||||||
(mkRenamedOptionModule
|
(mkRenamedOptionModule
|
||||||
[ "virtualisation" "libvirtd" "qemuSwtpm" ]
|
[ "virtualisation" "libvirtd" "qemuSwtpm" ]
|
||||||
[ "virtualisation" "libvirtd" "qemu" "swtpm" "enable" ]
|
[ "virtualisation" "libvirtd" "qemu" "swtpm" "enable" ]
|
||||||
)
|
)
|
||||||
|
(mkRemovedOptionModule [ "virtualisation" "libvirtd" "qemuOvmf" ]
|
||||||
|
"The 'virtualisation.libvirtd.qemuOvmf' option has been removed. All OVMF images distributed with QEMU are now available by default."
|
||||||
|
)
|
||||||
|
(mkRemovedOptionModule [ "virtualisation" "libvirtd" "qemuOvmfPackage" ]
|
||||||
|
"The 'virtualisation.libvirtd.qemuOvmfPackage' option has been removed. All OVMF images distributed with QEMU are now available by default."
|
||||||
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
###### interface
|
###### interface
|
||||||
@@ -408,17 +401,15 @@ in
|
|||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
assertions = [
|
assertions = [
|
||||||
{
|
|
||||||
assertion = config.virtualisation.libvirtd.qemu.ovmf.package == null;
|
|
||||||
message = ''
|
|
||||||
The option virtualisation.libvirtd.qemu.ovmf.package is superseded by virtualisation.libvirtd.qemu.ovmf.packages.
|
|
||||||
If this option was set to `foo`, set the option `virtualisation.libvirtd.qemu.ovmf.packages' to `[foo.fd]` instead.
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
assertion = config.security.polkit.enable;
|
assertion = config.security.polkit.enable;
|
||||||
message = "The libvirtd module currently requires Polkit to be enabled ('security.polkit.enable = true').";
|
message = "The libvirtd module currently requires Polkit to be enabled ('security.polkit.enable = true').";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
assertion = ((lib.filterAttrs (n: v: v != null) cfg.qemu.ovmf) == { });
|
||||||
|
message = "The 'virtualisation.libvirtd.qemu.ovmf' submodule has been removed. All OVMF images distributed with QEMU are now available by default.";
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
environment = {
|
environment = {
|
||||||
@@ -488,20 +479,12 @@ in
|
|||||||
|
|
||||||
ln -s --force ${cfg.qemu.package}/bin/qemu-pr-helper /run/${dirName}/nix-helpers/
|
ln -s --force ${cfg.qemu.package}/bin/qemu-pr-helper /run/${dirName}/nix-helpers/
|
||||||
|
|
||||||
${optionalString cfg.qemu.ovmf.enable (
|
# Symlink to OVMF firmware code and variable template images distributed with QEMU
|
||||||
let
|
cp -sfv $(
|
||||||
ovmfpackage = pkgs.buildEnv {
|
${pkgs.jq}/bin/jq -rs \
|
||||||
name = "qemu-ovmf";
|
'[.[] | .mapping.executable.filename, .mapping."nvram-template".filename] | unique | .[]' \
|
||||||
paths = cfg.qemu.ovmf.packages;
|
${cfg.qemu.package}/share/qemu/firmware/* \
|
||||||
};
|
) /run/${dirName}/nix-ovmf
|
||||||
in
|
|
||||||
''
|
|
||||||
ln -s --force ${ovmfpackage}/FV/AAVMF_CODE{,.ms}.fd /run/${dirName}/nix-ovmf/
|
|
||||||
ln -s --force ${ovmfpackage}/FV/OVMF_CODE{,.ms}.fd /run/${dirName}/nix-ovmf/
|
|
||||||
ln -s --force ${ovmfpackage}/FV/AAVMF_VARS{,.ms}.fd /run/${dirName}/nix-ovmf/
|
|
||||||
ln -s --force ${ovmfpackage}/FV/OVMF_VARS{,.ms}.fd /run/${dirName}/nix-ovmf/
|
|
||||||
''
|
|
||||||
)}
|
|
||||||
|
|
||||||
# Symlink hooks to /var/lib/libvirt
|
# Symlink hooks to /var/lib/libvirt
|
||||||
${concatStringsSep "\n" (
|
${concatStringsSep "\n" (
|
||||||
@@ -620,7 +603,7 @@ in
|
|||||||
in
|
in
|
||||||
[
|
[
|
||||||
"L+ /var/lib/qemu/vhost-user - - - - ${vhostUserCollection}/share/qemu/vhost-user"
|
"L+ /var/lib/qemu/vhost-user - - - - ${vhostUserCollection}/share/qemu/vhost-user"
|
||||||
"L+ /var/lib/qemu/firmware - - - - ${cfg.qemu.package}/share/qemu/firmware"
|
"L+ /var/lib/qemu/firmware - - - - ${qemuOvmfMetadata}"
|
||||||
];
|
];
|
||||||
|
|
||||||
security.polkit = {
|
security.polkit = {
|
||||||
|
|||||||
Reference in New Issue
Block a user