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.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/)
|
||||
for all the details and how to ensure smooth upgrades.
|
||||
|
||||
|
||||
@@ -17,14 +17,6 @@ let
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
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) ''
|
||||
user = "qemu-libvirtd"
|
||||
group = "qemu-libvirtd"
|
||||
@@ -38,36 +30,6 @@ let
|
||||
dirName = "libvirt";
|
||||
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 {
|
||||
options = {
|
||||
enable = mkOption {
|
||||
@@ -116,11 +78,28 @@ let
|
||||
};
|
||||
|
||||
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 = { };
|
||||
description = ''
|
||||
QEMU's OVMF options.
|
||||
'';
|
||||
internal = true;
|
||||
description = "This submodule is deprecated and has been removed";
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
@@ -241,17 +235,16 @@ in
|
||||
[ "virtualisation" "libvirtd" "qemuVerbatimConfig" ]
|
||||
[ "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
|
||||
[ "virtualisation" "libvirtd" "qemuSwtpm" ]
|
||||
[ "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
|
||||
@@ -408,17 +401,15 @@ in
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
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;
|
||||
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 = {
|
||||
@@ -488,20 +479,12 @@ in
|
||||
|
||||
ln -s --force ${cfg.qemu.package}/bin/qemu-pr-helper /run/${dirName}/nix-helpers/
|
||||
|
||||
${optionalString cfg.qemu.ovmf.enable (
|
||||
let
|
||||
ovmfpackage = pkgs.buildEnv {
|
||||
name = "qemu-ovmf";
|
||||
paths = cfg.qemu.ovmf.packages;
|
||||
};
|
||||
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 to OVMF firmware code and variable template images distributed with QEMU
|
||||
cp -sfv $(
|
||||
${pkgs.jq}/bin/jq -rs \
|
||||
'[.[] | .mapping.executable.filename, .mapping."nvram-template".filename] | unique | .[]' \
|
||||
${cfg.qemu.package}/share/qemu/firmware/* \
|
||||
) /run/${dirName}/nix-ovmf
|
||||
|
||||
# Symlink hooks to /var/lib/libvirt
|
||||
${concatStringsSep "\n" (
|
||||
@@ -620,7 +603,7 @@ in
|
||||
in
|
||||
[
|
||||
"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 = {
|
||||
|
||||
Reference in New Issue
Block a user