libvirt is an open-source virtualization management library, daemon set and toolkit that provides one stable API for defining, starting, stopping, migrating and monitoring virtual machines, virtual networks and storage. In Linux virtualization, libvirt is the standard control layer above KVM and QEMU, and it also supports other drivers such as LXC containers, Xen and bhyve.
libvirt does not run guests itself. It translates management requests into hypervisor-specific actions, for example by building a QEMU command line, configuring cgroups and setting up bridges. Tools such as virsh, virt-manager, virt-install, Cockpit, OpenStack Nova and KubeVirt all build on it, which makes libvirt the common language of Linux virtualization management.
Architecture of the libvirt stack
The stack has three layers: a client library linked into management tools, one or more daemons that hold state and talk to the hypervisor, and hypervisor drivers that perform the actual work. Clients connect through a connection URI that names the driver, the scope and optionally a remote host.
Historically a single libvirtd daemon handled everything. Current distributions such as Fedora and RHEL 9 use modular daemons instead, one per responsibility, which reduces the privileges and attack surface of each component and allows them to be restarted independently.
| Daemon | Responsibility |
|---|---|
| virtqemud | QEMU and KVM virtual machines |
| virtnetworkd | Virtual networks, NAT and DHCP |
| virtstoraged | Storage pools and volumes |
| virtnodedevd | Host devices for passthrough |
| virtsecretd | Secrets such as disk encryption keys |
| virtnwfilterd | Network traffic filters for guests |
| virtproxyd | Compatibility endpoint for remote clients |
Domains, connection URIs and XML definitions
In libvirt terminology a virtual machine is a domain, and every object is described by an XML definition. A domain XML lists CPUs, memory, disks, network interfaces, firmware and devices. A domain can be persistent, defined permanently with virsh define, or transient, existing only while it runs.
The connection URI selects where and with what privilege a client operates. The table shows the most common forms.
| URI | Meaning | Typical use |
|---|---|---|
| qemu:///system | System-wide instance running as root | Servers, bridged networking, shared storage |
| qemu:///session | Per-user instance without root | Desktop VMs, development |
| qemu+ssh://host/system | Remote system instance over SSH | Managing other hosts securely |
| qemu+tls://host/system | Remote access with TLS certificates | Large fleets and automation |
| lxc:///system | LXC container driver | System containers managed like VMs |
The session instance cannot create bridges or access host devices without help, so guests started under it typically use user-mode networking. This distinction explains many cases where a VM created as an ordinary user cannot be reached from the network.
Networks, storage pools and everyday virsh commands
Besides domains, libvirt manages virtual networks and storage pools. The default network virbr0 provides NAT on 192.168.122.0/24 with DHCP and DNS served by dnsmasq, while bridged and macvtap modes connect guests directly to the physical network. Storage pools abstract directories, LVM volume groups, iSCSI targets, NFS shares and Ceph RBD images.
The command-line client virsh exposes almost the entire API. The following table lists the commands administrators use daily.
| Command | Action |
|---|---|
| virsh list –all | Show running and stopped domains |
| virsh start / shutdown | Boot a domain or request a clean guest shutdown |
| virsh destroy | Force off a domain immediately, like pulling the plug |
| virsh edit | Edit the domain XML with validation |
| virsh dumpxml | Print the current domain definition |
| virsh snapshot-create-as | Create a named snapshot |
| virsh migrate –live | Move a running domain to another host |
Note that `virsh destroy` does not delete anything; it only stops the guest abruptly. Removing the definition requires virsh undefine, and disk images are deleted only with the explicit --remove-all-storage option.
Comparison with neighboring virtualization components
libvirt is often confused with the components it manages. It is a management layer, while KVM is a kernel module and QEMU is the machine emulator that runs each guest as a process.
| Component | Layer | Role |
|---|---|---|
| KVM | Kernel | Hardware-assisted CPU and memory virtualization |
| QEMU | User space process | Device emulation and guest execution |
| Virtio | Paravirtual devices | Fast disk and network interfaces for guests |
| libvirt | Management | API, lifecycle, networking and storage control |
| virt-manager and Cockpit | User interface | Graphical front ends using the libvirt API |
| LXC | Containers | OS-level virtualization, also reachable through libvirt |
Running QEMU directly offers maximum flexibility for experiments, but loses persistent definitions, security labeling with SELinux or AppArmor through sVirt, cgroup placement and migration support. For anything beyond a quick test, libvirt is the recommended entry point.
Pitfalls in libvirt administration
Most operational problems stem from scope confusion, manual changes outside libvirt and storage handling. The following points summarize them.
- System versus session: a domain defined under one URI is invisible from the other, which looks like a missing VM.
- Editing XML files on disk: files under
/etc/libvirtare overwritten; changes belong invirsh editor the API. - Image permissions: sVirt labels disk images, so images in unusual directories may be denied access until labeled correctly.
- Snapshot types: internal qcow2 snapshots and external snapshots behave differently for backup and live migration.
- Default network conflicts: the 192.168.122.0/24 range may collide with an existing network and break routing.
A plain-language summary
A virtual machine is a computer that exists only in software. libvirt is the control desk for those software computers. It keeps a record of every machine, knows how much memory and disk each one has, and starts, stops or moves them on request.
Without it, every program that wanted to manage virtual machines would need to learn the details of each underlying engine. With it, all tools speak one common language, and the engine underneath can do the heavy lifting.
An example from practice
A mid-sized company runs about sixty internal virtual machines on four KVM hosts with shared Ceph storage. The administrators want to patch hosts during working hours without interrupting the accounting system, the wiki and the build servers.
Each host runs the modular libvirt daemons, and all guests use Virtio disks backed by an RBD storage pool, so every host can see every disk. Before patching a host, an automation script lists its domains with virsh and runs virsh migrate --live --persistent --undefinesource to move each one to the least loaded neighbor over qemu+ssh connections.
Users notice nothing beyond a sub-second pause during each migration. The host is updated, rebooted and returned to service, and maintenance no longer requires a weekend window.