What is Home Assistant?
Home Assistant is an open-source home automation platform that puts local control and privacy first. It is released under the Apache-2.0 license and integrates with thousands of devices and services, from Zigbee and Z-Wave sensors to Philips Hue, Sonos and energy meters. Automations run locally, so they keep working when your internet connection does not.
Requirements
- A machine on your home network with 2 CPU cores and 2 GB of RAM. A Raspberry Pi 4 or 5, an Intel N100 mini PC or a VM all work.
- Docker Engine and Docker Compose v2.
- Optional: a USB Zigbee or Z-Wave coordinator, and Bluetooth on the host.
This guide covers the "Home Assistant Container" installation type. If the machine is dedicated to Home Assistant, the project recommends Home Assistant OS instead, which includes the Supervisor and the add-on store.
Step 1: Prepare the server
The steps assume Ubuntu 24.04 with Docker installed. If you need Docker, follow the official install guide. A cloud VPS is not a good fit here: Home Assistant must sit on the same LAN as your devices.
mkdir -p ~/homeassistant/config && cd ~/homeassistant
If you have a Zigbee or Z-Wave stick, find its stable device path:
ls -l /dev/serial/by-id/
Step 2: Create the Docker Compose file
Save this as docker-compose.yml:
services:
homeassistant:
container_name: homeassistant
image: ghcr.io/home-assistant/home-assistant:stable
restart: unless-stopped
network_mode: host
privileged: true
environment:
TZ: "Europe/London"
volumes:
- ./config:/config
- /etc/localtime:/etc/localtime:ro
- /run/dbus:/run/dbus:ro
# Pass through a Zigbee/Z-Wave USB stick instead of using privileged mode:
# devices:
# - /dev/serial/by-id/usb-YOUR_STICK_ID:/dev/ttyUSB0
network_mode: host is what the official documentation uses, because device discovery depends on multicast traffic that does not pass through Docker's bridge network. With host networking, ports: mappings are ignored and Home Assistant binds directly to port 8123 on the host. The /run/dbus mount enables the Bluetooth integration.
privileged: true gives the container access to all host devices. It is convenient but broad. If you only need one USB stick, remove privileged and use the devices: block with the path from /dev/serial/by-id/, which keeps the same name across reboots.
There are no secrets in the Compose file. You create the owner account in the browser. The stable tag tracks the current stable release. To pin, use a version tag such as 2026.9 from the releases page.
Step 3: Start and open the app
docker compose up -d
docker compose logs -f homeassistant
Open http://SERVER_IP:8123. The onboarding wizard asks you to create the owner account, set your home location, units and time zone, and then shows integrations it already discovered on your network. Use a strong password and enable multi-factor authentication in your user profile afterwards.
Step 4: Put it behind HTTPS
For remote access, use a reverse proxy or a tunnel rather than forwarding port 8123. With Caddy on the same host:
home.example.com {
reverse_proxy 127.0.0.1:8123
}
Home Assistant rejects proxied requests until you trust the proxy. Add this to config/configuration.yaml and restart:
http:
use_x_forwarded_for: true
trusted_proxies:
- 127.0.0.1
- ::1
If the proxy runs elsewhere, such as Nginx Proxy Manager on another machine, list its IP address instead and enable "Websockets Support", which the frontend requires.
Backups and upgrades
Everything is in the config folder: configuration.yaml, automations, the .storage directory with integrations and users, and the recorder database. Home Assistant also has a built-in backup feature under Settings, System, Backups, which can run on a schedule and encrypt the archive. Copy those archives off the machine.
Read the monthly release notes for breaking changes, then upgrade:
docker compose pull && docker compose up -d
Troubleshooting
- "400: Bad Request" through the proxy: the proxy IP is missing from
trusted_proxies. Checkconfig/home-assistant.logfor the exact address. - Devices are not discovered: confirm
network_mode: hostis set. Discovery does not work on Docker's default bridge network. - Zigbee stick not found: pass the
/dev/serial/by-id/path, and make sure no other container, such as Zigbee2MQTT, is holding it. - Database grows large: tune the
recorder:integration withpurge_keep_daysand exclude chatty entities.
Next steps
Add Mosquitto and Zigbee2MQTT as extra containers, set up the Home Assistant companion app for presence detection, and build your first automation in Settings, Automations and scenes.
Spotted something out of date? Tell us and we will update the guide.