Install the stack
sudo pacman -S qemu-desktop virt-manager gnome-boxes dnsmasq iptables-nft libvirt edk2-ovmf
The edk2-ovmf package gives you UEFI firmware images for guest VMs; without it, only BIOS boots work. iptables-nft is the nftables-compatible iptables frontend that modern libvirt expects (the original iptables AUR package pulls in the legacy binary; don't mix them).
Enable libvirtd
sudo systemctl enable --now libvirtd.service
sudo systemctl status libvirtd.service
Let your user manage libvirt without sudo
Drop in a polkit rule so members of the libvirt group can manage VMs:
sudo tee /etc/polkit-1/rules.d/50-libvirt.rules <<'EOF'
polkit.addRule(function(action, subject) {
if (action.id == "org.libvirt.unix.manage" &&
subject.isInGroup("libvirt")) {
return polkit.Result.YES;
}
});
EOF
sudo groupadd --system libvirt 2>/dev/null || true
sudo gpasswd -a "$USER" libvirt
# log out and back in so the group membership applies
Alternatively, most distros ship a pre-existing kvm group — use that if it's the one your kernel has already granted /dev/kvm access to (check with ls -l /dev/kvm).
Bring up the default libvirt network
This is the NAT-based network that virt-manager uses out of the box. If it isn't already running:
sudo virsh net-list --all
# If the 'default' network isn't listed:
sudo virsh net-define /usr/share/libvirt/networks/default.xml
# Start it and set it to autostart:
sudo virsh net-start default
sudo virsh net-autostart default
Confirm you now have a virbr0 interface:
ip addr show virbr0
You should see 192.168.122.1/24 (the default libvirt subnet). Guests attached to this network get an IP via libvirt's embedded dnsmasq and can reach the internet through NAT.
Enable the QEMU bridge helper (for non-root bridging)
This allows unprivileged QEMU processes to attach a tap device to your bridge — important for gnome-boxes, which doesn't use libvirt and can't use privileged bridging:
sudo mkdir -p /etc/qemu
sudo tee /etc/qemu/bridge.conf <<'EOF'
allow virbr0
EOF
sudo chmod 644 /etc/qemu/bridge.conf
# Make qemu-bridge-helper setuid so unprivileged users can invoke it
sudo chmod u+s /usr/lib/qemu/qemu-bridge-helper
The bridge-helper only needs CAP_NET_ADMIN, but chmod u+s makes it fully setuid-root. On a personal desktop this is fine. In a multi-user environment consider granting the capability instead: sudo setcap cap_net_admin+ep /usr/lib/qemu/qemu-bridge-helper.
For a real bridge to your LAN (not libvirt NAT)
If you want the VMs to get addresses directly from your home/office router rather than libvirt's subnet, the extra step is creating a Linux bridge that slaves your physical NIC:
# With systemd-networkd:
sudo tee /etc/systemd/network/10-br0.netdev <<'EOF'
[NetDev]
Name=br0
Kind=bridge
EOF
sudo tee /etc/systemd/network/20-br0-bind.network <<'EOF'
[Match]
Name=enp3s0 # your actual NIC
[Network]
Bridge=br0
EOF
sudo tee /etc/systemd/network/30-br0.network <<'EOF'
[Match]
Name=br0
[Network]
DHCP=yes
EOF
sudo systemctl enable --now systemd-networkd
In virt-manager, edit a VM → NIC → set network source to "Bridge device..." and name br0. The VM now lives on your LAN directly.
Verify
sudo virsh net-list --all— the default network should be active and autostart.ip link show type bridge— at leastvirbr0, plusbr0if you set one up.- Inside a guest:
ip route get 1.1.1.1— should return via the bridge IP. - From the host:
ping <guest-ip>— should work now that host and guest share a subnet.