Arch Linux KVM/libvirt VM Lab Guide

With br0 working, use libvirt/KVM + UEFI + qcow2 + VirtIO + VNC for installation, then install XFCE + xrdp inside each guest. This gives you VNC as a rescue/console connection and RDP for normal desktop use.

This guide uses Ubuntu 26.04, Rocky Linux 10, and AlmaLinux 10. For an Intel N200 host with 8 GB RAM, start each VM with 2 GB RAM / 2 vCPUs and avoid running all three heavily at once.

1. ISO and VM storage

Recommended layout:

/var/lib/libvirt/
├── iso/
│   ├── ubuntu-26.04-live-server-amd64.iso
│   ├── Rocky-10-x86_64-minimal.iso
│   └── AlmaLinux-10-x86_64-minimal.iso
└── images/
    ├── ubuntu.qcow2
    ├── rocky.qcow2
    └── alma.qcow2

Create the ISO directory:

sudo mkdir -p /var/lib/libvirt/iso
sudo chmod 755 /var/lib/libvirt/iso

VM disks will go in /var/lib/libvirt/images/.

Check ISOs:

ls -lh /var/lib/libvirt/iso/

Copy downloaded ISOs:

sudo cp ~/Downloads/*.iso /var/lib/libvirt/iso/

2. Create Ubuntu

sudo virt-install \
  --connect qemu:///system \
  --name ubuntu \
  --memory 2048 \
  --vcpus 2 \
  --cpu host-passthrough \
  --disk path=/var/lib/libvirt/images/ubuntu.qcow2,size=30,format=qcow2,bus=virtio \
  --cdrom /var/lib/libvirt/iso/ubuntu-26.04-live-server-amd64.iso \
  --network bridge=br0,model=virtio \
  --boot uefi \
  --graphics vnc,listen=127.0.0.1 \
  --noautoconsole

Check:

sudo virsh list --all
sudo virsh vncdisplay ubuntu

:0 means port 5900, :1 means 5901, and so on.

If VNC is listening only on localhost, tunnel it from another machine:

ssh -L 5900:127.0.0.1:5900 youruser@192.168.1.17

Connect the VNC client to 127.0.0.1:5900.

3. Create Rocky Linux

Use the exact ISO filename present in /var/lib/libvirt/iso/:

sudo virt-install \
  --connect qemu:///system \
  --name rocky \
  --memory 2048 \
  --vcpus 2 \
  --cpu host-passthrough \
  --disk path=/var/lib/libvirt/images/rocky.qcow2,size=30,format=qcow2,bus=virtio \
  --cdrom /var/lib/libvirt/iso/Rocky-10-x86_64-minimal.iso \
  --network bridge=br0,model=virtio \
  --boot uefi \
  --graphics vnc,listen=127.0.0.1 \
  --noautoconsole

Then:

sudo virsh vncdisplay rocky

If it reports :1, tunnel port 5901:

ssh -L 5901:127.0.0.1:5901 youruser@192.168.1.17

4. Create AlmaLinux

sudo virt-install \
  --connect qemu:///system \
  --name alma \
  --memory 2048 \
  --vcpus 2 \
  --cpu host-passthrough \
  --disk path=/var/lib/libvirt/images/alma.qcow2,size=30,format=qcow2,bus=virtio \
  --cdrom /var/lib/libvirt/iso/AlmaLinux-10-x86_64-minimal.iso \
  --network bridge=br0,model=virtio \
  --boot uefi \
  --graphics vnc,listen=127.0.0.1 \
  --noautoconsole

Then:

sudo virsh vncdisplay alma

Do not assume VNC display numbers stay fixed; always check with virsh vncdisplay.

5. After installation: remove/eject the ISO

Inspect disks:

sudo virsh domblklist ubuntu

Example:

Target   Source
--------------------------------------------------
vda      /var/lib/libvirt/images/ubuntu.qcow2
sda      /var/lib/libvirt/iso/ubuntu-26.04-live-server-amd64.iso

You can edit the VM with:

sudo virsh edit ubuntu

or use virsh change-media to eject the virtual CD-ROM after identifying its target.

6. Ubuntu: XFCE + RDP

Inside Ubuntu:

sudo apt update
sudo apt upgrade -y
sudo apt install xfce4 xfce4-goodies -y
sudo apt install xrdp -y
sudo systemctl enable --now xrdp
echo "startxfce4" > ~/.xsession
systemctl status xrdp

Find the guest IP:

hostname -I

Because the VM is attached to br0, it should receive a normal 192.168.1.x LAN address. Connect an RDP client to that IP on port 3389.

7. Rocky Linux: XFCE + RDP

Inside Rocky:

sudo dnf update -y
sudo dnf group list
sudo dnf search xfce

If the XFCE group is available:

sudo dnf group install "Xfce" -y

Install and enable xrdp if available:

sudo dnf install xrdp -y
sudo systemctl enable --now xrdp

If firewalld is enabled:

sudo firewall-cmd --permanent --add-port=3389/tcp
sudo firewall-cmd --reload

Set the XFCE session:

echo "startxfce4" > ~/.Xclients
chmod +x ~/.Xclients

Find the IP:

hostname -I

If Rocky 10 reports that XFCE or xrdp is unavailable, verify repository/package availability rather than adding arbitrary third-party repositories.

8. AlmaLinux: XFCE + RDP

Inside AlmaLinux:

sudo dnf update -y
sudo dnf group list
sudo dnf search xfce

Install the available XFCE group/packages, then:

sudo dnf install xrdp -y
sudo systemctl enable --now xrdp
sudo firewall-cmd --permanent --add-port=3389/tcp
sudo firewall-cmd --reload
echo "startxfce4" > ~/.Xclients
chmod +x ~/.Xclients

9. Why keep both VNC and RDP?

The VNC configured by virt-install --graphics vnc is the QEMU virtual console, not a VNC server running inside the guest. It can show UEFI, GRUB, the installer, boot failures and recovery screens even when guest networking is broken.

RDP/xrdp is better for everyday XFCE desktop access after the guest has booted.

So a useful setup is:

Arch host
   │
QEMU/libvirt VNC console
   │
Guest VM (Ubuntu/Rocky/Alma)
   │
XFCE + xrdp
   │
br0 → 192.168.1.x → RDP

Keep QEMU VNC as the rescue console and use RDP for normal GUI access.

10. virsh management commands

List all VMs:

sudo virsh list --all

List running VMs:

sudo virsh list

Start:

sudo virsh start ubuntu

Normal/ACPI shutdown:

sudo virsh shutdown ubuntu

Restart:

sudo virsh reboot ubuntu

Force power off:

sudo virsh destroy ubuntu

destroy does not delete the VM. It is comparable to pulling the power cord.

Pause:

sudo virsh suspend ubuntu

Resume:

sudo virsh resume ubuntu

11. VM autostart

Enable:

sudo virsh autostart ubuntu

Check:

sudo virsh dominfo ubuntu | grep Autostart

Disable:

sudo virsh autostart ubuntu --disable

With an 8 GB host, avoid autostarting all three guests unless their workloads are very light.

12. Delete a VM

A VM consists of its libvirt definition plus its virtual disk/storage.

virsh undefine alone removes the definition but can leave the qcow2 disk behind.

First shut down:

sudo virsh shutdown ubuntu
sudo virsh list --all

Inspect its storage:

sudo virsh domblklist ubuntu

To remove a UEFI guest and its managed storage completely:

sudo virsh undefine ubuntu --remove-all-storage --nvram

Warning: --remove-all-storage is destructive and deletes the VM's storage.

Verify:

sudo virsh list --all
ls -lh /var/lib/libvirt/images/

Quick reference

ActionCommand
List VMsvirsh list --all
Startvirsh start ubuntu
ACPI shutdownvirsh shutdown ubuntu
Restartvirsh reboot ubuntu
Force power offvirsh destroy ubuntu
Pausevirsh suspend ubuntu
Resumevirsh resume ubuntu
VNC displayvirsh vncdisplay ubuntu
VM informationvirsh dominfo ubuntu
Network interfacevirsh domiflist ubuntu
Virtual disksvirsh domblklist ubuntu
Edit configurationvirsh edit ubuntu
Enable autostartvirsh autostart ubuntu
Disable autostartvirsh autostart ubuntu --disable
Delete VM + diskvirsh undefine ubuntu --remove-all-storage --nvram

Recommended addition: QEMU Guest Agent

Install qemu-guest-agent inside Ubuntu, Rocky and AlmaLinux. It allows libvirt to communicate more cleanly with the running guest and improves VM management from the host.