Home Assistant OS ran out of space on its virtual disk. The 32 GiB volume, which provided roughly 30.8 GiB of usable space, hit 95.6% capacity. The primary culprit was the Recorder integration, which had accumulated a ~10 GB SQLite database.
Stopping the chatty integration halted further growth, but it did not solve the immediate problem. SQLite does not return freed pages to the filesystem. To shrink the database file, I would need to run VACUUM, which requires free space equal to the size of the database itself. With only 4.1 GiB of free space remaining, that was impossible. Additionally, the latest automatic backup was 4.17 GB, which also no longer fit.
Growing the virtual disk was the only viable path. I needed to expand the qcow2 image from 32 to 64 GiB on my Unraid server, which runs Home Assistant OS as a KVM virtual machine.
Why 32 GiB Was Not Enough
Home Assistant OS partitions its virtual disk into several logical volumes. The root partition holds the operating system, while the data partition holds the configuration, add-ons, and the recorder database. In my case, the root partition had plenty of free space, but the data partition was saturated.
The Recorder integration keeps 30 days of history by default (purge_keep_days: 30). Over time, this accumulates significant data, especially with the 1,656 entities I track. When the free space dropped below the threshold required for a backup or a database optimization, the system became unstable. Backups failed, and the UI became sluggish.
Expanding the disk was a low-risk operation compared to migrating data to a new server or manually sharding the database. However, it requires careful preparation to avoid corrupting the image.
Pre-flight Checks and Rollback
Before touching the disk image, I performed three critical checks. These are non-negotiable for maintaining data integrity.
First, I verified there were no internal snapshots in the qcow2 image. Internal snapshots lock the image in a way that makes resizing dangerous. If snapshots exist, the resize operation can fail or corrupt the data. I used qemu-img snapshot -l to list any snapshots. The output was empty, confirming a clean slate.
Second, I ensured the Home Assistant OS update system (RAUC) was settled. HAOS uses an A/B partition scheme for updates. I checked that slot A was the active, stable boot slot (version 18.3) and that there were no pending updates or partial boots. The host had been up for 7.7 hours, indicating no recent restarts or update attempts.
Third, I confirmed there was no <capacity> element in the libvirt domain XML that might override manual resizing.
Once these checks passed, I created a rollback copy. I took a full 32 GiB copy of the qcow2 image while Home Assistant was still running. This is possible because qcow2 supports copy-on-write. The copy was byte-identical to the source, as verified by qemu-img check. This backup is your safety net. If something goes wrong during the resize or the subsequent boot, you can revert to this copy.
Resizing the Disk
With the rollback copy in place, I shut down the virtual machine gracefully. The shutdown took approximately 70 seconds. It is crucial that the VM is fully powered off (shut off) before proceeding. Attempting to resize a mounted or active disk can lead to data corruption.
Once the VM was off, I used the qemu-img tool to resize the primary image.
qemu-img resize /path/to/haos_ova.qcow2 +32G
This command added 32 GiB to the existing 32 GiB, resulting in a 64 GiB virtual disk. The command executed instantly because qcow2 images are sparse; the additional space is allocated on the host filesystem as data is written.
After resizing, I started the virtual machine.
Home Assistant OS Auto-Expansion
Home Assistant OS handles the partition expansion automatically. There is no need to manually partition the new space or format it.
On boot, the haos-expand.service systemd unit runs. It detects that the virtual disk is larger than the partition table. It then uses sfdisk to resize partition 8 (the data partition) to fill the available space. Following this, systemd-growfs@mnt-data is triggered to expand the ext4 filesystem on that partition to match the new partition size.
This process is robust and designed to be hands-off. I did not need to log into the VM shell or run any commands.
Verification and Results
After the VM booted and the services stabilized, I verified the changes.
The disk_total metric in Home Assistant showed 62.3 GB, up from 30.8 GB. The free space jumped from 4.1 GB to 34.3 GB. The used space remained at 25.4 GB, confirming that the existing data was preserved and the new space was empty.
All 49 integrations loaded correctly. The 68 automations were all in the on state. I checked the Recorder integration, and the database was still intact. A template sensor that had previously failed due to disk space issues repopulated correctly. The automatic backup also succeeded, fitting comfortably into the new free space.
Cleanup and Future Considerations
The rollback copy of the qcow2 image remains on the host. I kept it for a few days to ensure stability before deleting it. If you choose to keep it, be aware that it consumes another 32 GiB of host storage.
Home Assistant OS is moving toward using systemd-repart instead of the custom haos-expand service in version 19. This change may alter the boot sequence slightly, but the outcome—automatic expansion of the data partition—will likely remain the same.
For Unraid users, the VM manager UI also allows resizing the disk size directly. This method updates the libvirt configuration and the qcow2 image simultaneously. However, the manual qemu-img approach gives you more visibility into the process and ensures the rollback copy is created before any changes are made.
The 32 GiB limit was a constraint imposed by the default HAOS VM template. For larger installations with significant history retention or many add-ons, starting with a 64 GiB or larger disk is advisable. The cost of the additional storage is minimal, and the risk of running out of space is eliminated.