Skip to content

Home Assistant

Home automation hub for the homelab. Runs in the home namespace alongside its supporting stack — Mosquitto (MQTT broker), Node-RED (flow automation), ESPHome (device firmware), and Ring MQTT (Ring device bridge).

Architecture

graph LR
    subgraph home["Namespace: home"]
        HA[Home Assistant\nport 8123]
        NR[Node-RED\nport 1880]
        MQ[Mosquitto\nport 1883]
        ESP[ESPHome\nport 6052]
        RM[Ring MQTT\nport 55123]
    end

    DEVICES[IoT Devices\nESPHome firmware] -->|MQTT| MQ
    RING[Ring Doorbell\n& Cameras] -->|MQTT bridge| RM
    SLZB[SMLIGHT SLZB-06U\nZigbee coordinator]
    RM -->|MQTT| MQ
    MQ -->|topics| HA
    NR -->|flows| HA
    HA ~~~ ESP
    SLZB -->|TCP socket\nZHA / EZSP| HA
Hold "Alt" / "Option" to enable pan & zoom

Components

Home Assistant

The core automation hub. Manages all integrations, automations, and dashboards.

Setting Value
Image homeassistant/home-assistant (Flux image policy)
Port 8123
Memory 1–4 Gi
Strategy Recreate (safe for single-replica stateful apps)
Storage homeassistant PVC — 50Gi local-path on worker-0b (hourly rsync backup to NFS)
Networking Ingress at ha.hdhomelab.com (cert-manager TLS)

Mosquitto

MQTT broker. All IoT devices and bridges publish and subscribe through it.

Setting Value
Image eclipse-mosquitto (Flux image policy)
Ports 1883 (MQTT) · 9001 (WebSocket)
Memory 128–256 Mi
LoadBalancer IP 192.168.71.243 (Cilium L2)
Storage mosquitto PVC — 1Gi NFS (data/, config/, log/ subPaths)
HTTPRoute mqtt.hdhomelab.com → port 9001

Note

Mosquitto gets a dedicated LoadBalancer IP (192.168.71.243) so MQTT clients on the LAN can reach it directly on port 1883 without going through the HTTP gateway.

Node-RED

Low-code flow automation. Connects to Home Assistant via the HA integration node and can trigger automations, read states, and react to events.

Setting Value
Image nodered/node-red (Flux image policy)
Port 1880
Memory 1–2 Gi
Storage nodered PVC — 1Gi NFS
Networking Ingress at nodered.hdhomelab.com (cert-manager TLS)

ESPHome

Compiles and manages firmware for ESP8266/ESP32 microcontrollers. Devices flashed with ESPHome report their state to Home Assistant via native API or MQTT.

Setting Value
Image esphome/esphome (Flux image policy)
Port 6052
Memory 256Mi–2Gi
Storage esphome-data PVC — 512Mi NFS
Networking Ingress at esphome.hdhomelab.com (cert-manager TLS)

Zigbee (ZHA + SMLIGHT SLZB-06U)

Zigbee devices are managed through the built-in ZHA (Zigbee Home Automation) integration. The coordinator is an SMLIGHT SLZB-06U, connected to Home Assistant over the LAN via a TCP socket — no USB passthrough or node pinning required.

Setting Value
Coordinator SMLIGHT SLZB-06U
Radio type EZSP (Silicon Labs EFR32)
Connection socket:// TCP — network-attached
TCP port 6638
ZHA database /config/zigbee.db (in the homeassistant NFS PVC)

Adding Zigbee devices

Settings → Devices & Services → Zigbee Home Automation → Add device. Put the device in pairing mode before clicking.

No manifest changes needed

Because the coordinator connects over TCP, the HA pod requires no hostPath volume, securityContext: privileged, or nodeSelector. The Cilium policy for the home namespace has no egress restrictions, so the pod reaches the coordinator freely.

Ring MQTT

Bridges Ring devices (doorbell, cameras) into the MQTT ecosystem so Home Assistant can consume them like any other MQTT device. Connects to the Mosquitto broker internally.

Setting Value
Image tsightler/ring-mqtt (Flux image policy)
Ports 8554 (RTSP) · 55123 (HTTP)
Memory 128–256 Mi
Storage ring-mqtt PVC — 128Mi NFS

Storage

PVC Size Storage class Notes
homeassistant 50Gi local-path on worker-0b Primary config — fast local I/O for SQLite
homeassistant-config-backup 50Gi syno-nfs-retain Hourly rsync backup via CronJob
nodered 1Gi syno-nfs-retain /volume2/homelab/k8s/pvc-nodered
mosquitto 1Gi syno-nfs-retain /volume2/homelab/k8s/pvc-mosquitto
ring-mqtt 128Mi syno-nfs-retain /volume2/homelab/k8s/pvc-ring-mqtt
esphome-data 512Mi syno-nfs-retain /volume2/homelab/k8s/pvc-esphome

