KVM (Kernel-based Virtual Machine) and QEMU (Quick EMUlator) are both open-source virtualization technologies that run on Linux, but they are different in the way they accomplish the same tasks.

While KVM [Link] is a Linux kernel module that makes it functions as a hypervisor with the usage of hardware virtualization features (Intel VT-x and AMD-V), QEMU is an emulator.

QEMU it is capable of emulating different architectures and peripherals at the expense of related overhead. But it also can work with KVM to take advantage of the hardware virtualization.


KVM + QEMU

  • Install steps.
sudo apt-get update
sudo apt-get install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virt-manager -y
sudo reboot
  • Checking
egrep -c '(vmx|svm)' /proc/cpuinfo
sudo systemctl status libvirtd

Note: if it returns 0, the virtualization must be enabled on the BIOS. The service libvirtd must be active (running). The users that will manage the VMs need to be members of libvirt and kvm groups or use sudo.

GUI Interface

nohup sudo virt-manager &

KVM

  • Listing all VMs
virsh list --all
  • Managing VMs
virsh start vmName
virsh suspend vmName
virsh resume vmName
virsh shutdown vmName
virsh destroy vmName
virsh undefine vmName
virsh console vmName
  • Snapshots of a VM
virsh snapshot-list vmName
virsh snapshot-create-as --domain vmName --name snapshotName --description "Add description or comments here."
virsh snapshot-revert vmName snapshotName
virsh snapshot-delete vmName snapshotName
  • Getting information about OS Variants.
virt-install --os-variant list
virt-install --osinfo ubuntu22.04
  • Deploying a Kali VM from an ISO with VNC and a bridged network.
virt-install --name Kali --memory 4096 --vcpus 4 --os-variant debian11 --network bridge=virbr0 --graphics vnc --cdrom kali.iso --disk size=100,format=qcow2

Note: to proceed with the installation use a VNC client from the host machine connecting to 127.0.0.1 or use SSH to port forward port 5900.

  • Connecting via VNC
virsh vncdisplay vmName

In its VM configuration file it will look like the following:

<graphics type='vnc' port='-1' autoport='yes'>
  <listen type='address'/>
</graphics>

Configure it accordingly. For example:

<graphics type='vnc' port='5900' autoport='no' tls='yes'>
  <listen type='address' address='192.168.10.10'/>
</graphics>
  • Cloning a VM
virt-clone --original vmName --name vmNameCloned --auto-clone

OR

virt-clone --original vmName --name vmNameCloned --file /var/lib/libvirt/images/vmNameCloned.qcow2

Note: the path /var/lib/libvirt/images is where virtual disks are stored by default, while /etc/libvirt/qemu/ is where each VM configuration is located.

  • Configuring a VMs
virsh dominfo vmName
virsh autostart vmName
virsh edit vmName
  • Managing Networks
virsh net-list --all
virsh net-define /PATH/networkConfig.xml
virsh net-start networkName
virsh net-autostart networkName

Note: out of the box the default network might be not started and not set to auto-start. And alternatively, to the command line, KVM has a nice GUI called Virtual Machine Manager if you are running on a host with a graphic environment.


QEMU

  • Listing all VMs

Because QEMU emulates virtual machines, each one will be shown as a separate process and can be identified and killed using htop, for example.

  • Creating a Disk
