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
br0showsNO-CARRIER: wrong NIC in bridge or cable in the other port. Fixinterfaces: [<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
haCLI 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 deprecatedgateway4. - 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=offor--os-variant generic. - Size must be specified → qcow2 path wrong or file not decompressed.
- q35 XML error → change
<controller model='pci-root'/>topcie-rootand 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
haCLI. - VirtIO for disk and NIC = better performance.
- Automate backups: qcow2 + XML + netplan.
Happy automating!