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>

Written on December 23, 2025