Home Assistant is the open source brain for a smart home. It ties lights, plugs, thermostats, sensors and cameras from dozens of brands into one app, and runs automations locally ("turn the porch light on at sunset", "tell me if the garage is open after 10 pm") without depending on each vendor's cloud.
This is the one app on this site that doesn't belong on your VPS. Home Assistant needs to talk to devices on your home network, and a server in a data center can't see them. Install it on a machine at home: an old laptop, a mini PC or a Raspberry Pi. You can still reach it from anywhere (step 4).
OS or Container: pick your install type
- Home Assistant OS is the project's recommendation for most people. You flash it onto a dedicated device, it updates itself, and it supports one-click apps (formerly called add-ons) such as Zigbee2MQTT and backups.
- Home Assistant Container is just Home Assistant in Docker. Pick it when the machine also runs other things, like a home server with your other Compose apps. You manage updates yourself, and there are no apps; you run those tools as separate containers instead.
Since this site is all about Docker Compose, the rest of this guide covers Container. If HA OS fits you better, the official installation page walks you through flashing it.
1. Write the Compose file
On your home Linux machine with Docker installed:
sudo mkdir -p /opt/homeassistant
cd /opt/homeassistant
sudo nano compose.yml
services:
homeassistant:
container_name: homeassistant
image: ghcr.io/home-assistant/home-assistant:stable
volumes:
- ./config:/config
- /etc/localtime:/etc/localtime:ro
- /run/dbus:/run/dbus:ro # Bluetooth support
restart: unless-stopped
stop_grace_period: 60s
privileged: true # access to USB radios and Bluetooth
network_mode: host # needed to discover devices on your network
environment:
TZ: America/Denver # your timezone
This matches the official example. Two settings look alarming but are expected here. network_mode: host lets Home Assistant discover devices on your LAN, which it can't do from inside Docker's private network. privileged: true gives it access to USB radios like Zigbee sticks.
sudo docker compose up -d
2. Onboarding
From any device on your home network, open http://<machine-ip>:8123 (find the IP with hostname -I). Create your account, set your home's location, and Home Assistant will list the devices it already discovered on your network. That first screen is usually the "oh, wow" moment.
3. Your first automation
Go to Settings → Automations & scenes → Create automation. A great first one: When the sun sets, then turn on a light. Every automation follows that trigger → (optional condition) → action shape, and the visual editor means you don't need to write any YAML.
4. Reaching it from outside
Pick one, from simplest to most hands-on:
- Home Assistant Cloud (Nabu Casa): a paid subscription. Secure remote access with zero networking, and it funds the project's development.
- A VPN (Tailscale or WireGuard): your phone joins your home network privately. Nothing is exposed to the internet. This is my favourite option.
- Reverse proxy with HTTPS: forward a domain to the machine's port 8123. Home Assistant then also needs
use_x_forwarded_for: trueand your proxy's IP intrusted_proxiesunderhttp:inconfiguration.yaml, or it will refuse the proxied requests.
Whichever you choose, turn on two-factor authentication under your user profile first. This app can unlock doors.
5. Updates and backups
cd /opt/homeassistant
sudo docker compose pull && sudo docker compose up -d
Home Assistant releases monthly, and the release notes list "breaking changes". Skim them before updating. Everything that matters lives in ./config: your automations, dashboards, integrations and history. Back up that folder nightly and keep a copy off the machine. Rebuilding automations from memory is nobody's idea of a fun weekend.
Troubleshooting
- Devices aren't discovered: check that
network_mode: hostis set and the machine is on the same network (and VLAN) as the devices. - "400: Bad Request" through a reverse proxy: the
trusted_proxiessetting is missing or has the wrong IP. - Zigbee dongle not found: confirm it shows up on the host with
ls /dev/serial/by-id/, then point the integration at that path.
Official documentation: Home Assistant docs · Repository: home-assistant/core