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

Thanks for your guide! It’s great!
I’ve been having crazy problems with my networking.
I made a post about it here, so there is no point repeating.
https://ubuntuforums.org/showthread.php?t=2464606&p=14047312#post14047312

If you could take a look, it would be greatly appreciated.

I’m still trying to figure out networking myself. I stuck with netplan for this guide because that was what I (finally) got working, so I’m not sure I’d be much help with ifupdown.

The only thing I noticed is that my ip route has no line mentioning eno1 (which would be enp2s0 for you). Mine shows:

default via 10.0.30.1 dev br0 proto dhcp src 10.0.30.21 metric 100
10.0.30.0/24 dev br0 proto kernel scope link src 10.0.30.21
10.0.30.1 dev br0 proto dhcp scope link src 10.0.30.21 metric 100
172.11.0.0/24 dev br-0ecd20e9f9fe proto kernel scope link src 172.11.0.1
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
172.18.0.0/16 dev br-993e33e0f597 proto kernel scope link src 172.18.0.1
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1 linkdown

But I’m not sure if it’s relevant, or what to do about it using ifupdown.

1 Like

Wow. Thanks for that.
Indeed, those routes got added when I started the HA vm.
Removing the enp2s0 routes did help the host to ping the gateway.

Now I need to work out why they are getting added by virsh (if added by this) and if stopping that happening will resolve the issue… what a pain!

BTW, your post helped lead me to my workaround.
I added metric 1000 to the bottom of my dhcpcd.conf which had an entry for enp2s0 .
This was adding the other routes!

It will still add them, but it will not hit them first

@Aephir what an awesome post. Very clear. This saved me loads of time and worked without issues on Ubuntu 20.04. Thanks so mcuh.

1 Like

@Aephir Thank you so much for this amazing post! I followed your guide and got it all set with a fresh install of Ubuntu 20.04. However, I had to change 1-2 things, I post them here in case anyone come across it.
In your guide Step 1.4, I believe these 2 commands are NOT required

gunzip hassos_ova-4.16.qcow2.gz
mv hassos_ova-4.16.qcow2 hassos.qcow2

Setting up Network Section
I had problems getting this to work, so I first had to “REMOVE” the default bridge created by KVM Install by running these 2 commands

virsh net-destroy default
virsh net-undefine default

Since I had “STATIC” IP for my Ubuntu, here is what my 00-installer-config.yaml looks like

network:
  ethernets:
    enh1: //This is going to be different for your setup
      dhcp4: false
      dhcp6: false
  bridges:
    br0:
      interfaces: [ enh1 ] //whatever interface you have above
      addresses: [192.168.0.80/24] //your static IP for the HOST (Ubuntu) 
      gateway4: 192.168.0.1 // your router IP 
      nameservers:
        addresses: [8.8.8.8,8.8.4.4] //Google Name Servers
      parameters:
        stp: true
        forward-delay: 4
      dhcp4: no
      dhcp6: no
  version: 2

you should do netplan generate first before applying to catch any errors

Step 3
The only thing I had to do is to install virt-install, if you run the command and get an error, it tells you what you need to do to install it.

Last in order for the KVM to start automatically, run this command
virsh autostart hassos //name of your VM you created

I changed the IP for Home Assistant from the SuperVisor UI. overall fantastic guide ! really appreciate the time effort you put towards this.
Cheers,

1 Like

Great, thanks for posting your experience and additions!

