Libvirt: Difference between revisions

Onny (talk | contribs)
Add note on enable USB redirection
Add section "File sharing via virtiofs mount"
 
(21 intermediate revisions by 12 users not shown)
Line 5: Line 5:
Enable libvirt daemon
Enable libvirt daemon


{{file|/etc/nixos/configuration.nix|nix|<nowiki>
{{file|||<nowiki>
virtualisation.libvirtd = {
virtualisation.libvirtd.enable = true;
  enable = true;
 
  qemu = {
# Enable TPM emulation (optional)
    package = pkgs.qemu_kvm;
# install pkgs.swtpm system-wide for use in virt-manager (optional)
    runAsRoot = true;
virtualisation.libvirtd.qemu = {
    swtpm.enable = true;
  swtpm.enable = true;
    ovmf = {
      enable = true;
      packages = [(pkgs.unstable.OVMF.override {
        secureBoot = true;
        tpmSupport = true;
      }).fd];
    };
  };
};
};


# Enable USB redirection (optional)
# Enable USB redirection (optional)
virtualisation.spiceUSBRedirection.enable = true;
virtualisation.spiceUSBRedirection.enable = true;
</nowiki>}}
 
</nowiki>|name=/etc/nixos/configuration.nix|lang=nix}}


To enable local user access to libvirt, for example by using <code>virt-manager</code> or <code>gnome-boxes</code>, add yourself to the <code>libvirtd</code> group
To enable local user access to libvirt, for example by using <code>virt-manager</code> or <code>gnome-boxes</code>, add yourself to the <code>libvirtd</code> group
Line 37: Line 30:


=== UEFI with OVMF ===
=== UEFI with OVMF ===
Enable UEFI firmware support, following Qemu configuration for your local user is required
{{file|~/.config/libvirt/qemu.conf|nix|<nowiki>
# Adapted from /var/lib/libvirt/qemu.conf
# Note that AAVMF and OVMF are for Aarch64 and x86 respectively
nvram = [ "/run/libvirt/nix-ovmf/AAVMF_CODE.fd:/run/libvirt/nix-ovmf/AAVMF_VARS.fd", "/run/libvirt/nix-ovmf/OVMF_CODE.fd:/run/libvirt/nix-ovmf/OVMF_VARS.fd" ]
</nowiki>}}


See [https://ostechnix.com/enable-uefi-support-for-kvm-virtual-machines-in-linux/ this tutorial] on how to run a guest machine in UEFI mode using <code>virt-manager</code>.
See [https://ostechnix.com/enable-uefi-support-for-kvm-virtual-machines-in-linux/ this tutorial] on how to run a guest machine in UEFI mode using <code>virt-manager</code>.
Line 52: Line 37:
If you would like to enable nested virtualization for your guests to run KVM hypervisors inside them, you should enable it as follows:  {{nixos:option|boot.extraModprobeConfig}}, for example:
If you would like to enable nested virtualization for your guests to run KVM hypervisors inside them, you should enable it as follows:  {{nixos:option|boot.extraModprobeConfig}}, for example:


{{file|/etc/nixos/configuration.nix|xml|<nowiki>
{{file|||<nowiki>
boot.extraModprobeConfig = "options kvm_intel nested=1";
boot.extraModprobeConfig = ''
</nowiki>}}
  options kvm_intel nested=1
'';
</nowiki>|name=/etc/nixos/configuration.nix|lang=nix}}
 
=== Networking ===
 
==== Default networking ====
 
Enable and start the default network using the following commands:
 
<syntaxhighlight lang="console">
# virsh net-autostart default
# virsh net-start default
</syntaxhighlight>
 
This will configure the default network to start automatically on boot and immediately activate it. You may need to whitelist the interface for the firewall like so:
 
{{File|3=networking.firewall.trustedInterfaces = [ "virbr0" ];|name=/etc/nixos/configuration.nix|lang=nix}}


=== Bridge networking ===
==== Bridge networking ====


Create a XML file called <code>virbr0.xml</code> with the definition of the bridge interface
Create a XML file called <code>virbr0.xml</code> with the definition of the bridge interface.


<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
Line 68: Line 70:
</syntaxhighlight>
</syntaxhighlight>


Add and enable bridge interface
Add and enable bridge interface.


<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
Line 78: Line 80:
</syntaxhighlight>
</syntaxhighlight>


Edit the libvirt guest <code>my_guest</code> XML file and add the bridge interface to it
Edit the libvirt guest <code>my_guest</code> XML file and add the bridge interface to it.


<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
Line 84: Line 86:
</syntaxhighlight>
</syntaxhighlight>


Add
Add:


<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
Line 99: Line 101:
</syntaxhighlight>
</syntaxhighlight>


Inside the guest configure networking for the interface <code>enp1s0</code> (name might differ)
Inside the guest configure networking for the interface <code>enp1s0</code> (name may differ).


{{file|/etc/nixos/configuration.nix|nix|<nowiki>
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
networking.interfaces.enp1s0.ipv4.addresses = [{
networking.interfaces.enp1s0 = {
  address = "10.25.0.2";
  ipv4.addresses = [{
  prefixLength = 24;
    address = "10.25.0.2";
}];
    prefixLength = 24;
  }];
  defaultGateway = {
    address = "10.25.0.1";
    interface = "ens1s0";
  };
};
</nowiki>}}
</nowiki>}}


