Install Home Assistant OS with KVM on Ubuntu headless (CLI only)

For anyone who’s had their VM crash and not restart, I found my config in /etc/libvirt/qemu after following the directions in this thread.

Edit your hassos.xml.



And replace it with:


Now if your HASSOS dies in the middle of the night you won’t wake up to a dead automation system.

Haven’t figured out what caused it yet, but putting this band-aid on took some digging so I thought I’d share it.

You can also edit the nearby line to make it start on reboot, but I had already done that with a CLI command.

1 Like

I had not thought about that scenario.
I was curious if this could also be done using virsh… turns out you can (My domain name is hassio, so substitute yours if different):

  • virsh set-lifecycle-action hassio crash restart --config
  • virsh set-lifecycle-action hassio crash restart --live

The first one changes the domain’s xml file for you, the second one presumably acts on the Domain/VM while its running. There are also some core-dump options too (not shown).


@Aephir First things first, thank you for putting together this guide. I’ve outgrown my RPi4 and will give try following your step-by-step instructions on my recently purchased mini pc.

I noticed that you mention in an earlier post that you have upgraded to Ubuntu 22.04. Have you had any success getting this to work on Ubuntu server 22.04 LTS?

Sort of. It works, but I didn’t install on 22.04, just upgraded from 20.04 after installing, so can’t say if there would be changes for the actual install.

But please let me know how it works if you try!

@Aephir thanks so much for this guide!

I installed on Ubuntu 22.04, but I had to add
--osinfo detect=on,require=off

to bypass the os-variant requirement.

Additionally, you should add that the qcow2 file should either be in the same directory (var/lib/libvirt/images/hassos-vm) or else reference the full path in the --disk arg.

1 Like

@Aephir I followed your guide and was able to install HAOS in Ubuntu server 22.04 LTS using kvm. Once I got it up and running, I simply restored a full backup of my RPi4 HAOS. One caveat, I haven’t moved my zwave stick over yet. I will do that next.

Below are some notes from my experience that may be of interest to others.

  1. I am running this VM on a Beelink EQ12 which has two LAN ports that I want to pass through to the VM. So I used a slightly different /etc/netplan/00-installer-config.yaml file. See below.
# This is the network config written by 'subiquity'
      dhcp4: true
      dhcp4: false
  version: 2
      dhcp4: true
        - enp1s0
        stp: true
      dhcp4: false
        - enp2s0
        addresses: []
        stp: true
  1. When I applied the netplan above, Ubuntu 22.04 assigned a new mac address to the bridge br0. This is really strange because I expected it to be the same as the mac address for enp1s0. After some googling around I found that this issue is associated with Ubuntu 22.04 but no one seems to know exactly why. In any event, the original mac address can be cloned on the bridge by doing the following.
    Change the macaddresspolicy in /usr/lib/systemd/network/ from persistent to none.
    This is important because I want my router to assign a static ip address based on the mac address of enp1s0.
  2. To install the VM, I used the following command. Note that I manually assign mac addresses to the VM’s LAN ports. Again, this is because I want to be able to assign static ip addresses using mac addresses. Also, I followed the approach suggested by @poiromaniax and used --osinfo detect=on,require=off.
virt-install --import --name haos --description "Home Assistant OS" --osinfo detect=on,require=off --ram=3072 --vcpus=2 --disk /var/lib/libvirt/images/haos-vm/haos_ova-10.3.qcow2,bus=virtio --network bridge=br0,model=virtio,mac=52:54:00:B9:7A:01 --network bridge=br1,model=virtio,mac=52:54:00:B9:7A:02 --graphics none --noautoconsole --boot uefi
  1. I followed the instructions provided by @brady, namely to create the /etc/docker/daemon.json file and restart docker. But when I went to restart docker, I got a message saying that the service didn’t exist: Failed to restart docker.service: Unit docker.service not found.. It didn’t seem to interfere with anything I was doing.

  2. I found that I needed to install the virtinst package.

1 Like

Thanks @Cold-Lemonade , @poiromaniax . I have added a few comments and changes as per your suggestions.

1 Like

OS: Ubuntu 23.04 Server

  • Beelink SEi12 Pro
  • Zooz z-wave stick 700

I followed the updated tutorial step by step and got it working almost effortlessly. I did bump into problems in step 2.1 as I’m not using docker and have no idea what that step is supposed to do. I skipped it and all is well. Thank you all, especially @Aephir.

I did notice that XRDP completely broke after setting up the network bridge. I modified the netplan config as follows and all is well again.

# This is the network config written by 'subiquity'
      dhcp4: true
  version: 2
      dhcp4: yes
             - enp3s0
        stp: true
        - to:
          via: # Your IP Gateway, run: 'ip route | grep default'
