Server--:--:--You--:--:--

Your First VM with KVM and libvirt

By Prabath Thalangama· September 18, 2026· 3 min read
#kvm#libvirt#virtualization

Introduction

KVM turns any modern Linux box into a Type-1-ish hypervisor using the kernel's own virtualization support. libvirt is the management layer on top — virsh, virt-install, and the API that tools like oVirt and Proxmox build on. This post gets you from nothing to a running, reachable VM.

Concepts

  • KVM — the kernel modules (kvm, kvm_intel / kvm_amd) that expose hardware virtualization to userspace.
  • QEMU — the userspace process that emulates the rest of the machine (disks, NICs, BIOS) and calls into KVM for CPU/memory.
  • libvirt — a daemon (libvirtd / the newer split virtqemud) and a stable API/CLI so you don't script QEMU directly.
  • A domain — libvirt's word for a VM. Defined by an XML file.

Hands-on

Check support and install

# CPU virtualization flag present?
grep -Eo 'vmx|svm' /proc/cpuinfo | sort -u

# Fast readiness check (install libvirt-clients first if missing).
virt-host-validate qemu

On RHEL/Rocky/Alma:

sudo dnf install -y qemu-kvm libvirt virt-install libvirt-daemon-config-network
sudo systemctl enable --now libvirtd
sudo usermod -aG libvirt "$USER"   # log out/in for group to take effect

On Debian/Ubuntu: sudo apt install -y qemu-kvm libvirt-daemon-system virtinst.

Create a VM from a cloud image

Cloud images boot fast and take a password/key via cloud-init:

IMG=/var/lib/libvirt/images
sudo curl -Lo $IMG/rocky9.qcow2 \
  https://download.rockylinux.org/pub/rocky/9/images/x86_64/Rocky-9-GenericCloud-Base.latest.x86_64.qcow2

# Give this VM its own disk backed by the base image.
sudo qemu-img create -f qcow2 -F qcow2 -b $IMG/rocky9.qcow2 $IMG/web1.qcow2 20G

sudo virt-install \
  --name web1 \
  --memory 2048 --vcpus 2 \
  --disk path=$IMG/web1.qcow2,format=qcow2 \
  --os-variant rocky9 \
  --network network=default,model=virtio \
  --graphics none \
  --cloud-init user-data=./user-data.yaml \
  --import

Minimal user-data.yaml:

#cloud-config
users:
  - name: admin
    sudo: ALL=(ALL) NOPASSWD:ALL
    ssh_authorized_keys:
      - ssh-ed25519 AAAA... you@laptop

--import skips the installer and boots the disk directly. --graphics none attaches the serial console; press Ctrl+] to detach.

Day-to-day with virsh

virsh list --all                    # every domain and its state
virsh start web1
virsh shutdown web1                  # graceful (ACPI)
virsh destroy web1                   # force off (like pulling power)
virsh console web1                   # serial console
virsh domifaddr web1                 # the VM's IP (from the DHCP lease)
virsh dumpxml web1                   # the full definition
virsh edit web1                      # edit XML, validated on save
virsh snapshot-create-as web1 pre-upgrade
virsh setmem web1 4G --live          # if memory ballooning is set up

Verification and troubleshooting

virt-host-validate qemu             # every check should say PASS
virsh net-list --all                # 'default' should be active + autostart
ssh admin@$(virsh domifaddr web1 | awk '/ipv4/{print $4}' | cut -d/ -f1)

Common problems:

  • virt-host-validate fails on "hardware virtualization" — enable VT-x/AMD-V in the BIOS/UEFI. On a cloud instance you need a bare-metal or nested-virt-capable instance type.
  • virsh says "failed to connect to the hypervisor" — you're not in the libvirt group yet (log out/in), or you want the system connection: export LIBVIRT_DEFAULT_URI=qemu:///system.
  • VM boots but has no network — the default network isn't started: virsh net-start default && virsh net-autostart default. Or the guest NIC model isn't virtio and the guest lacks the driver.
  • No IP from domifaddr — the guest got its lease before libvirt was watching; try --source arp, or check virsh net-dhcp-leases default.
  • Terrible disk performance — you used --disk ...,bus=sata. Use bus=virtio (the default with model=virtio networking) and cache=none on fast storage.
  • Can't reach the VM from other machines — the default network is NAT. For LAN-visible VMs, create a bridged network to the host's physical NIC.
PrabathStuck on something this site can't fix?Reach out to Prabath directly on LinkedIn.