Home Assistant OS in Incus-Virtual Machine on RPI5
Home Assistant OS in Linux container (Incus/LXD) on RPI5 with reverse proxy (Nginx) in separate container
Goal
I wanted to have Home Assistant OS running, but didn’t want to dedicate a full Raspberry Pi for this. So I searched whether is was possible to have HA running in a Virtual Machine on my main Raspberry PI.
Used sources
https://discussion.scottibyte.com/t/home-assistant-os-in-incus-101/648
Environment
- Raspberry PI 5 with 4 GB RAM
- Running Arch Linux
- incus (linux container installed) with 4 containers running amongst them a Nginx reverse proxy
Working machanism
In order to run a Virtual Machine, an emulator (qemu) and Virtualizing extensions (KVM aka libvirt) are required.
- incus uses qemu for VM’s
- incus generates qemu config file from
- incus profile attached to incus image and
- from ‘incus config edit
For example for our test-vm
- /run/incus/test-vm/qemu.conf is used as input file for running qemu
- so do not edit this file; is generated on startup of incus vm
This file contains
# GPU
[device "qemu_gpu"]
driver = "virtio-gpu-pci"
#this is the problem
#this device is NOT in the output of: qemu-system-aarch64 -device help|grep -i virtio-gpu)
bus = "qemu_pcie3"
addr = "00.0"
Installation
Execute following commands on RPI5
wget https://github.com/home-assistant/operating-system/releases/download/16.3/haos_generic-aarch64-16.3.qcow2.xz
# NB AARCH64 version
# uncompress xz file
unxz haos_generic-aarch64-16.3.qcow2.xz
incus-migrate
# Answer questions as follows:
# local incus server: yes
# Choose 2: Virtual Machine
# Nname of new instance: HA-OS
# qcow2 file: ./haos_ova-16.3.qcow2
# UEFI booting: yes
# Secure boot: no
# Choose 1 to start the migration of the qcow2 formatted file
# **NB: in contrast to the instructions in the above mentioned source, only de 'default' profile is used for this instance, not the 'bridged profile'
After the incus image is created, execute the following commands:
incus config device override HA-OS root size=50GiB
incus config set HA-OS limits.memory 2GiB
# more RAM makes my RPI5 too busy/slow
incus start HA-OS
Error: Virtual machine not supported
Of course starting HA-OS was not working the first time; I got error “Virtual machine not supported”. So now first test whether a very basic VM is working:
incus launch images:debian/12 test-vm --vm -c security.secureboot=false
This gave the same error “ERROR virtual machine not supported”.
incus info | grep -i virtualization
Should show the “virtual machines supported by qemu, but this is NOT SHOWN.
edk2-ovmf and seabios are independent of architecture, you can download the packages from the Arch x86_64 repo and install them using pacmam.
So copy edk2-ovmf-202508-1-any.pkg.tar.zst from laptop to /var/cache/pacman/pkg/ on RPI.
sudo pacman -U edk2-ovmf-202508-1-any.pkg.tar.zst
journalctl -u incus -n50
sdf
Last command gives Unable to run feature checks during QEMU initialization: Unable to locate a UEFI firmware
Incus expects the edk2-aarch64 firmware in a standard location like /usr/share/qemu</code. On Arch ARM, it is often stored in /usr/share/edk2/aarch64/. To fix this, you must explicitly point Incus to the correct directory by setting an environment variable in the service file.
Package edk2-aarch64 is on the arch website flagged as out-of-date. But it can be downloaded from mirror
https://archlinux.org/packages/extra/any/edk2-aarch64/
NB: not sure if this is necessary, or that installing of virt-firmware is sufficient.
pacman -U <file>
# now files are present at /usr/share/edk2/aarch64/
pacman -Ss edk2 # search edk2 packages
# this gives: extra/virt-firmware 25.12-1
# - Collection of tools for edk2 firmware images
pacman -S virt-firmware
sudo systemctl edit incus.service
And add
Environment=INCUS_EDK2_PATH=/usr/share/edk2/aarch64/
In the upper part (override part) of the file
Now this dir contains the needed .fd files
systemctl restart incus
Error: virtio-gpu-pci is not a valid device model name
Now I get following error: virtio-gpu-pci is not a valid device model name.
Launching our test VM incus launch images:debian/12 test-vm --vm -c security.secureboot=false gives an error.
incus info --show-log test-vm gives virtio-gpu-pci is not a valid device model name
sudo pacman -S qemu-hw-display-virtio-gpu qemu-hw-display-virtio-vga virglrenderer
incus admin shutdown
systemctl restart incus
I still get the same error; now try to disable graphics
incus config device add test-vm console none
journalctl -u incus -n 50
gives as output
level=warning msg="Skipped moving GPT alternative header to end of disk as sgdisk command not found" dev=/var/lib/incus/storage-pools/default/virtual-machines/test-vm/root.img driver=dir pool=default
So install missing package
sudo pacman -S gptfdisk
pacman -S cdrtools
Launch test VM:
incus launch images:debian/12 test-vm --vm -c security.secureboot=false
This gives still error of virtio-gpu-pci
List device qemu supports:
qemu-system-aarch64 -device help|grep -i virtio-gpu gives
virtio-gpu-device, bus virtio-bus
This is different from virtio-gpu-pci.
So Incus must be configured to use a different device:
incus profile set default raw.qemu -- "-device virtio-gpu-device"
This command inserts following in config file:
- config:
raw.qemu: -device virtio-gpu-device
This can be checked via
incus profile edit default
This still not solved the problem.
pacman -S qemu-hw-display-virtio-gpu-pci
This is the command that did the trick, and solved this problem
The HA-OS virtual machine starts
Now check our test-vm:
incus launch images:debian/12 test-vm --vm -c security.secureboot=false
This succeeds!!
Now lets try to start HA-OS
incus start HA-OS
# gets IP after 20 seconds (check via 'incus list')
incus list #note the IP-address of the HA-OS container
I can access HA from the RPI5 via the links text-only browser:
links <IPi of incus HA VM>:8123
incus console HA-OS --show-log shows log of the VM
Now HA-OS is working, we have to make it accessible from the internet so we can configure it further. But to be able to configure HA-OS I have to login via a browser into HA, but my RPI5 is headless, and I cannot access HA from another computer.
Make HA-OS accessible via internet
Get access to HA-OS via a browser
Install a graphical browser on RPI5, and display the GUI on my laptop running Arch Linux with Wayland (not X); I use a browser light on memory, to prevent memory exhaustion on RPI5. This is why I do not use firefox. Waypipe is a utility via which I can display the graphical browser running on my headless RPI5, on my laptop. On RPI5
pacman -S falkon
pacman -S waypipe
On laptop: pacman -S waypipe
Now start falkon on RPI5, from laptop with display on laptop.
On laptop: waypipe --no-gpu ssh <user>@<IP of RPI5> falkon
NB: the “-no-gpu: switch is necessary
In the falkon browser navigate to <IP of HA-OS VM)>:8123
Configure HA-OS to be used with existing Nginx reverse proxy
I had already a running Nginx reverse proxy. This was running in an Incus container (not a VM) on the same RPI5. So I wanted to use this reverse proxy, and not the built in one in HA OS.
I just created an nginx site file in the nginx proxy container:
incus exec proxy -- bash #start a bash shell in the incus container named 'proxy'.
cd /etc/nginx/sites-available
create a file namen ha.<yourdomain> with following contents:
server {
server_name ha.<yourdomain>;
location / {
proxy_pass http://HA-OS.incus:8123;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# the lines below are REALLY NECESSAY for websockets required by HA OS to work
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
real_ip_header proxy_protocol;
set_real_ip_from 127.0.0.1;
listen [::]:443 ssl proxy_protocol; # managed by Certbot
listen 443 ssl proxy_protocol; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/<YOUR PATH>/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/YOUR PATH/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = ha.<yourdomain>) {
return 301 https://$host$request_uri;
} # managed by Certbot
# for all urls:
return 404; # managed by Certbot
Now use the Falkon browser (see above) running on RPI5, to get access to HA OS. Log in into HA OS and
- go to settings and activate
advanced mode. - install add ons
- ssh
- file editor
Use file editor to edit /root/config/configuration.yaml and add folowing lines in http section:
use_x_forwarded_for: true
trusted_proxies:
- <IP of Nginx reverse proxy server>