Lightweight hypervisor
When managing servers either in a small shop or even at scale, Cockpit is a great solution. It even comes pre-installed on various fedora based distro's.
Today I will show you how to make a lightweight hypervisor out of your linux server by using the native qemu with virsh & cockpit as a management gui
Install Cockpit
Install Cockpit for server management
Cockpit is the best choice for a modern web-based UI that’s actively maintained and easy to use.
sudo apt update
sudo apt install cockpit cockpit-machines -y
sudo systemctl enable --now cockpitOnce installed, you can access the UI via:
👉 https://your-server-ip:9090
Configure VM with local lan IP
Overview
To put a VM directly on to the hosts LAN, we need to:
- Create a bridge (
br0) on the host. - Attach the physical interface (
enp0s31f6or whatever the actual NIC is) to the bridge. - Attach the VM to
br0.
Step 1: Create a Real Bridge (br0)
Find the physical interface name (e.g., enp0s31f6):
ip link showNow, create a Netplan config:
sudo nano /etc/netplan/51-net-bridge-cfg.yamlReplace its contents with:
network:
version: 2
bridges:
br0:
interfaces:
- enp0s31f6
dhcp4: yes
parameters:
stp: false
forward-delay: 0Summary:
- Creates
br0as a bridge. - Attaches
enp0s31f6(our physical interface). - Disables STP for faster networking.
- Gets an IP via DHCP, just like a real LAN device.
Apply the new network config:
sudo chmod 600 /etc/netplan/51-net-bridge-cfg.yaml
sudo netplan applyConfirm the bridge exists:
ip a show br0You should see it with an IP on your LAN.
Step 2: Attach the VM to br0
Run virt-install and use the existing br0 bridge:
sudo virt-install \
--name ubuntu-noble \
--memory 10000 \
--vcpus 4 \
--disk path=/home/sysadmin/cluster-mode/build/packer/ubuntu-cloud-image/output-noble/ubuntu-noble.img,format=qcow2 \
--os-variant ubuntu24.04 \
--import \
--network bridge=br0,model=virtio \
--noautoconsoleStep 3: Restart the VM
sudo virsh shutdown ubuntu-noble
sudo virsh start ubuntu-nobleCheck vm status
sudo virsh list --allonce the vm is up an running we need to configure the interface inside the vm.
Use virsh console to access vm
If your VM has a serial console configured, you can access it with:
virsh console <vm-name>Press Enter after connecting to see the login prompt. To exit, use Ctrl+].
Step 4: Configure the networking interface on the virtual machine
Run:
sudo nano /etc/netplan/00-installer-config.yamlPaste this:
network:
version: 2
ethernets:
enp1s0:
dhcp4: true
dhcp6: false
optional: true
nameservers:
addresses:
- 1.1.1.1This does the following:
- Enables DHCP for IPv4 (
dhcp4: true). - Marks the interface as optional, so the VM won’t hang on boot if DHCP is slow.
- Uses Cloudflare DNS.
Apply the Configuration
Run:
chmod 600 /etc/netplan/00-installer-config.yaml
sudo netplan applyConfiguration Script
You can copy the snippet below to apply the configurations we just described. Name servers are omitted because we handle them on the network level and dhcp will configure it.
Host script
TODO
VM script
cat <<EOF | sudo tee /etc/netplan/00-installer-config.yaml
network:
version: 2
ethernets:
enp1s0:
dhcp4: true
optional: true
EOF
chmod 600 /etc/netplan/00-installer-config.yaml
sudo netplan applyInside the VM, check its new IP:
ip ayou should now see it with an ip on the hosts lan.
Troubleshooting
Manually Bring Up the Interface Inside the VM
Try forcing the interface up inside the VM:
sudo ip link set enp1s0 up
sudo dhclient enp1s0Check again:
ip aIf dhclient successfully gets an IP, Libvirt’s DHCP is working.
Manually Request an IP
If you still don’t get an IP, force DHCP to assign one:
sudo dhclient enp1s0Now check again:
ip aFind the VM's IP
After booting the VM, check its assigned IP:
sudo virsh domifaddr ubuntu-nobleExample output:
Name MAC address Protocol Address
-------------------------------------------------------------------------------
vnet0 52:54:00:6b:3c:21 ipv4 192.168.122.50/24Now, SSH into the VM:
ssh [email protected]If domifaddr doesn’t show an IP, access the VM console and run:
ip aConfigure VM with virtual IP - UNVERIFIED
Check If virbr0 is Providing IPs
Run:
sudo virsh net-list --allIf you see:
Name State Autostart Persistent
--------------------------------------------
default active yes yesThen your default network is active and working.
If default is inactive, start it:
sudo virsh net-start default
sudo virsh net-autostart defaultCheck If Libvirt's DHCP Is Working
Run this on the host machine:
sudo virsh net-dumpxml default | grep -i rangeExpected output:
<range start='192.168.122.2' end='192.168.122.254'/>If nothing appears, the DHCP server is not running.
Restart the default network:
sudo virsh net-destroy default
sudo virsh net-start defaultThen, check if DHCP is handing out leases:
sudo cat /var/lib/libvirt/dnsmasq/default.leasesIf the file is empty, Libvirt’s DHCP is failing.
Attach the VM to virbr0
Run virt-install and use the existing virbr0 bridge:
sudo virt-install \
--name ubuntu-noble \
--memory 10000 \
--vcpus 4 \
--disk path=/home/sysadmin/cluster-mode/build/packer/ubuntu-cloud-image/output-noble/ubuntu-noble.img,format=qcow2 \
--os-variant ubuntu24.04 \
--import \
--network bridge=virbr0,model=virtio \
--noautoconsole- Network bridge=virbr0: use bridged mode to give the vm a native ip on the local lan.
dump the config with
sudo virsh dumpxml ubuntu-noble > my-vm.xml
# import with: sudo virsh define my-vm.xmlInside the VM, Replace Netplan Config
Run:
sudo nano /etc/netplan/00-installer-config.yamlPaste this:
network:
version: 2
ethernets:
enp1s0:
dhcp4: true
dhcp6: false
optional: true
nameservers:
addresses:
- 8.8.8.8
- 1.1.1.1🔹 This does the following:
- Enables DHCP for IPv4 (
dhcp4: true). - Disables IPv6 (
dhcp6: false) sincevirbr0usually doesn’t provide it. - Marks the interface as optional, so the VM won’t hang on boot if DHCP is slow.
- Uses Google & Cloudflare DNS.
Apply the Configuration
Run:
sudo netplan applyNow, check your network:
ip aIf everything is correct, you should see an IP like 192.168.122.X.
Alternative: Assign the VM a Static IP
If you want the VM to have a fixed IP, modify the network configuration inside the VM (/etc/netplan/ for Ubuntu).
Example netplan config inside the VM:
network:
version: 2
ethernets:
enp1s0:
dhcp4: no
addresses:
- 192.168.122.100/24
gateway4: 192.168.122.1
nameservers:
addresses: [8.8.8.8, 1.1.1.1]Then apply:
sudo netplan applyNow, the VM will always use 192.168.122.100.
Solution: Use iptables to Forward Ports
Since Libvirt uses NAT for virbr0, the VM is behind a virtual subnet (192.168.122.x). We’ll forward ports from the host to the VM, so you can access it like it's on your LAN.
Find Your VM's IP
Run this on the host:
sudo virsh domifaddr ubuntu-nobleExample output:
Name MAC address Protocol Address
-------------------------------------------------------------------------------
vnet0 52:54:00:6b:3c:21 ipv4 192.168.122.50/24👉 Take note of the VM’s IP (192.168.122.50).
To operate the vm with virsh some example commands
sudo virsh start <vm-name> # start
sudo virsh shutdown <vm-name> # graceful shutdown
sudo virsh destroy <vm-name> # forced shutdown
sudo virsh console <vm-name> # access the console
sudo virsh undefine <vm-name> # fully remove VM