The host should now be able to reach the guest via the bridge interface and vice versa.
The host should now be able to reach the guest via the bridge interface and vice versa.


=== File sharing ===
=== File sharing via virtiofs mount ===
One of the best ways to share a host directory with the guest OS is with [https://virtio-fs.gitlab.io/ virtiofs]. On the host system, install the <code>virtiofsd</code> package:<syntaxhighlight lang="nix">
environment.systemPackages = with pkgs; [
  guestfs-tools
  virtiofsd
];
</syntaxhighlight>Next, a few sections of the XML must be edited, which can be done manually or via virt-manager in the guest configuration GUI. If using virt-manager, first navigate on the toolbar to Edit > Preferences > General, and click "Enable XML Editing". Next, open the virtual machine and under the hardware configuration, navigate to Memory and check the box "Enable shared memory". This will add an "access" block to the XML for you, similar to this:<syntaxhighlight lang="xml">
<memory unit="KiB">1638400</memory>
<currentMemory unit="KiB">1638400</currentMemory>
<memoryBacking>
  <source type="memfd"/>
  <access mode="shared"/>
</memoryBacking>
</syntaxhighlight>While still in the hardware configuration, click "Add Hardware" and select "Filesystem". For driver, select "virtiofs". For source path, input the folder on the host machine you wish to share, no trailing slash. For target path, don't put a path but instead a tag/label that is easily identifiable. It will be used in the mount options in the guest OS setup shortly. Once done, you should have a new Filesystem device configuration similar to this:<syntaxhighlight lang="xml">
<filesystem type="mount" accessmode="passthrough">
  <driver type="virtiofs"/>
  <binary path="/run/current-system/sw/bin/virtiofsd"/>
  <source dir="/media"/>
  <target dir="my_host_media_share"/>
  <alias name="fs0"/>
  <address type="pci" domain="0x0000" bus="0x07" slot="0x00" function="0x0"/>
</filesystem>
</syntaxhighlight>If your guest system is using NixOS, you can boot the system and add the new filesystem entry to auto-mount on boot and you're done:<syntaxhighlight lang="nix">
fileSystems."/media" = {
  device = "my_host_media_share";
  fsType = "virtiofs";
};
</syntaxhighlight>If the system fails to fully reboot after applying the changes, ensure the filesystem device matches the "Target path" in your XML exactly.
 
==== Error starting domain: internal error: Child process (/run/current-system/sw/bin/virtiofsd --print-capabilities) unexpected exit status 127: libvirt:  error : cannot execute binary /run/current-system/sw/bin/virtiofsd: No such file or directory ====
This error means virtiofsd was not installed on the host system. Ensure the system package was installed before making changes in virt-manager.
 
==== Error starting domain: operation failed: Unable to find a satisfying virtiofsd ====
The virtiofsd binary path needs to be specified in the filesystem configuration. virt-manager doesn't add this by default and instead assumes a default path that doesn't exist under NixOS. Open the guest machine's hardware details page, click on the passthrough filesystem created earlier, open the XML tab and inside the `<filesystem>...</filesystem>` add the following element to tell virtio where to find the virtiofsd binary:<syntaxhighlight lang="xml">
<binary path="/run/current-system/sw/bin/virtiofsd"/>
</syntaxhighlight>
 
=== File sharing via WebDAV ===


In order to share files between host and guest, one recommended way of doing this is to use <code>spice-webdavd</code>.
Another recommended way to share files between host and guest is to use <code>spice-webdavd</code>.


Shutdown the client, in this example named <code>my_guest</code>, and edit the libvirt XML file.
Shutdown the client, in this example named <code>my_guest</code>, and edit the libvirt XML file.
Line 130: Line 175:
</syntaxhighlight>
</syntaxhighlight>


Start the guest machine. Inside the guest, add following part to your system configuration and apply it
Start the guest machine. Inside the guest, add following part to your system configuration and apply it.


{{file|/etc/nixos/configuration.nix|nix|<nowiki>
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
Line 136: Line 181:
</nowiki>}}
</nowiki>}}


List available shares for the guest
List available shares for the guest.


<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
Line 142: Line 187:
</syntaxhighlight>
</syntaxhighlight>


Mount an example share called <code>myshare</code> to the mountpoint <code>myshare</code>
Mount an example share called <code>myshare</code> to the mountpoint <code>myshare.</code>


