Skip to content

Home Assistant Integration

Home Assistant is Sanctum’s haus automation hub. It runs as a Docker container on the Mac Mini with bridge networking, integrating Sonos speakers, HomeKit devices, and providing remote access through a Cloudflare tunnel. It used to run on the VM, but the VM’s networking had other ideas.

The robot butler — your haus automation concierge

┌──────────────────────────────────────────────┐
│ Mac Mini │
│ │
│ ┌─────────────────────────────────────────┐ │
│ │ Docker (bridge network) │ │
│ │ │ │
│ │ ┌─────────────────────────────────┐ │ │
│ │ │ Home Assistant Container │ │ │
│ │ │ Port 8123 → Web UI │ │ │
│ │ │ Port 21063 → HomeKit Bridge │ │ │
│ │ │ SSH agent → VM access │ │ │
│ │ └─────────────────────────────────┘ │ │
│ └─────────────────────────────────────────┘ │
│ │
│ Cloudflare Tunnel → ha.nepveu.name │
└──────────────────────────────────────────────┘

HA was migrated from the VM to Mac Docker because SLIRP networking on the VM proved unreliable for the number of integrations and real-time device communication required. Translation: the Sonos speakers kept dropping off, and no amount of debugging SLIRP made the problem go away. Some battles you win. Some you migrate around.

The container uses bridge networking rather than --network=host because host networking is not supported on macOS Docker. This is the polite way of saying “Docker on Mac is a compromise and we’ve all agreed to live with it.”

SettingValue
Imageghcr.io/home-assistant/home-assistant:stable
Network modebridge
Web UI port8123
HomeKit port21063
Config directory~/.openclaw/homeassistant/
Restart policyunless-stopped

The compose.yaml at ~/.openclaw/homeassistant/ defines the container with these essential directives:

  • Port mappings: 8123:8123 (web), 21063:21063 (HomeKit)
  • Volume mount: Local config directory into /config
  • Extra hosts: host.docker.internal:host-gateway for reaching Mac services from inside the container
  • SSH agent socket: /run/host-services/ssh-auth.sock mounted for agent forwarding to the VM

Docker Desktop is configured with auto-start enabled, ensuring HA comes up after a reboot without manual intervention.

Sanctum manages 10 Sonos speakers. Because the HA container runs in bridge networking mode, mDNS/SSDP discovery does not work. All speakers must be configured as known hosts in configuration.yaml.

sonos:
media_player:
hosts:
- 192.168.1.101
- 192.168.1.102
# ... all 10 speaker IPs

The XTTS-v2 TTS server runs on the Mac (port 8008, using MPS GPU acceleration). To play speech on Sonos speakers, use the media_player.play_media service with a media-source://tts/ URI and the announce: true flag.

The HA container needs SSH access to the VM for certain automations and scripts. This is accomplished by mounting the Mac’s SSH agent socket into the container.

The SSH agent socket at /run/host-services/ssh-auth.sock is mapped as a volume in the compose file. Scripts inside the container can then SSH to [email protected] using the Mac’s loaded SSH keys without storing any private keys in the container.

SSH wrapper scripts live at ~/.openclaw/ha-scripts/ and exec SSH directly to the VM with agent forwarding enabled.

The configuration.yaml includes network-specific settings for the bridge networking environment:

homeassistant:
internal_url: "http://192.168.1.10:8123"
external_url: "https://ha.nepveu.name"
http:
use_x_forwarded_for: true
trusted_proxies:
- 172.16.0.0/12
- 192.168.64.0/20

The trusted proxies cover Docker’s internal bridge subnets, allowing HA to correctly identify client IPs when accessed through the Cloudflare tunnel or Docker’s bridge network.

There are two remote access paths into HA, each serving a different purpose. Because one way in would have been too simple, and simplicity is what other people have.

For accessing the HA web UI from a browser, a Cloudflare tunnel provides HTTPS with Zero Trust access controls.

ComponentDetails
Tunnel namemanoir-nepveu
LaunchAgentcom.sanctum.tunnel
External URLhttps://ha.nepveu.name
Routeha.nepveu.name to localhost:8123
AuthCloudflare Access OTP

The HA Companion app cannot handle Cloudflare Access’s login page, so it connects via Tailscale instead. Tailscale provides end-to-end WireGuard encryption, so HTTPS is not needed.

  1. Install Tailscale on iPhone and connect (do NOT enable exit node)

  2. Install HA Companion

  3. Open HA Companion → Settings → Companion App → Server & Connection

  4. Configure connection URLs:

    FieldValue
    Internal URLhttp://<mac-lan-ip>:8123
    External URLhttp://<tailscale-ip>:8123
  5. Under Internal Connection: add your haus Wi-Fi SSID so the app uses the LAN when haus

  6. Enable Local Push for instant notifications on haus Wi-Fi

  7. Test: turn off Wi-Fi briefly — the app should reconnect via Tailscale

The HomeKit bridge runs on port 21063, allowing Apple Home app control of HA-managed devices.

SettingValue
Port21063
Pairing code840-97-709

HomeKit entities are configured within HA’s integration settings. The bridge exposes selected devices to Apple Home while keeping the full HA device list available through the web UI.

Terminal window
# Start HA
cd ~/.openclaw/homeassistant && docker compose up -d
# Stop HA
cd ~/.openclaw/homeassistant && docker compose down
# View logs
docker logs -f homeassistant
# Restart
cd ~/.openclaw/homeassistant && docker compose restart

If the Mac Docker instance has issues, a rollback path exists to the VM:

  1. Stop the Mac container: docker compose down
  2. SSH to the VM: ssh openclaw
  3. Start the VM instance: ~/.openclaw/ha-docker.sh recreate