Setting Up KVM/libvirt Virtualization on Rocky Linux 9.6
Virtualization is a cornerstone of modern IT infrastructure, allowing you to run multiple operating systems on a single physical machine. In this guide, we'll walk through setting up KVM (Kernel-based Virtual Machine) with libvirt on Rocky Linux 9.6 (Blue Onyx). This setup includes:
- Installing required packages
- Configuring a network bridge (
br0) for external VM connectivity - Enabling IP forwarding
- Setting up external storage (optional but recommended)
- Creating various Linux and Windows VMs using
virt-install
Tested Environment
Linux toborrocky-osborne-pro-com 5.14.0-570.18.1.el9_6.x86_64
Rocky Linux 9.6 (Blue Onyx)
Step 1: Install Required Packages
First, enable the EPEL repository and install the virtualization stack:
sudo dnf install -y epel-release
sudo dnf install -y qemu-kvm libvirt virt-manager virt-install \
bridge-utils virt-top libguestfs-tools \
virt-viewer
Tools Explained
•qemu-kvm: Core hypervisor
•libvirt: Management daemon and tools
•virt-install: CLI tool for creating VMs
•virt-manager: GUI (optional but useful)
•bridge-utils: For managing network bridges
Step 2: Enable and Start libvirtd
sudo systemctl enable --now libvirtd
systemctl status libvirtd
Verify KVM modules are loaded:
sudo lsmod | grep kvm
# Should show kvm_intel or kvm_amd
Add your user to the libvirt group for non-root access:
sudo usermod -aG libvirt $USER
Log out and back in for group changes to take effect.
Step 3: Create a Network Bridge (br0) for External Access
By default, libvirt creates virbr0 (NAT), which does not allow VMs to be accessed externally.
We’ll create a bridged interface (br0) so VMs get real IPs on your network.
3.1 Define Variables
BR_NAME="br0"
BR_INT="$(ip route get 1.1.1.1 | awk '{print $5}')" # e.g., enp5s0
SUBNET_IP="$(hostname -I | cut -f1 -d' ')/24" # e.g., 10.0.0.100/24
GW="$(ip route | awk '/default/ {print $3}')" # Gateway IP
DNS1="1.1.1.2"
DNS2="1.0.0.2"
Replace DNS if needed (Cloudflare used here).
3.2 Enable IP Forwarding
sudo sysctl -w net.ipv4.ip_forward=1
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
3.3 Create the Bridge
sudo nmcli connection add type bridge autoconnect yes \
con-name ${BR_NAME} ifname ${BR_NAME}
3.4 Reconfigure Existing Interface
sudo nmcli con modify ${BR_INT} connection.id ${BR_INT}
sudo nmcli con down ${BR_INT} && sudo nmcli con up ${BR_INT}
sudo systemctl restart NetworkManager
3.5 Configure br0 with Static IP
sudo nmcli connection modify ${BR_NAME} \
ipv4.addresses ${SUBNET_IP} \
ipv4.gateway ${GW} \
ipv4.dns "${DNS1} ${DNS2}" \
ipv4.method manual
3.6 Enslave the Physical Interface
sudo nmcli connection delete ${BR_INT}
sudo nmcli connection add type bridge-slave autoconnect yes \
con-name ${BR_INT} ifname ${BR_INT} master ${BR_NAME}
3.7 Activate the Bridge
sudo nmcli connection up ${BR_NAME}
3.8 Test Connectivity
ping -I br0 1.1.1.1
If this fails:
nmcli con del br0 ${BR_INT}
Then reconnect via GUI → retry from Step 3.3.
Step 4: Configure libvirt to Use the Bridge
Allow QEMU to use custom bridges:
echo 'allow all' | sudo tee /etc/qemu-kvm/bridge.conf
sudo systemctl restart libvirtd
Set permissions:
sudo chown -R $USER:libvirt /var/lib/libvirt/
Step 5: (Optional) Use External Storage for VMs & ISOs
Mount large drives in /etc/fstab:
/dev/sdd1 /mnt/vm_hosts xfs defaults 0 2
/dev/sdb1 /mnt/iso_storage ext4 defaults 0 2
Create symlinks:
sudo rm -rf /var/lib/libvirt/images
sudo ln -s /mnt/vm_hosts /var/lib/libvirt/images
sudo ln -s /mnt/iso_storage /var/lib/libvirt/iso_storage
sudo chmod 666 /var/lib/libvirt/iso_storage/*
Now all VM disks go to fast external storage.
Step 6: Create Virtual Machines with virt-install
All VMs use:
• Bridge:br0
• Graphics: VNC (connect viavirt-vieweror VNC client)
• Disk format:qcow2(sparse, efficient)
Linux Examples
AlmaLinux 10
virt-install \
--name AlmaLinux10 \
--ram 2048 --vcpus 2 \
--disk path=/var/lib/libvirt/images/almalinux-10.img,size=40,format=qcow2 \
--os-variant centos-stream9 \
--network bridge=br0,model=virtio \
--graphics vnc,listen=0.0.0.0 \
--console pty,target_type=serial \
--location /var/lib/libvirt/iso_storage/AlmaLinux-10.0-x86_64-dvd.iso
Rocky Linux 9
virt-install \
--name RockyLinux \
--ram 2048 --vcpus 2 \
--disk path=/var/lib/libvirt/images/rocky.img,size=40,format=qcow2 \
--os-variant rocky9.0 \
--network bridge=br0,model=virtio \
--graphics vnc,listen=0.0.0.0 \
--console pty,target_type=serial \
--cdrom /var/lib/libvirt/iso_storage/Rocky-9.3-x86_64-dvd.iso
Ubuntu 24.04
virt-install \
--name Ubuntu24 \
--ram 3072 --vcpus 2 \
--disk path=/var/lib/libvirt/images/ubuntu-24.04.02.img,size=40,format=qcow2 \
--os-variant ubuntu24.04 \
--network bridge=br0,model=virtio \
--graphics vnc,listen=0.0.0.0 \
--console pty,target_type=serial \
--cdrom /var/lib/libvirt/iso_storage/ubuntu-24.04.2-live-server-amd64.iso
Kali Linux
virt-install \
--name Kali \
--ram 2048 --vcpus 2 \
--disk path=/var/lib/libvirt/images/kali-linux-2025.2.img,size=40,format=qcow2 \
--os-variant debian12 \
--network bridge=br0,model=virtio \
--graphics vnc,listen=0.0.0.0 \
--console pty,target_type=serial \
--cdrom /var/lib/libvirt/iso_storage/kali-linux-2025.2-installer-amd64.iso
Post-install (Kali):
sudo apt update && sudo apt install -y spice-vdagent qemu-guest-agent
Arch Linux
virt-install \
--name ArchLinux \
--ram 2048 --vcpus 2 \
--disk path=/var/lib/libvirt/images/archlinux-2025.06.01.img,size=40,format=qcow2 \
--os-variant archlinux \
--network bridge=br0,model=virtio \
--graphics vnc,listen=0.0.0.0 \
--console pty,target_type=serial \
--cdrom /var/lib/libvirt/iso_storage/archlinux-2025.06.01-x86_64.iso \
--boot cdrom,useserial=on
Windows Server Examples
Important: Windows needs VirtIO drivers during install.
Download VirtIO ISO
cd /var/lib/libvirt/iso_storage
wget https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso
cd ..
Windows Server 2022
virt-install \
--name WinServer2022 \
--ram 4096 --vcpus 2 \
--disk path=/var/lib/libvirt/images/winserver2022.img,size=50,format=qcow2 \
--os-variant win2k22 \
--network bridge=br0,model=virtio \
--graphics vnc,listen=0.0.0.0 \
--console pty,target_type=serial \
--cdrom /var/lib/libvirt/iso_storage/WindowsServer2022_x64FRE_en-us.iso \
--disk path=/var/lib/libvirt/iso_storage/virtio-win.iso,device=cdrom
Windows Server 2025
virt-install \
--name WinServer2025 \
--ram 4096 --vcpus 2 \
--disk path=/var/lib/libvirt/images/winserver2025.img,size=50,format=qcow2 \
--os-variant win2k22 \
--network bridge=br0,model=virtio \
--graphics vnc,listen=0.0.0.0 \
--console pty,target_type=serial \
--cdrom /var/lib/libvirt/iso_storage/WindowsServer2025_x64FRE_en-us.iso \
--disk path=/var/lib/libvirt/iso_storage/virtio-win.iso,device=cdrom
After first boot (Windows):
1. Open Device Manager
2. Update unknown drivers → Browse → Select E:\ (VirtIO CD)
3. Network will appear
Connect to VMs via VNC
Find VNC port:
virsh vncdisplay AlmaLinux10
# :0 → port 5900
# :1 → port 5901
Connect using:
virt-viewer --attach --wait AlmaLinux10
Or via VNC client: your-host-ip:5900
Management Tips
| Task | Command |
|---|---|
| List VMs | virsh list --all |
| Start VM | virsh start RockyLinux |
| Shutdown | virsh shutdown WinServer2022 |
| Force off | virsh destroy WinServer2022 |
| Console | virsh console AlmaLinux10 (Ctrl + ] to exit) |
| Delete VM | virsh undefine VMName --remove-all-storage |
Conclusion
You now have a production-ready KVM/libvirt environment with:
- External network access via
br0 - Efficient storage via symlinked disks
- Support for Linux, Windows, and niche distros
- CLI automation with
virt-install
Use virt-manager for GUI management or stick to virsh for scripting and automation.
Happy Virtualizing!
Tested and verified on Rocky Linux 9.6 — November 2025
ISOs should be placed in /var/lib/libvirt/iso_storage/
Adjust RAM, CPU, and disk size per your hardware