Importing Home Assistant as a Virtual Machine in Incus
Wednesday, October 8, 2025
Reading time 4 minutes
I’ve been a fan of Home Assistant for a while now. Although I don’t have too many home automation devices yet, I use it to automate parts of my daily routine that depend on sensors, automations, and some integrations with devices I have at home.
Since I already have a machine that serves as a server and generally has enough resources to run Home Assistant, I’ve opted to use the Home Assistant OS version (the operating system designed for this software) inside a virtual machine on my server.
I currently use Incus (a fork of LXD), which I’ll probably write about on another occasion. So here I’ll write a bit about how to correctly import the latest version of the Home Assistant operating system image into Incus, and how to deploy the virtual machine. For this, naturally, we must assume that Incus is already properly installed and configured.
What is Home Assistant?
Home Assistant is essentially an open-source ecosystem designed to allow total control of a smart home. The idea behind the project is to give users back control of their home automation devices, allowing, in most cases, complete control and integration even between different device families that are not natively compatible with each other.
What is Incus?
In other blog posts I’ve already written about Libvirt (how to create virtual machines, manage them, among other things). Incus is, broadly speaking, a project born from a slightly different idea (creating Linux system containers that could run providing a complete operating system, but sharing the host system’s kernel) but gradually gained capabilities to manage virtual machines using qemu underneath, just like Libvirt does. Incus is actually a fork of another project called LXD, created by Canonical (the company behind Ubuntu). The idea behind Incus is to allow managing configurations of system containers, OCI (like Docker images), and complete virtual machines with the same configuration and syntax.
Choosing a Variant
In my case the choice is simple: I’ve chosen the full operating system variant from the multiple available options mainly because everything works as intended in this variant. You can install add-ons via Docker containers automatically, it includes some system services designed to supervise and keep the system running and updated, and in general it was made so you don’t have to spend time manually updating the system or tinkering with it if you don’t know what you’re doing. Besides this version, Home Assistant can be installed via Docker (although you can’t install add-ons easily), or directly on a Debian system; but all these additional options are considered advanced.
Importing the Image
Now, to create a Home Assistant image within an Incus instance, the first thing you need to do is import the image into our instance. The Home Assistant project already offers several ready-made images for different operating systems and in different formats. All of them can be found on the operating system’s GitHub releases page. Since we’ll be using disk images, we need to choose the qcow2 images. At the time of writing this, the most recent version of the operating system is version 16.2. Let’s download it into our instance with something like this:
mkdir homeassistant
cd homeassistant
wget https://github.com/home-assistant/operating-system/releases/download/16.2/haos_ova-16.2.qcow2.xz
Once downloaded, extract it as follows:
xz -d haos_ova-16.2.qcow2.xz
This will leave us with a new file named exactly like the downloaded one, but ending in .qcow2. This is the operating system image, which contains everything needed to start the system. However, before we can do that, we need to create a file with metadata to import the image into the instance. It’s done like this:
cat << EOF > metadata.yaml
architecture: x86_64
creation_date: 1719527456
properties:
description: Home Assistant image
os: Debian
release: trixie 13.0
EOF
This will write the file with the minimum information necessary for Incus to know how to treat the disk image that accompanies this information.
Then, it must also be packaged like this:
tar -cvzf metadata.tar.gz metadata.yaml
Finally, you can import the image and the packaged metadata:
incus image import metadata.tar.gz haos_ova-16.2.qcow2 --alias haos
Once this is done, the image has been imported. This broadly means we can now create virtual machines from this image, which will be the template.
Creating the Virtual Machine
Creating a Home Assistant virtual machine is quite simple. You just define the VM:
incus launch haos ha --vm -c security.secureboot=false -d root,size=40GiB
Stop it immediately to assign more resources:
incus stop ha --force
incus config set ha limits.cpu=4 limits.memory=4GiB
(The Home Assistant operating system can run with half these resources, but as you require add-ons and integrations, you may find yourself needing more memory or more CPU time).
Now you can start the system:
incus start ha
From here, Home Assistant has started normally. The project’s web UI can be found on port 8123 of the IP address assigned to the VM. You can also look for it among the devices connected to the router, as it publishes its name by default.