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)

Windows Server 2025 Hosted by KVM

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 via virt-viewer or 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

🛸