Installing headless KVM VM on Ubuntu 24.04 + Home Assistant OS (HAOS): From “no network” to a clean VM — with fixes along the way

All steps were done on Ubuntu 24.04.2 LTS (headless) with libvirt/KVM and a bridged network. I end with a repeatable, EFI‑booting HAOS VM and a backup plan.

  • I use systemd‑networkd + Netplan bridge (br0 ) with a static IP on the host.
  • I install KVM/QEMU/Libvirt + OVMF (UEFI).
  • I import HAOS qcow2 and create the VM with UEFI, VirtIO (disk & NIC), bridge=br0, and VNC.
  • The HAOS CLI is on the graphical console (tty1) → I use VNC (or add a serial console explicitly).

HAOS requires EFI to boot.


1) Host networking: robust bridge for KVM

1.1 Identify the right NIC

If I have two physical ports, I make sure the cable is in the NIC I bridge. Check link:

ip link
# Look for RUNNING/LOWER_UP on e.g. enp2s0

1.2 Netplan bridge with static host IP

Create /etc/netplan/01-netcfg.yaml :

network:
  version: 2
  renderer: networkd
  ethernets:
    enp2s0:          # <-- my active NIC
      dhcp4: no
  bridges:
    br0:
      interfaces: [enp2s0]
      addresses:
        - 192.168.0.10/24
      nameservers:
        addresses: [192.168.0.1, 8.8.8.8]
      routes:
        - to: default
          via: 192.168.0.1
      parameters:
        stp: false
        forward-delay: 0

Apply & verify:

sudo netplan --debug generate
sudo netplan apply
ip a show br0
ip route
ping 192.168.0.1

Common pitfalls & fixes

  • br0 shows NO-CARRIER : wrong NIC in bridge or cable in the other port. Fix interfaces: [<nic>] and/or move the cable.
  • NetworkManager slows boot / interferes: disable it on servers.
sudo systemctl disable --now NetworkManager

2) Install KVM + libvirt + OVMF (UEFI)

sudo apt update
sudo apt install -y qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virtinst ovmf
sudo usermod -aG libvirt,kvm $USER
newgrp libvirt

egrep -c '(vmx|svm)' /proc/cpuinfo     # >0 means HW virtualization
systemctl status libvirtd

3) Get the HAOS qcow2

sudo mkdir -p /var/lib/libvirt/images/hassos
cd /var/lib/libvirt/images/hassos

wget https://github.com/home-assistant/operating-system/releases/download/16.2/haos_ova-16.2.qcow2.xz
unxz haos_ova-16.2.qcow2.xz

sudo chown libvirt-qemu:kvm haos_ova-16.2.qcow2
sudo chmod 0644 haos_ova-16.2.qcow2

4) Create the VM (EFI, VirtIO, Bridge, VNC)

virt-install \
  --name homeassistant \
  --description "Home Assistant OS" \
  --memory 4096 --vcpus 2 \
  --disk path=/var/lib/libvirt/images/hassos/haos_ova-16.2.qcow2,format=qcow2,bus=virtio \
  --network bridge=br0,model=virtio \
  --graphics vnc,listen=127.0.0.1 --video virtio \
  --import \
  --boot uefi \
  --osinfo detect=on,require=off
  • Why EFI? HAOS won’t boot without EFI/UEFI.
  • Why VNC? HAOS’s interactive ha CLI is on the graphical console (tty1), not on the serial console.

5) Open the VNC console (securely)

virsh vncdisplay homeassistant
# Example: :0  → port 5900 on the host

ssh -L 5900:127.0.0.1:5900 adm-simon@ha-server
vncviewer localhost:5900

You might need to install vncviewer on your client computer.


6) Give HAOS a fixed IP (inside the guest)

While connected with vncviewer to the homeassistant VM:

login
ha network info
ha network update enp0 ipv4.method static \
  ipv4.address 192.168.0.50/24 \
  ipv4.gateway 192.168.0.1 \
  ipv4.dns 192.168.0.1
ha network apply

Then open http://192.168.0.50:8123 .


7) Problems I hit — and how I fixed them

7.1 Host loses SSH after netplan apply

  • Wrong NIC in bridge → fix interfaces: [<nic>] .
  • Use routes: instead of deprecated gateway4 .
  • Disable NetworkManager.

7.2 DHCP reservation ignored after bridging

  • Reservation tied to physical NIC MAC, but bridge uses its own MAC.
  • Fix: static IP for br0 .

7.3 br0 is NO-CARRIER

  • Cable in wrong port → move cable or change NIC in YAML.

7.4 Slow boot: systemd-networkd-wait-online

  • Limit to br0 :
sudo systemctl edit systemd-networkd-wait-online.service
[Service]
ExecStart=
ExecStart=/lib/systemd/systemd-networkd-wait-online --interface=br0 --timeout=10

7.5 Desktop kept suspending the server

Don’t ask me why, but while trying around with virsh, at some point I decided to install a UI on my server in order to use the UI of KVM instead of command line. Bad idea on a server…

  • Remove GNOME after network is stable:
sudo systemctl set-default multi-user.target
sudo apt purge -y gdm3 gnome-shell gnome-session gnome-control-center gnome-terminal xorg* lightdm*
sudo apt autoremove --purge -y

7.6 virsh console shows nothing

  • HAOS CLI is on VGA (tty1), not serial → use VNC.

7.7 VM doesn’t appear in DHCP/ARP

  • HAOS didn’t boot (no EFI) or NIC model mismatch.
  • Fix: enable EFI and use VirtIO NIC.

7.8 virt-install errors

  • OS name required → add --osinfo detect=on,require=off or --os-variant generic .
  • Size must be specified → qcow2 path wrong or file not decompressed.
  • q35 XML error → change <controller model='pci-root'/> to pcie-root and add VirtIO-SCSI.

8) Backup & Disaster Recovery

Backup

virsh shutdown homeassistant
virsh dumpxml homeassistant > /backup/homeassistant.xml
tar czf /backup/homeassistant.qcow2.tgz /var/lib/libvirt/images/hassos/haos_ova-16.2.qcow2
sudo cp /etc/netplan/*.yaml /backup/
sudo cp -r /etc/libvirt /backup/libvirt-config
rsync -avz /backup/ user@nas:/srv/backup/ha-server/

Restore

sudo apt install -y qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virtinst ovmf
sudo cp /backup/*.yaml /etc/netplan/
sudo netplan apply
sudo cp -r /backup/libvirt-config/* /etc/libvirt/
sudo cp /backup/homeassistant.qcow2 /var/lib/libvirt/images/hassos/
virsh define /backup/homeassistant.xml
virsh start homeassistant

Key Lessons Learned for me

  • EFI/OVMF is mandatory for HAOS.
  • Use VNC for initial setup; serial console won’t show ha CLI.
  • VirtIO for disk and NIC = better performance.
  • Automate backups: qcow2 + XML + netplan.

Happy automating!

2 Likes

Hi there I have tried your guide and it turned out successful for me in my mac mini running ubuntu server. I really appreciate your work and sharing it here. I was wondering if you have tried installing this in ubuntu desktop with wifi. I have tried and was able to run the VM but when it came to some addons like home assistant matter hub, it was not able to connect to the devices. Hope you would share your experience.

When you say “devices” are you referring to Matter/Thread devices, or are you referring to USB Thread sticks?

I am referring to this addon GitHub - t0bst4r/home-assistant-matter-hub: Publish your Home-Assistant Instance using Matter. which doesn’t need any usb devices.