Loading...
E.G.

Where Home Assistant Runs: One Small VM, Measured

September 1, 2026
Table of Contents

I moved Home Assistant onto a machine of its own this month — a small cloud VM, nothing sitting at home. Before I did, I wanted a straight answer to something the documentation does not give you: what does it actually need?

What I settled on is a Hetzner cx23. Two vCPU, 4 GB of memory, 40 GB of disk, in Nuremberg, on Ubuntu 24.04. That comes to 7.09 euro a month before tax. Home Assistant 2026.8.2 runs in a container on Docker 29.7.2, with network_mode: host.

What the machine serves: a dashboard built from stock cards, running on demo sensors.

What it actually uses

With the container stopped, the machine sits at 611 MB. That is Ubuntu plus the Docker daemon and nothing else. Two minutes after starting Home Assistant it reads 960 MB, and the container accounts for 339 MB of that.

The figure moves, which is why the timing belongs next to it. Immediately after start it reads 850 MB. After 22 hours of uptime I measured between 969 and 985 MB. Anyone quoting a memory number for Home Assistant should say when they took it, because all three of those are true.

From docker compose up to an HTTP 200 on port 8123 took 6.6 seconds, measured in half-second steps. That number flatters the software: the interface answers before the integrations have finished initialising, so it is the moment the web server is up, not the moment the system is ready.

The image is 625 MB. After the base setup the disk sat at 5.4 GB of 38 available, and at 9.4 GB once I added a 4 GB swap file. The jump is the swap file.

Two vCPU and 4 GB is more than a container install with no add-ons needs today. I would not go lower, because the recorder database grows steadily and swap on a 4 GB machine is what keeps an upgrade from being killed for memory.

Why this is not running on the Kubernetes cluster

I already run a single-node k3s for other things, so the obvious question was whether Home Assistant belonged there. I measured that machine first: 11.7 percent CPU as a baseline across seven days, before any workload of mine runs at all, and 1 to 1.5 GB of memory for the control plane sitting idle.

The overhead was not what decided it. Home Assistant needs mDNS and broadcast traffic to find devices on the network. In Docker that is network_mode: host, one line. The Kubernetes equivalent is hostNetwork: true, and that gives up the network isolation which was the reason to run Kubernetes in the first place.

One correction while I am here, because it comes up often: there is no Docker in K3s. K3s runs containerd, and the Docker backend has been deprecated for a while. Same OCI image, different runtime underneath.

What a standard setup leaves open

I went over the machine the day after cloud-init built it, and found four things that were worth fixing. None of them announce themselves, which is the point of listing them.

ufw was installed and never enabled. The package was in the cloud-init list, and without an explicit enable the result is a firewall reporting inactive. It does not matter while the provider firewall in front of it filters everything, and it starts mattering the moment ports 80 and 443 open for TLS.

sshd had password authentication on, which is the Ubuntu default. Root itself is key-only, so nothing was exposed yet — but any additional user created later could have logged in with a password.

There was no swap on a 4 GB machine, and the SSH allow-list held exactly one address: a home connection whose IP rotates. I have locked myself out that way on another project, so a fixed second address went in as an anchor.

All four are fixed on the running machine and written back into the cloud-init file, so rebuilding does not quietly undo them.

What a machine in a data centre cannot do

This is the part most posts about hosting Home Assistant leave out, and it is the first thing you should check before copying my setup. Your devices are on your home network. A VM in Nuremberg is not, and mDNS discovery stops at your router. Anything that speaks only on the local network — Zigbee sticks, KNX, most cheap WiFi plugs — is unreachable from there.

For this build that is on purpose. It binds no device at all in its first phase; it exists to be set up cleanly and photographed. The house is still run by the old instance, which sits where it can see the hardware.

If you want a cloud machine and local devices, you need a tunnel back home, and then the network path becomes the thing that breaks at three in the morning rather than the server. A machine at home avoids that entirely. What it costs you instead is the uptime, the backups and the upgrade discipline that the provider otherwise handles.

What I would keep

The container install, for the reason that it stayed boring. No Supervisor, no add-ons, one compose file, and an upgrade is a changed image tag. What I gave up is the add-on ecosystem, and for a machine that does nothing but run Home Assistant I have not missed it yet. Worth separating two things that get confused here: add-ons are a Supervisor feature and a container install has none, while HACS works fine in a container and gives you integrations, cards and themes.

If you want the install itself rather than the machine choice, I wrote that up separately for Docker on a Linux VM. And once it runs, the first thing worth doing is a backup that covers the whole host, not just the config folder.

Related articles