If you’re still running VirtualBox or VMware on Linux, you’re leaving performance on the table. Fedora Workstation ships with KVM baked into the kernel — near-native performance, shared clipboard and file transfer over SPICE protocol, no license required. The tricky part is the initial setup, which gets confusing fast if you don’t understand how all the components fit together.
I’ve been using Fedora as my primary development machine for two years. Fedora 40 shipped QEMU 8.2 on day one — more conservative distros typically lag a few months behind. This article documents how I set up and optimize VMs, covering both Linux guests and Windows 11.
KVM, QEMU, libvirt, and Virt-manager — Understanding the Stack Before You Start
A lot of people mix these up. They’re actually four distinct layers:
- KVM (Kernel-based Virtual Machine): A Linux kernel module that turns your CPU into a type-1 hypervisor. Requires CPU virtualization support (Intel VT-x or AMD-V).
- QEMU: A hardware emulator — virtualizes CPU, RAM, disk, NIC, USB, and more. KVM accelerates QEMU using hardware virtualization.
- libvirt: A daemon that manages VMs and exposes a unified API. Both Virt-manager and
virshcommunicate through libvirt. - Virt-manager: A GUI frontend for libvirt — easy to use and feature-complete for daily use.
The full stack: Virt-manager → libvirt (libvirtd) → QEMU → KVM → CPU hardware
Checking Requirements and Installing
Step 1: Verify CPU Virtualization Support
egrep -c '(vmx|svm)' /proc/cpuinfo
Any result > 0 means you’re good. vmx is Intel VT-x, svm is AMD-V. If you get 0, go into your BIOS and enable virtualization first.
For a more thorough check:
virt-host-validate
This command checks KVM, IOMMU, and other prerequisites. Install the virt-manager package first if the command isn’t available yet.
Step 2: Install Required Packages
sudo dnf install -y @virtualization
The @virtualization group package pulls in everything you need: virt-manager, libvirt, qemu-kvm, bridge-utils, and related tools. Much simpler than installing each package individually.
To add CLI tools for creating and connecting to VMs from the terminal:
sudo dnf install -y virt-install virt-viewer
Step 3: Start and Enable libvirtd
sudo systemctl enable --now libvirtd
sudo systemctl status libvirtd
Step 4: Add Your User to the libvirt Group
This is the most commonly skipped step — and the one that causes the most annoying permission errors when opening Virt-manager:
sudo usermod -aG libvirt,kvm $(whoami)
Log out and back in for the group membership to take effect. Verify with:
groups | grep libvirt
Creating a Linux VM with Virt-manager
Creating a VM via GUI
Open Virt-manager and click File → New Virtual Machine. Select Local install media (ISO image or CDROM).
- Browse to your ISO file (e.g., Ubuntu 24.04 or Debian 12)
- Virt-manager will auto-detect the OS — if it can’t, select it manually from the dropdown
- Allocate RAM and CPU — 4GB RAM + 2 vCPUs is the minimum, 8GB makes development work much more comfortable
- Create a disk image — select Create a disk image for the virtual machine, sized at 30–50GB
- Review the network — the default NAT (default) is fine for VMs that need internet access
Check Customize configuration before install to make additional adjustments before booting.
Creating a VM Faster via CLI
virt-install \
--name ubuntu24 \
--memory 4096 \
--vcpus 2 \
--disk size=40 \
--cdrom /path/to/ubuntu-24.04.iso \
--os-variant ubuntu24.04 \
--network default \
--graphics spice \
--video qxl
List available os-variant values to use the correct one:
osinfo-query os | grep ubuntu
Installing a Windows 11 VM
Windows requires one extra step compared to Linux: installing VirtIO drivers so the installer can detect QEMU’s virtual disk and NIC. Without these drivers, the Windows installer won’t see any drives — discovering this after the fact wastes a lot of time.
Download the VirtIO Drivers ISO
wget https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso
Create the Windows VM with the Correct Configuration
virt-install \
--name windows11 \
--memory 8192 \
--vcpus 4 \
--disk size=80,bus=virtio \
--cdrom /path/to/Win11.iso \
--disk /path/to/virtio-win.iso,device=cdrom \
--os-variant win11 \
--network default,model=virtio \
--graphics spice \
--video qxl \
--tpm emulator,model=tpm-crb,version=2.0
The --tpm option is critical for Windows 11, which requires TPM 2.0. QEMU emulates TPM via swtpm:
sudo dnf install -y swtpm swtpm-tools
During Windows installation, when the installer asks for a drive and shows nothing: click Load driver → Browse to the virtio-win CDROM → navigate to the viostor/w11/amd64 folder → click OK. The disk will appear.
Optimizing VM Performance
Use VirtIO for Disk and Network
Virt-manager sometimes defaults to legacy emulation (IDE, e1000). Check and switch to VirtIO in the VM Details panel:
- Disk: Make sure the bus is set to
virtio, not IDE or SATA - NIC: Change the model from
e1000etovirtio
The difference is significant: sequential reads with VirtIO hit ~1.2 GB/s inside the VM, while IDE emulation tops out around 300–400 MB/s. You’ll notice it when compiling large projects or running a database.
For Linux VMs, VirtIO drivers are already in the kernel — no extra installation needed. For Windows, install them from the virtio-win ISO downloaded earlier.
CPU Pinning for Heavy Workloads
If you’re running a VM to compile code or do rendering, CPU pinning is worth trying. When the host OS and VM compete for the same cores, you get uneven latency spikes — pinning eliminates that:
# Check the host CPU topology
lscpu -e
# Pin the VM to cores 2-5 (keeping cores 0-1 for the host OS)
virsh vcpupin windows11 0 2
virsh vcpupin windows11 1 3
virsh vcpupin windows11 2 4
virsh vcpupin windows11 3 5
Fast Snapshots with virsh
# Create a snapshot before experimenting
virsh snapshot-create-as ubuntu24 snap-before-upgrade "Before kernel upgrade"
# List snapshots
virsh snapshot-list ubuntu24
# Roll back to a snapshot
virsh snapshot-revert ubuntu24 snap-before-upgrade
Creating a snapshot takes 2–3 seconds, and reverting is just as fast. I create one before any risky experiment on a VM — reinstalling from scratch takes over an hour, and that’s never worth it.
Managing VMs via CLI When There’s No GUI
# List all VMs
virsh list --all
# Start/stop a VM
virsh start ubuntu24
virsh shutdown ubuntu24
virsh destroy ubuntu24 # Force off, like pulling the power cord
# Connect to the console (for server VMs without a GUI)
virsh console ubuntu24
Troubleshooting Common Issues
“Cannot access storage file” Error When Starting a VM
The most common cause is a permission issue on the directory containing the disk image. libvirt runs as the qemu user, so the directory needs to be accessible:
sudo chown -R qemu:qemu /var/lib/libvirt/images/
sudo chmod 755 /var/lib/libvirt/images/
Storing disk images in a custom directory like /home/user/vms/? You need to add the SELinux context — this is a common pitfall on Fedora since SELinux is enabled by default:
sudo semanage fcontext -a -t virt_image_t "/home/user/vms(/.*)?"
sudo restorecon -Rv /home/user/vms/
VM Has No Internet Access
# Check if the default network is running
virsh net-list --all
# If the "default" network is inactive
virsh net-start default
virsh net-autostart default
Conclusion
After two years of daily use, KVM/QEMU on Fedora has never let me down. Linux VMs for testing scripts run smoothly, Windows VMs for proprietary software work well too — disk I/O with VirtIO is noticeably faster than VirtualBox, and CPU overhead is practically imperceptible for typical workloads.
The three things most likely to trip you up: forgetting to add your user to the libvirt group, not loading VirtIO drivers before installing Windows, and forgetting to start libvirtd. Hitting any one of these costs you 30 minutes of unnecessary debugging. Beyond that, Virt-manager is fairly intuitive — for more demanding workloads like CI/CD or network labs, dig into network bridges and storage pools next.