qemu-img create -f qcow2 /PATH/vmImage.qcow2 100G
  • Lunching a VM – Basic Syntax
    • [arch]
      • x86-64 for x86 64 bits.
      • i386 for x86 32 bits.
      • arch64 for ARM 64 bits.
      • arm for ARM 32 bits.
      • ppc for PowerPC.
      • more
    • [memory]
      • 2048 for explicit in megabytes (default).
      • 2G for explicit in gigabytes.
    • [cores]
      • 2 for the number of virtual cores/threads (integer).
    • [boot]
      • order=d (or just d) to first try to boot the disk.
      • menu=on will prompt a menu that will allow the selection of the desired boot order.
    • -drive
      • It is the complete way or setting disks to the VM and optionally accepts additional options. It is compatible with .vhd (VirtualPC), .vdi (VirtualBox), .vmdk (VMWare), and more.
      • E.g. -drive file=vmImage.qcow2 or -drive file=vmImage.img,if=ide,format=raw,cache=writeback
    • -hda, -hdb, -hdc, and so on.
      • Alternatively to the -drive, it is a shorthand to set hard disk images.
      • E.g. -hda vmImage.qcow2
    • -cdrom
      • It is used to run an installation or recovery live CD.
    • -enable-kvm -cpu host
      • Allows QEMU to use the hardware virtualization features of KVM for better performance because it will not emulate the CPU if the Guest has the same architecture of the Host.
    • -vga virtio -display [display]
      • virtio is a paravirtualised video device.
        • vnc=127.0.0.1:0 it is strongly recommended to only bind on localhost and use an SSH tunnel to connect to. If set to bind on one or all interfaces of the Host, make sure the firewall rules as restricted appropriately.
        • sdl uses Simple DirectMedia Layer library and provides a good performance because it supports 3D emulation.
        • gtk uses GIMP Toolkit library but does not provide not optimal performance.
        • none does not display video output (headless).
    • -vga qxl
      • Uses SPICE to remote desktop and requires enabling the module by issuing sudo modprobe qxl bochs_drm.
    • -device virtio-gpu-pci
      • Check this option to “pass-through” a GPU/Video adapter placed in a PCI Express slot to the VM.
qemu-system-[arch] -m [memory] -smp [cores] -boot [boot] -hda [PATH] -cdrom [PATH] -enable-kvm -cpu host -vga virtio -display [display]
qemu-system-x86_64 -m 4G -smp 4 -boot menu=on -hda /PATH/vmImage.qcow2 -cdrom /PATH/file.iso -enable-kvm -cpu host -vga virtio -display vnc=127.0.0.1:0
qemu-system-x86_64 -m 2048 -drive file=vmImage.qcow2,format=qcow2 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -device virtio-net-pci,netdev=net0,mac=52:54:00:12:34:56
qemu-system-x86_64 -m 2G -hda vmImage.qcow2 -usb -device usb-host,hostbus=2,hostaddr=4

Note: use lsusb to find out the bus and address of the USB device you want to pass-through.

  • Managing Volumes
qemu-img info vmImage.qcow2
qemu-img resize vmImage.qcow2 +10G
qemu-img commit vmImage.qcow2
qemu-img convert -O vmdk -O qcow2 vmImage.vmdk vmImage.qcow2 
  • ARM VMs
sudo apt-get install qemu-system-arm -y
qemu-system-arm -M help
qemu-system-arm -M virt -enable-kvm -m 256 -kernel vmlinuz-3.2.0-4-virt -initrd initrd.img-3.2.0-4-virt -hda ARMvmImage.qcow2 -append "root=/dev/vda1" -netdev user,id=usernet,hostfwd=tcp::2222-:22 -device virtio-net-device,netdev=usernet

Note: the volumes and networks are managed similarly for all architectures.


GUEST AGENT

  • Install on the guest OS
sudo apt update && sudo apt -y install qemu-guest-agent -y
sudo systemctl enable qemu-guest-agent --now

OR

sudo apt update && sudo apt install spice-vdagent -y

REFLECTIONS

Unless there is a reason to emulate a VM, like a different architecture for example, it is recommended to use KVM for most of the cases.

The configuration files for each VM are stored at /etc/libvirt/qemu.


BONUS

To install Windows 11 on QEMU/KVM it is usually useful to send key combinations to the guest:

virsh send-key Win11_VM_Name --holdtime 1000 KEY_LEFTSHIFT KEY_F10

This will allow to enter the following command to bypass the sign-in feature and install Windows 11 offline.

OOBE\BYPASSNRO

Or to create a new user from the Terminal, enter the following commands.

net user Administrator /active:yes
net user /add userName userPassword
net localgroup administrators userName /add
%windir%\system32\oobe\msoobe.exe