1 Like

@Aephir forgot to also mention (and because I totally borked my machine I had to reinstall)

Ubuntu 22.04 (havent checked earlier releases), also need to install virt-manager package. May want to add that into your installation command in step 1.1

Also, am I the only one that has: “start job is running for Wait for Network” on startup

For docker, editing the docker.service worked but not creating the etc/docker/daemon.json

1 Like

I typically don’t look during startup (everything running headless, I only SSH into the machine), but I do seem to remember this from way back when I had a monitor connected. I think it’s just that your network startup is slower than whatever start job that is set to require/wait for network. Nothing to be alarmed about, it just (as far as I know) pauses the start job until network is up and running.

1 Like

If you don’t mind me asking, what does not work if virt-manager package is not installed? My thought is that virt-manager is not needed for a setup that only uses cli (virsh/virt-install). As a note, I do use virt-manager and a desktop, so just curious.

When I tried virt-install without installing extras, it came back with Command Not Found

After googling around, I learned that virt-manager is the way to install this

OK I see, thanks.
I’m looking at some notes I took during my installation, and virt-manager installs virtinst, and virt-viewer, so I think in theory instead of installing virt-manger one can simply install virtinst.

1 Like

@Aephir After my success getting this work on Ubuntu 22.04 LTS Server, I decided to install Ubuntu 23.04 Server on my mini pc so I had to start all over. Good news, I got it working by following your steps. Like @luis-godinez, I skipped Step 2.1 and didn’t have any problems. Also, like @wmaker, I had to install virtinst.

In case anyone else tries to do this on Ubuntu 23.04 Server, I should note that there is a weird bug in the 00-installer-config.yaml used for configuring netplan on this version of Ubuntu. To address this bug, I had to change the permissions for this file using chmod 700. Also, their earlier change to the MACAddressPolicy that I described in an earlier post will not prevent the kernel from assigning a different mac address to the bridge. I had to manually assign the physical ethernet interface’s mac address to the bridge in the 00-installer-config.yaml.

While everything worked without issue, when I enabled by ufw firewall on the host computer, it completely cut off the virtual machine running HAOS. Does anyone have any insight into what ufw rules I need to add to allow the vm to access the network? With ufw enabled, my router cannot even assign an ip address to the vm because it cannot see it.

Has anyone got this working with ufw?

Hope you don’t mind me asking (I’m trying to understand your networking config) but do I have this correct, that you are trying to get your Ethernet interface (enp1s0) and the Bridge interface (br0, which is using enp1s0) to have the same MAC? And you are trying to have an IP address assigned by DHCP to both interfaces? And you want DHCP to use the MAC to assign an IP address? Wouldn’t this result in two interfaces with the same IP address?

Hi @wmaker.

I want the host and the vm to have separate ip addresses and that is currently working.

Both ip addresses are assigned using dhcp by the router. When I first install the vm, my virsh command manually assigns the vm a different mac address for its virtual ethernet interface (vnet0) than the one I manually assigned the bridge (br0) in netplan. Because they have different mac addresses, the router assigns them different ip addresses (or so I surmise given my very basic understanding of networking). The context for all of this is that Frigate NVR is running in a container on the host and HAOS running in a vm on the host. I want to be able to access these applications through separate ip address.

I have it set up and working with two separate ip addresses. The problem is that when I enable ufw on the host, it blocks the vm from accessing the network and so HA is cut off from everything. My host’s ufw rules are very restrictive so I am trying to figure out what rules to add to allow the vm access to the network via vnet0.

I hope this explanation makes better sense.

I think I have found a solution to the problem of ufw blocking the vm running HAOS. I assigned a static ip address to the virtual ethernet interface (vnet0) in my router using the mac address that I manually assigned when I created the vm. Then I set up forwarding rules in /etc/ufw/before.rules. For more details, see this:

I need to make one change to the above approach of editing /etc/ufw/before.rules… This works but the ip address for the virtual machine must be set inside Home Assistant. When the router’s dhcp server assigned the ip address, I couldn’t access the virtual machine from the network. The reason seemed to be that the host’s ufw is an enabled on start up and prevented the guest from getting an ip address. This rendered the edits to /etc/ufw/before.rules ineffective. The solution was to assign a static ip address inside Home Assistant.

I like this solution better than disabling netfilter on the bridge. I’m no networking expert, but that sounds like an invitation to all sorts of security problems.

Damn, make sure you downloaded the ova image, I spent whole night dealing with UEFI unable to boot from drive and figured this morning that I downloaded the aarch64 image as I am migrating from rpi4…

@ENT108 May I ask for clarification… what filename did you try that had UEFI problems, and what filename did you use that actually worked?

You mentioned that you are migrating from rpi4, but what are you migrating to…is it x86?