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 splitvirtqemud) 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-validatefails 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.virshsays "failed to connect to the hypervisor" — you're not in thelibvirtgroup yet (log out/in), or you want the system connection:export LIBVIRT_DEFAULT_URI=qemu:///system.- VM boots but has no network — the
defaultnetwork isn't started:virsh net-start default && virsh net-autostart default. Or the guest NIC model isn'tvirtioand the guest lacks the driver. - No IP from
domifaddr— the guest got its lease before libvirt was watching; try--source arp, or checkvirsh net-dhcp-leases default. - Terrible disk performance — you used
--disk ...,bus=sata. Usebus=virtio(the default withmodel=virtionetworking) andcache=noneon fast storage. - Can't reach the VM from other machines — the
defaultnetwork is NAT. For LAN-visible VMs, create a bridged network to the host's physical NIC.
Related tools and reading¶
- On-site: Subnet Calculator, Certificate Decoder.
- Related posts: libvirt networking: NAT vs bridged, cloud-init for VM templates.
Related tools
Stuck on something this site can't fix?Reach out to Prabath directly on LinkedIn.