How to Install Home Assistant with Docker (Smart Home on Your Own Server)

Home Assistant ties together the smart bulbs, plugs, thermostats and sensors that each came with their own app, and runs automations locally — lights on at sunset, heating off when everyone's out — with no cloud in the loop. It runs happily in a Docker container on the server you already have.
Quick reference
| Task | What |
|---|---|
| Folder | ~/docker/homeassistant/compose.yaml |
| Start | docker compose up -d |
| First visit | http://server-ip:8123 |
| Config files | ./config/configuration.yaml |
| Logs | docker compose logs -f |
| Phone app | Home Assistant Companion (iOS/Android) |
Container or Home Assistant OS?
Home Assistant comes in several flavours. Home Assistant OS is a whole operating system for a dedicated Pi or VM and includes the add-on store. The Container version, which this guide uses, is the core app only — ideal when the server already runs other things. Add-ons (Mosquitto, Zigbee2MQTT, Node-RED) are just more containers you run alongside it.
1. The compose file
mkdir -p ~/docker/homeassistant && cd ~/docker/homeassistant
nano compose.yaml
services:
homeassistant:
image: ghcr.io/home-assistant/home-assistant:stable
container_name: homeassistant
network_mode: host
privileged: true
environment:
TZ: Europe/London
volumes:
- ./config:/config
- /etc/localtime:/etc/localtime:ro
- /run/dbus:/run/dbus:ro
restart: unless-stopped
network_mode: host is unusual but required: Home Assistant discovers devices by listening for broadcasts on your network, which doesn't work from behind Docker's normal network. It means there's no ports: section — it simply listens on 8123. privileged plus the dbus mount let it see USB sticks (Zigbee, Z-Wave) and Bluetooth.
docker compose up -d
sudo ufw allow 8123/tcp
2. First run
Open http://192.168.1.50:8123. It takes a minute to start the first time. Create your account, name the home, set the location (used for sunrise and sunset) and it immediately lists devices it has already found on the network — printers, TVs, Hue bridges, Sonos.
3. Add integrations
Settings → Devices & services → Add integration. Search for the brand. Most local devices (Shelly, Tasmota, Hue, Sonos, Chromecast) are found automatically; cloud ones (Tuya, Ring) ask you to log in.
4. A first automation
Settings → Automations → Create automation.
- When: Sun → sunset, offset −30 minutes
- Then do: Light → Turn on → living room lamp
Save. That's a lamp that comes on half an hour before dark, every day, with no app and no cloud.
5. The phone app
Install Home Assistant on your phone and point it at http://192.168.1.50:8123. For access away from home, either use your VPN (tutorial 33) or put it behind Nginx with HTTPS (tutorial 28) — and add this to configuration.yaml so it trusts the proxy:
http:
use_x_forwarded_for: true
trusted_proxies:
- 127.0.0.1
Zigbee and Z-Wave
A USB coordinator (Sonoff Zigbee 3.0 dongle, say) plugs into the server. Find it with ls /dev/serial/by-id/, add it as a volume in the compose file (- /dev/serial/by-id/usb-...:/dev/ttyUSB0), and set up the Zigbee Home Automation integration, or run Zigbee2MQTT as another container.
Troubleshooting
Nothing is discovered. You left out network_mode: host.
"400 Bad Request" through Nginx. Missing trusted_proxies in configuration.yaml. Restart the container after adding it.
A device stops responding after a Wi-Fi change. It got a new IP. Give smart devices DHCP reservations on the router (tutorial 8).
Updating. docker compose pull && docker compose up -d. Back up ./config first; the UI also has Settings → System → Backups.
Wrapping up
One compose file with host networking, a browser visit, and your smart home runs from the cupboard instead of six company clouds. Add devices as you go, write automations in the visual editor, and keep ./config in your backups.
