Episode 1 of the InventiveHQ KVM virtualization series. Start here, then continue through guest creation, administration, storage, and networking.
This guide turns a clean Ubuntu server into a working KVM and libvirt virtualization host. We will verify hardware acceleration first, install QEMU and libvirt, authorize a normal administrator account, prepare private NAT networking, and validate the finished host.
We deliberately stop before creating a virtual machine. That gives this first lesson one clear result: a host that is ready for the first guest in Episode 2.
Lab verified July 2026 · Ubuntu 26.04 LTS · libvirt 12.0.0 · QEMU 10.2.1
Already have a working host? Use the command builder to construct safe inspection and lifecycle commands before changing it. Start by inventorying its guests, networks, storage pools, and current connection URI.
What KVM, QEMU, libvirt, and virsh do
The components form a stack rather than four names for the same product:
- CPU virtualization supplies Intel VT-x/VMX or AMD-V/SVM hardware instructions.
- KVM exposes those instructions through the Linux kernel.
- QEMU runs each guest process and supplies its virtual hardware.
- libvirt manages QEMU guests, networks, storage, and policy through a consistent service and API.
- virsh is the command-line client for libvirt.
The commands in this series use the host-wide qemu:///system libvirt connection. A default libvirt network gives future guests private DHCP and NAT without putting them directly on the physical LAN.
Before you begin
You need:
- An Ubuntu server with an account that can run
sudo - Intel VT-x/VMX or AMD-V/SVM exposed to Linux
- Internet or configured Ubuntu repository access
- A new login session after changing group membership
- A maintenance window if the server already runs workloads
If Ubuntu itself is a virtual machine, the outer hypervisor must expose nested virtualization. Package installation cannot compensate for missing processor support.
Quick installation checklist
These are all commands used in the walkthrough. Read the detailed sections before applying them to a shared or production server.
# 1. Check hardware support
lscpu | grep -E 'Virtualization|Hypervisor vendor'
grep -Eoc '(vmx|svm)' /proc/cpuinfo
ls -l /dev/kvm
# 2. Install the host stack
sudo apt update
sudo apt install -y cpu-checker qemu-system-x86 libvirt-daemon-system libvirt-clients virtinst
kvm-ok
# 3. Start and inspect libvirt
sudo systemctl enable --now libvirtd
systemctl is-active libvirtd
virsh --connect qemu:///system version
# 4. Authorize the current account
sudo adduser "$USER" libvirt
sudo adduser "$USER" kvm
# Log out completely and sign back in before continuing
id
virsh --connect qemu:///system list --all
# 5. Prepare the private network
virsh net-list --all
virsh net-start default # Run only if default is inactive
virsh net-autostart default
virsh net-info default
# 6. Validate the completed host
sudo virt-host-validate qemu
virsh --connect qemu:///system uri
ls -ld /var/lib/libvirt/images
1. Verify hardware virtualization
Start by asking Linux which virtualization capabilities it can see:
lscpu | grep -E 'Virtualization|Hypervisor vendor'
On Intel hardware, look for VT-x; on AMD hardware, look for AMD-V. A nested lab may also report its outer hypervisor:
Virtualization: VT-x
Hypervisor vendor: KVM
Count the VMX or SVM flags visible to Linux:
grep -Eoc '(vmx|svm)' /proc/cpuinfo
Any positive count means at least one logical processor exposes the instructions. The exact number depends on the host's CPU allocation. Then inspect the KVM device:
ls -l /dev/kvm
Expected shape:
crw-rw---- 1 root kvm 10, 232 ... /dev/kvm
Stop if the flag count is zero or /dev/kvm is absent. On physical hardware, enable virtualization in BIOS or UEFI. In a guest, enable nested virtualization on the outer hypervisor and expose a compatible CPU model.
2. Install KVM, QEMU, libvirt, and virt-install
Refresh the Ubuntu package index:
sudo apt update
Install the complete host stack used in this series:
sudo apt install -y cpu-checker qemu-system-x86 libvirt-daemon-system libvirt-clients virtinst
Each package has a specific purpose:
| Package | Purpose |
|---|---|
cpu-checker | Provides Ubuntu's kvm-ok validation command |
qemu-system-x86 | Runs x86 virtual machine processes |
libvirt-daemon-system | Installs the system-wide libvirt service and configuration |
libvirt-clients | Provides virsh and host validation clients |
virtinst | Provides virt-install, used to create guests in Episode 2 |
This guide uses qemu-system-x86 because it is available on the tested Ubuntu 26.04 LTS host; the older qemu-kvm convenience package has no installation candidate there. Do not blindly mix package instructions from different Ubuntu releases.
Now run Ubuntu's focused acceleration check:
kvm-ok
Expected output:
INFO: /dev/kvm exists
KVM acceleration can be used
3. Start libvirt and verify the connection
Enable the compatibility service at boot and start it now:
sudo systemctl enable --now libvirtd
Confirm that systemd reports it active:
systemctl is-active libvirtd
Expected output:
active
Ubuntu may activate modular libvirt daemons and sockets behind this service. If a future Ubuntu release uses only modular daemon units, follow that release's documented service names while continuing to use the same system libvirt URI.
Ask virsh to connect explicitly and print all relevant versions:
virsh --connect qemu:///system version
Our lab returned:
Compiled against library: libvirt 12.0.0
Using library: libvirt 12.0.0
Using API: QEMU 12.0.0
Running hypervisor: QEMU 10.2.1
Version numbers will vary. The important evidence is a successful qemu:///system connection rather than an authentication or socket error.
4. Configure non-root administrator access
Add the current account to Ubuntu's libvirt and KVM groups:
sudo adduser "$USER" libvirt
sudo adduser "$USER" kvm
Expected result for each command:
Adding user ... to group ...
Done.
Log out completely and sign back in now. Linux captures supplementary groups when a login session starts; merely opening another tab may retain the old group list.
Verify both groups appear:
id
The output should include kvm and libvirt. Then test the system connection without sudo:
virsh --connect qemu:///system list --all
An empty domain table is correct on a clean host:
Id Name State
--------------------
Do not work around a permission error with chmod 777 on libvirt sockets. Use the distribution's groups or polkit policy. Access to system libvirt is privileged: an authorized user can control host resources and virtual machines.
5. Prepare the default private network
Inventory libvirt networks before changing them:
virsh net-list --all
A fresh installation normally contains a persistent network named default. It may initially be inactive:
Name State Autostart Persistent
------------------------------------------------
default inactive no yes
Start it only when it is inactive:
virsh net-start default
Enable it after future host reboots:
virsh net-autostart default
Inspect the result:
virsh net-info default
Expected fields:
Name: default
Active: yes
Persistent: yes
Autostart: yes
Bridge: virbr0
The default network normally provides private DHCP and NAT through virbr0. It does not modify the production interface or make guests first-class members of the physical LAN. Bridged networking has separate routing, firewall, redundancy, and remote-access risks and belongs in its own planned change.
6. Validate the completed KVM host
Run libvirt's broader QEMU host validation:
sudo virt-host-validate qemu
At minimum, the checks relevant to this lab should pass:
QEMU: Checking for hardware virtualization : PASS
QEMU: Checking if device /dev/kvm exists : PASS
QEMU: Checking if device /dev/vhost-net exists : PASS
QEMU: Checking if device /dev/net/tun exists : PASS
Read every warning in the context of the intended workload. For example, optional IOMMU or secure-guest capabilities may warn inside a nested lab without preventing ordinary KVM guests. A warning should be understood, not automatically ignored.
Prove which URI virsh opened:
virsh --connect qemu:///system uri
Expected output:
qemu:///system
Finally, verify the standard libvirt image directory exists:
ls -ld /var/lib/libvirt/images
The owner, permissions, and timestamps can vary, but the directory should exist. Do not loosen its permissions simply to make manual file copying easier; use libvirt storage management and appropriate administrative access.
Troubleshooting
grep returns 0 or /dev/kvm is missing
The operating system cannot see hardware virtualization. Enable Intel VT-x or AMD-V in firmware, or expose nested virtualization from the outer hypervisor. Reboot if the firmware or outer-host setting requires it, then repeat all three hardware checks.
kvm-ok says KVM acceleration cannot be used
Check the CPU flags, /dev/kvm, and loaded modules:
lsmod | grep kvm
sudo dmesg | grep -i kvm
On a physical server, firmware settings are the most common cause. In a VM, verify nested virtualization and CPU passthrough or an appropriate virtual CPU model.
Unable to connect to libvirt or no socket is available
Inspect the service and recent logs:
systemctl status libvirtd --no-pager
sudo journalctl -u libvirtd -n 100 --no-pager
Also confirm that the requested URI is qemu:///system. Service unit names may differ if the distribution uses only modular libvirt daemons.
virsh works with sudo but fails as your account
Run id. If kvm and libvirt are absent, log out completely and back in. If they are present, inspect the socket and the distribution's polkit rules rather than weakening permissions.
The default network does not exist
First confirm you are on the system connection:
virsh --connect qemu:///system uri
virsh --connect qemu:///system net-list --all
If no default network was installed, use the distribution's packaged default network definition or create a deliberate network configuration. Do not copy an arbitrary XML definition onto a host without checking its subnet against existing physical, VPN, container, and virtual networks.
The default network is already active
Do not run virsh net-start default again. Continue with virsh net-autostart default and virsh net-info default.
Rollback and cleanup
Do not remove virtualization packages from a host that contains guests until you have inventoried and backed up its domain definitions, storage, networks, and secrets. On a brand-new disposable host with no guests, you can stop and disable the compatibility service:
sudo systemctl disable --now libvirtd
You can also remove your own group memberships, then log out and back in:
sudo deluser "$USER" libvirt
sudo deluser "$USER" kvm
Package removal is intentionally not presented as a universal copy-and-paste rollback. APT may identify dependencies for autoremove, while /var/lib/libvirt can contain valuable guest definitions, storage, networking state, and security material. Review those resources and APT's proposed transaction before approving any removal.
Download the tested scripts
The public InventiveHQ KVM Lab repository contains the Episode 1 commands, validation helpers, expected output, and repeatable lab files. The fixed episode-01-v1 tag keeps this article tied to the version used for the video.
Next, keep this host available for Episode 2. We will create the first Ubuntu guest with a cloud image, cloud-init, QEMU guest-agent access, and a serial recovery console.