I think the qcow2 file you can download has been compressed in different ways over the months/years, so that part of the guide might be outdated. I think I half-updated the guide the last time (when it changed from .gz to .xz, but apparently didn’t update everything. Thanks, I have now (I hope) updated all of that :slight_smile:

I’ll add a link to your post in the guide for anyone having network issues.

1 Like

I just installed latest versions following your guide, and configured static ip on the bridge with exact configuration like @Raul_7

One more addition. For me, the homeassistant was not reachable as it didn’t have the ip address in the same subnet. Not sure whether it obtained ip before I set the ip on the bridge correct. But, I had to set static ip on hassos.

Set ip (else it generate unrechale ip):

virsh console hassos

nmcli con edit "Home Assistant OS default"
print ipv4 
set ipv4.addresses 192.168.254.103/24
set ipv4.dns 192.168.254.254
set ipv4.gateway 192.168.254.254
save
q
exit

In my case, I choose this(ha) ip different from host ip created above with Netplan, but worked without any additional configuration on host.
hope that help someone.

Thanks for the hint on how to add a USB device.
In my case, I had to adjust the .xml slightly in format:

   <hostdev mode='subsystem' type='usb' managed='yes'>
      <source>
        <vendor id='0x17ef'/>
        <product id='0x480f'/>
      </source>
    </hostdev>

There is no more need for <devices>
I attached via this command: sudo virsh attach-device hassos --file usb_sticks.xml
The flag -persistent was not accepted when attaching

Hi all- I’m looking into setting up Home Assistant using the KVM image and, this might be a dumb question, but how much space is allocated to the Hassio when following this guide? My experience with VMs in the past has been to manually allocate a certain amount of space. Does KVM work differently?

Looking back at some notes I took when I first installed mine around 18 months ago or so, the disk image was around 6GB, and hassos thought it had a disk of about the same size and that about half of it was already used. I have over time expanded the image a couple of times using qemu-img resize.

Awesome- thank you for the quick reply!

Hi Gunnar,

I used --persistent (two --) not -persistent - you used only (one -) works and the USB Stick is up everytime I boot. I did this with Debian Bullseye 11 Headless.

Oops, autocorrect changed -- to . I’ve changed it in my previous post, thanks for catching this!

If you’re stuck at UEFI shell, disable secure booting. I found this “bug” several times while debugging the issue.

maybe worth adding to your first post @Aephir.

Thanks, I’ve added a note about this.

1 Like

Thanks Aephir for such a nice guide and all the other contributors!

I ran into an issue with getting the networking to route the traffic from within HassOS and I’m banging my head against the proverbial wall. My computer has two NICs and I assigned one with a static IP in bridge mode following your latest guide (and disabled netfilter). Even though DHCP would connect to my router and provide an IP it wasn’t visible within the VM. So I manually set the IP with bsr203’s tip and then I could at least ping from within my VM to the bridge IP but that was it (can’t ping the gateway). I double checked that my router wasn’t blocking me and I’m running out of ideas.

Here’s the Ubuntu server 2020.04 host setup (enp2s0 is the physical network card for the bridge):

# brctl show
bridge name	bridge id		STP enabled	interfaces
br-5f3493e0fbc0		8000.0242d3fbc585	no		
br0		8000.245ebe5d2e92	yes		enp2s0
							vnet0
docker0		8000.0242c14aa5ad	no		vetha6a3fe5

# ip a | sed 's/..:.. /xx:xx /' | sed 's/:....:....\/64 /:xxxx:xxxx\/64 /'
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:xx:xx brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master br0 state UP group default qlen 1000
    link/ether 24:5e:be:5d:xx:xx brd ff:ff:ff:ff:ff:ff
3: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 24:5e:be:5d:xx:xx brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.31/24 brd 192.168.1.255 scope global dynamic enp3s0
       valid_lft 6661sec preferred_lft 6661sec
    inet6 fe80::265e:beff:xxxx:xxxx/64 scope link 
       valid_lft forever preferred_lft forever
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 24:5e:be:5d:xx:xx brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.32/24 brd 192.168.1.255 scope global br0
       valid_lft forever preferred_lft forever
    inet6 fe80::265e:beff:xxxx:xxxx/64 scope link 
       valid_lft forever preferred_lft forever
5: br-5f3493e0fbc0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:d3:fb:xx:xx brd ff:ff:ff:ff:ff:ff
    inet 172.21.0.1/16 brd 172.21.255.255 scope global br-5f3493e0fbc0
       valid_lft forever preferred_lft forever
6: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:c1:4a:xx:xx brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:c1ff:xxxx:xxxx/64 scope link 
       valid_lft forever preferred_lft forever
8: vetha6a3fe5@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 4e:a4:fa:d0:xx:xx brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::4ca4:faff:xxxx:xxxx/64 scope link 
       valid_lft forever preferred_lft forever
14: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UNKNOWN group default qlen 1000
    link/ether fe:54:00:ad:xx:xx brd ff:ff:ff:ff:ff:ff
    inet6 fe80::fc54:ff:xxxx:xxxx/64 scope link 
       valid_lft forever preferred_lft forever

# ip route
default via 192.168.1.1 dev br0 proto static 
default via 192.168.1.1 dev enp3s0 proto dhcp src 192.168.1.31 metric 100 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 
172.21.0.0/16 dev br-5f3493e0fbc0 proto kernel scope link src 172.21.0.1 linkdown 
192.168.1.0/24 dev br0 proto kernel scope link src 192.168.1.32 
192.168.1.0/24 dev enp3s0 proto kernel scope link src 192.168.1.31 
192.168.1.1 dev enp3s0 proto dhcp scope link src 192.168.1.31 metric 100 

# virsh net-list 
 Name   State    Autostart   Persistent
-----------------------------------------
 br0    active   yes         yes

# virt-install --import --name hassio --memory 2048 --vcpus 2 --cpu host --disk haos_ova-7.2.qcow2,format=qcow2,bus=virtio --network bridge=br0,model=virtio --graphics none --noautoconsole --boot uefi

# ip a | sed 's/..:.. /xx:xx /' | sed 's/:....:....\/64 /:xxxx:xxxx\/64 /'
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:xx:xx brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop qlen 1000
    link/ether 2e:fc:9d:ac:xx:xx brd ff:ff:ff:ff:ff:ff
3: enp0s2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 52:54:00:ad:xx:xx brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.35/24 brd 192.168.1.255 scope global noprefixroute enp0s2
       valid_lft forever preferred_lft forever
    inet6 fe80::f60:7e1b:xxxx:xxxx/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
4: sit0@NONE: <NOARP> mtu 1480 qdisc noop qlen 1000
    link/sit 0.0.0.0 brd 0.0.0.0
5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue 
    link/ether 02:42:4f:d8:xx:xx brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:4fff:xxxx:xxxx/64 scope link 
       valid_lft forever preferred_lft forever
6: hassio: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue 
    link/ether 02:42:10:3f:xx:xx brd ff:ff:ff:ff:ff:ff
    inet 172.30.32.1/23 brd 172.30.33.255 scope global hassio
       valid_lft forever preferred_lft forever
    inet6 fe80::42:10ff:xxxx:xxxx/64 scope link 
       valid_lft forever preferred_lft forever
8: vethaf21852@if7: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master hassio 
    link/ether 6e:88:df:f7:xx:xx brd ff:ff:ff:ff:ff:ff
    inet6 fe80::6c88:dfff:fef7:a65/64 scope link 
       valid_lft forever preferred_lft forever
10: veth06dcc8d@if9: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master docker0 
    link/ether ce:5c:58:a7:xx:xx brd ff:ff:ff:ff:ff:ff
    inet6 fe80::cc5c:58ff:xxxx:xxxx/64 scope link 
       valid_lft forever preferred_lft forever
12: veth7fe8231@if11: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master hassio 
    link/ether f6:f1:40:56:xx:xx brd ff:ff:ff:ff:ff:ff
    inet6 fe80::f4f1:40ff:xxxx:xxxx/64 scope link 
       valid_lft forever preferred_lft forever
14: veth190e21c@if13: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master hassio 
    link/ether 92:f2:66:0c:xx:xx brd ff:ff:ff:ff:ff:ff
    inet6 fe80::90f2:66ff:xxxx:xxxx/64 scope link 
       valid_lft forever preferred_lft forever
16: veth65cf789@if15: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master hassio 
    link/ether aa:a3:7e:75:xx:xx brd ff:ff:ff:ff:ff:ff
    inet6 fe80::a8a3:7eff:xxxx:xxxx/64 scope link 
       valid_lft forever preferred_lft forever
18: veth86f3232@if17: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master hassio 
    link/ether 52:e2:ff:d1:xx:xx brd ff:ff:ff:ff:ff:ff
    inet6 fe80::50e2:ffff:xxxx:xxxx/64 scope link 
       valid_lft forever preferred_lft forever

# ip route
(nothing, hmmmm)

# nmcli con edit "Home Assistant OS default"
nmcli> print ipv4
['ipv4' setting values]
ipv4.method:                            manual
ipv4.dns:                               192.168.1.1
ipv4.dns-search:                        --
ipv4.dns-options:                       --
ipv4.dns-priority:                      0
ipv4.addresses:                         192.168.1.35/24
ipv4.gateway:                           192.168.1.1
ipv4.routes:                            --
ipv4.route-metric:                      -1
ipv4.route-table:                       0 (unspec)
ipv4.routing-rules:                     --
ipv4.ignore-auto-routes:                no
ipv4.ignore-auto-dns:                   no
ipv4.dhcp-client-id:                    --
ipv4.dhcp-iaid:                         --
ipv4.dhcp-timeout:                      0 (default)
ipv4.dhcp-send-hostname:                yes
ipv4.dhcp-hostname:                     --
ipv4.dhcp-fqdn:                         --
ipv4.dhcp-hostname-flags:               0x0 (none)
ipv4.never-default:                     no
ipv4.may-fail:                          yes
ipv4.dad-timeout:                       -1 (default)
ipv4.dhcp-vendor-class-identifier:      --
ipv4.dhcp-reject-servers:               --
nmcli> q   

# ping 192.168.1.32
192.168.1.32 is alive!

# ping 192.168.1.1
No response from 192.168.1.1

I can ping 192.168.1.32 from an external host but 192.168.1.35 (the VM) is dead.

I’m at a loss for what to try next…any help would be appreciated.

Cheers

I’m not really sure. It’s been a while since I did anything with this, so I might have forgotten a thing or two. Have you tried just letting you DHCP server take care of IPs? I mean getting the MAC of the VM, and making a reservation for a certain IP.

Also, how do you ping from within the VM? I’ve never been able to connect to a console inside the hassOS VM. I didn’t know that was possible without e.g. setting up SSH add-on. virsh console hassos (which is the typical way when using virsh/KVM) just leaves me hanging with a

Connected to domain hassos
Escape character is ^]

(except that’s not the keyboard combination on a Danish macOS keyboard, so that took a while to get out of…)

Why not creating the bridge devices on your second NIC and assign the IP via DHCP?

I tried using regular DHCP first and my router would receive the request but the VM would not get the IP back.

For testing from within the VM I do virsh console hassos and then hit Enter and there will be a login prompt and I type root for the username and then there is no password (get to a shell). The Escape character gets you out of the shell. Depending on your OS it could be different (try Esc then ], Control-], Alt-], GUI-] until something works). If your keyboard doesn’t have the ‘]’ letter then you could close your terminal window as a workaround.

@MrksHfmn good idea. Can you point me to some instructions for how to do that? I could dedicate the second NIC purely for the VM (maybe I don’t even need the bridge?).