The HA config PVC uses local-path to avoid SQLite-over-NFS sluggishness. See SQLite on Local Path for the backup pattern.

See Storage for storage class details.

Configuration Management

The HA config lives on a local-path PVC (node-local, not network-accessible). A SSH sidecar in the HA pod exposes the volume over SSH, and Mutagen syncs it live to the developer machine — no macFUSE or kernel extensions needed.

graph LR
    DEV["Mac\n~/mnt/ha-config"]
    MUTAGEN["Mutagen"]
    PF["kubectl port-forward\n:2222"]
    SSH["SSH sidecar\nalpine + openssh"]
    PVC["local-path PVC\n/config"]
    HA["Home Assistant\n/config"]
    GIT["Gitea"]

    DEV <-->|"live sync"| MUTAGEN
    MUTAGEN <-->|SSH| PF
    PF <-->|port-forward| SSH
    SSH <--> PVC
    HA <--> PVC
    DEV -->|"git push"| GIT
Hold "Alt" / "Option" to enable pan & zoom
Start / stop sync
~/repos/dotfiles/scripts/ha-mount.sh start    # live sync on
~/repos/dotfiles/scripts/ha-mount.sh stop     # live sync off

See Local-Path SSH Sidecar pattern for full setup details.

Structure

Dashboards are YAML-mode Lovelace configs split into per-view files using !include:

dashboards/
├── monitoring.yaml          # view registry (!include list)
├── control.yaml
└── monitoring/
    ├── view_overview.yaml
    ├── view_climate.yaml
    ├── view_batteries.yaml  # battery health dashboard
    └── view_plants.yaml

monitoring.yaml assembles views at runtime:

dashboards/monitoring.yaml
views:
  - !include monitoring/view_overview.yaml
  - !include monitoring/view_climate.yaml
  - !include monitoring/view_batteries.yaml

Dashboards are registered in configuration.yaml:

configuration.yaml (excerpt)
lovelace:
  dashboards:
    lovelace-monitoring:
      filename: dashboards/monitoring.yaml
    lovelace-control:
      filename: dashboards/control.yaml

Automations are split into per-feature files under automations/. HA merges them all at load time:

configuration.yaml (excerpt)
automation split: !include_dir_merge_list automations/
automations/
├── lights.yaml
├── door_hvac.yaml
├── garage_door_notification.yaml
├── temperature_warning.yaml
├── battery_notification.yaml   # low battery alerts
└── ...

Each file is a YAML list of automation objects:

automations/battery_notification.yaml
- id: battery_low_notification
  alias: Low Battery Notification
  triggers:
    - trigger: numeric_state
      entity_id:
        - sensor.motion_detector_battery
        ...
  actions:
    - action: notify.mobiles
      data:
        message: "{{ trigger.to_state.name }} battery is at {{ trigger.to_state.state | int }}%."

Workflow

Change type Apply with Restart?
Dashboard view Browser hard-refresh (Cmd+Shift+R) No
Automation hass-cli service call automation.reload No
Scripts / Scenes hass-cli service call script.reload No
configuration.yaml ha core restart Yes
# Start live sync, edit files, reload HA, commit
~/repos/dotfiles/scripts/ha-mount.sh start
hass-cli service call automation.reload

cd ~/mnt/ha-config
git add automations/my_automation.yaml
git commit -m "feat(ha): add my automation"
git push

MCP Integration

Two MCP servers expose Home Assistant to Claude Code, configured in homelab/.mcp.json.

Home Assistant's built-in /api/mcp endpoint — lightweight, no local process.

"ha": {
  "type": "http",
  "url": "https://ha.hdhomelab.com/api/mcp",
  "headers": {
    "Authorization": "Bearer ${HASS_TOKEN}"
  }
}

HASS_TOKEN must be set in the shell before Claude Code starts. Token is stored in the macOS keychain under service ha-token.

Full-featured local Python MCP server with 86 tools — automations, dashboards, HACS, backups, device registry, history, and more.

"home-assistant": {
  "command": "~/.claude/scripts/ha-mcp.sh",
  "args": []
}

The wrapper script reads the token from the macOS keychain and runs uvx --python 3.13 ha-mcp. Python 3.13 is pinned because ha-mcp requires >=3.13,<3.14.

Source: homeassistant-ai/ha-mcp

When to use which

Use the native endpoint for simple state reads and service calls. Use ha-mcp when you need automation CRUD, dashboard editing, HACS management, or device registry access.

Networking

Home Assistant and Node-RED use the Cilium Ingress controller (legacy Ingress resources with cert-manager TLS). Mosquitto's WebSocket endpoint is exposed via Gateway API HTTPRoute. See Networking for details.

Service Exposure Host
Home Assistant Ingress ha.hdhomelab.com
Node-RED Ingress nodered.hdhomelab.com
ESPHome Ingress esphome.hdhomelab.com
Mosquitto (MQTT) LoadBalancer 192.168.71.243
Mosquitto (WS) HTTPRoute mqtt.hdhomelab.com