Skip to main content

Home Assistant

Open-source home automation platform. Integrates with thousands of devices and services, supports local processing, and serves as the event bus for voice-triggered automations.

Home Assistant is a complementary service — nothing else in the stack talks to it, so it can run on its own machine or its own schedule without affecting anything. That matters more here than for most: if you're using a Zigbee or Z-Wave stick, HA needs to live on the machine that stick is plugged into, which may not be the machine running the rest of the stack. It still comes up from the repo root with everything else (./existential.sh && docker compose up -d) — being complementary means you can move it, not that it needs separate commands.

See the blog post Optimizing my life, now with Home Assistant for a real-world setup walkthrough.

Getting Started

  1. Enable the service in .env.shared:
    EXIST_IS_SERVICES_HOMEASSISTANT=true
  2. Run ./existential.sh to render templates and regenerate the compose file
  3. Start the container:
    docker compose up -d homeassistant
  4. Open https://homeassistant.EXIST_DOMAIN and complete the onboarding wizard to create your admin account

Home Assistant generates its own configuration.yaml on first boot inside the homeassistant_config volume — no manual pre-configuration needed.

Hardware Access

If you're connecting USB hardware (Zigbee sticks, Z-Wave controllers, etc.), uncomment privileged: true in docker-compose.yml and add the device path:

devices:
- /dev/ttyUSB0:/dev/ttyUSB0

Identify the device path on the host:

ls /dev/serial/by-id/

Voice

Home Assistant's Assist pipeline speaks the Wyoming protocol — a small, line-oriented TCP protocol — not HTTP. That is why the stack ships two purpose-built services for it rather than reusing WhisperX and Chatterbox, which are HTTP services HA cannot drive:

ServicePort
Speech → textwyoming-whisper10300
Text → speechwyoming-piper10200

Both run on CPU by design. The GPU is already holding the chat model and the embedding model; a GPU voice model would evict them mid-answer, and a spoken reply needs to land immediately anyway.

Wiring it up

Neither service has a web UI or a <slug>.<domain> hostname — Wyoming is raw TCP, so there is nothing for Caddy to front. You add them inside HA:

  1. Settings → Devices & Services → Add Integration → Wyoming Protocol
    • Host wyoming-whisper, port 10300
    • Repeat for host wyoming-piper, port 10200
  2. Settings → Voice assistants → Add assistant
    • Speech-to-text: the wyoming-whisper entry
    • Text-to-speech: the wyoming-piper entry
    • Conversation agent: Ollama, pointed at http://ollama:11434

The models are chosen globally in .env.sharedEXIST_MODEL_STT, EXIST_MODEL_STT_LANGUAGE and EXIST_MODEL_TTS_VOICE. See How it works for the full model-selection block.

Long-Lived Access Token

Many integrations (HAwake, Tasker via TaskerHA, external scripts) need a long-lived access token:

  1. HA → Profile (bottom-left avatar) → Long-Lived Access TokensCreate Token
  2. Copy and store the token securely — it's only shown once

Automations

HA automations are defined in YAML or via the UI under Settings → Automations & Scenes.

See HAwake → Home Assistant → Tasker for a complete example of using a custom wake word to trigger Tasker actions through HA.

Services

EndpointURL
Web Interfacehttps://homeassistant.EXIST_DOMAIN
REST APIhttps://homeassistant.EXIST_DOMAIN/api/

Debugging

# Container logs
docker logs homeassistant

# Configuration check (run inside the container)
docker exec homeassistant python -m homeassistant --script check_config --config /config

# Recent HA log entries
docker exec homeassistant tail -n 100 /config/home-assistant.log