{{file|/etc/nixos/configuration.nix|nix|<nowiki>
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
services.davfs2 = {
services.davfs2 = {
   enable = true;
   enable = true;
   extraConfig = ''
   settings.globalSection.ask_auth = 0;
    ask_auth 0
  '';
};
};


Line 160: Line 203:
};
};
</nowiki>}}
</nowiki>}}
=== Hooks ===
Libvirt allows the use of hooks to run custom scripts during specific events, such as daemon lifecycle events, domain lifecycle events, and network events. On NixOS, you can configure hooks via the NixOS module to automate the placement of hook scripts in the appropriate directories.
The following directories are used for placing hook scripts:
* '''<code>/var/lib/libvirt/hooks/daemon.d/</code>'''  Scripts here are triggered by daemon events like start, shutdown, and SIGHUP.
* '''<code>/var/lib/libvirt/hooks/qemu.d/</code>'''  Scripts for handling QEMU domain events such as begin, end, and migration.
* '''<code>/var/lib/libvirt/hooks/lxc.d/</code>'''  Scripts for LXC container events like begin and end.
* '''<code>/var/lib/libvirt/hooks/libxl.d/</code>'''  Scripts for Xen domains managed by <code>libxl</code> (begin/end events).
* '''<code>/var/lib/libvirt/hooks/network.d/</code>'''  Scripts triggered by network events such as begin and end.
See the [https://libvirt.org/hooks.html libvirt documentation] for more information.
An example config would be:<syntaxhighlight lang="nix">
{
  virtualisation.libvirtd.hooks = {
    daemon = {
      "example" = ./scripts/daemon-example.sh;
    };
    qemu = {
      "example" = ./scripts/qemu-example.sh;
    };
    network = {
      "example" = ./scripts/network-example.sh;
    };
  };
}
</syntaxhighlight>Note that after you added the configuration and switch, you'll have the following command to setup the hooks.<syntaxhighlight lang="bash">
systemctl start libvirtd-config.service
</syntaxhighlight>
=== PCI Passthrough ===
For detailed instructions on configuring PCI passthrough with libvirt, refer to the [[PCI passthrough]] page.


== Clients ==
== Clients ==
Line 170: Line 248:


Following are notes regarding the use of some of those tools
Following are notes regarding the use of some of those tools
==== error: cannot find any suitable libguestfs supermin ====
Use use the package libguestfs-with-appliance. See https://github.com/NixOS/nixpkgs/issues/37540
=== guestfs-tools ===
Includes virt-sysprep, used to prepare a VM image for use.  Review the manpage of virt-sysprep, virt-clone, and virt-builder.


==== <code>virt-builder</code> ====
==== <code>virt-builder</code> ====


virt-builder is installed with <code>libguestfs</code>, but has some issues from its packaging.
virt-builder is installed with <code>guestfs-tools</code>, but has some issues from its packaging.


It is possible to work around those issues without modifying the package (when a pristine nixpkgs is needed).
It is possible to work around those issues without modifying the package (when a pristine nixpkgs is needed).
Line 186: Line 274:


This will make your user use the shipped repo configurations, and works around the fact that virt-builder reads its executable name to build its configuration path. The executable being wrapped, it is named differently.
This will make your user use the shipped repo configurations, and works around the fact that virt-builder reads its executable name to build its configuration path. The executable being wrapped, it is named differently.
==== error: cannot find any suitable libguestfs supermin ====
Use use the package libguestfs-with-appliance. See https://github.com/NixOS/nixpkgs/issues/37540
=== guestfs-tools ===
Includes virt-sysprep, used to prepare a VM image for use.  Review the manpage of virt-sysprep, virt-clone, and virt-builder.


=== NixVirt ===
=== NixVirt ===


[https://flakehub.com/flake/AshleyYakeley/NixVirt NixVirt] is a flake that provides NixOS and Home Manager modules for setting up libvirt domains, networks and pools declaratively.
[https://github.com/AshleyYakeley/NixVirt NixVirt] is a flake that provides NixOS and Home Manager modules for setting up libvirt domains, networks and pools declaratively.


=== Accessing QEMU VMs through Webbrowser ===
=== Accessing QEMU VMs through Webbrowser ===
Line 241: Line 320:
==== Get EyeOS Spice Web Client ====
==== Get EyeOS Spice Web Client ====


As said, the experience with the EyeOS Spice Web Client has been the best so far. Another client would be the [https://cgit.freedesktop.org/spice/spice-html5/ spice-html5] from freedesktop.org.
As said, the experience with the EyeOS Spice Web Client has been the best so far. Another client would be the [https://gitlab.freedesktop.org/spice/spice-html5/ spice-html5] from freedesktop.org.


1. Download the [https://github.com/eyeos/spice-web-client/ EyeOS Spice Web Client] and unpack it (if necessary) or , as example, just <code>git clone https://github.com/eyeos/spice-web-client/ /var/www/spice</code>
1. Download the [https://github.com/eyeos/spice-web-client/ EyeOS Spice Web Client] and unpack it (if necessary) or , as example, just <code>git clone https://github.com/eyeos/spice-web-client/ /var/www/spice</code>
Line 284: Line 363:


And finally you can access the VMs GUI through <code>https://mydomain.tld:4500/spice/index.html?host=mydomain.tld&port=5959</code>
And finally you can access the VMs GUI through <code>https://mydomain.tld:4500/spice/index.html?host=mydomain.tld&port=5959</code>
[[Category:Virtualization]]
[[Category:Virtualization]]
[[Category:Applications]]
[[Category:Applications]]