A Kubernetes operator that manages Home Assistant entities via MQTT autodiscovery. Define your HA entities as Kubernetes Custom Resources, and the controller automatically publishes MQTT discovery payloads so Home Assistant creates them.
- 28 entity types supported: Button, Sensor, Switch, Light, Climate, Cover, Lock, Fan, Vacuum, and more
- Declarative configuration: Define entities as Kubernetes CRDs
- Automatic discovery: Controller publishes MQTT discovery payloads
- Clean deletion: Entities are removed from Home Assistant when CRDs are deleted
- Device grouping: Group multiple entities under a single device
- Availability tracking: Configure availability topics for entity status
- Web UI: Built-in dashboard for managing entities with dynamic forms
| Entity Type | CRD Kind |
|---|---|
| Alarm Control Panel | MQTTAlarmControlPanel |
| Binary Sensor | MQTTBinarySensor |
| Button | MQTTButton |
| Camera | MQTTCamera |
| Climate | MQTTClimate |
| Cover | MQTTCover |
| Device Tracker | MQTTDeviceTracker |
| Device Trigger | MQTTDeviceTrigger |
| Event | MQTTEvent |
| Fan | MQTTFan |
| Humidifier | MQTTHumidifier |
| Image | MQTTImage |
| Lawn Mower | MQTTLawnMower |
| Light | MQTTLight |
| Lock | MQTTLock |
| Notify | MQTTNotify |
| Number | MQTTNumber |
| Scene | MQTTScene |
| Select | MQTTSelect |
| Sensor | MQTTSensor |
| Siren | MQTTSiren |
| Switch | MQTTSwitch |
| Tag | MQTTTag |
| Text | MQTTText |
| Update | MQTTUpdate |
| Vacuum | MQTTVacuum |
| Valve | MQTTValve |
| Water Heater | MQTTWaterHeater |
ghcr.io/spontus/hass-crds-controller:v1.3.4
- Kubernetes cluster (1.26+)
- MQTT broker accessible from the cluster (e.g., Mosquitto)
- Home Assistant configured with MQTT integration
# Install CRDs
kubectl apply -f https://raw.githubusercontent.com/spontus/hass-crds/main/config/crd/crds.yaml
# Deploy controller (creates namespace hass-crds-system)
kubectl apply -f https://raw.githubusercontent.com/spontus/hass-crds/main/dist/install.yaml
# Create MQTT configuration secret
kubectl create secret generic mqtt-config -n hass-crds-system \
--from-literal=MQTT_BROKER=mqtt.example.com \
--from-literal=MQTT_PORT=1883 \
--from-literal=MQTT_USERNAME=homeassistant \
--from-literal=MQTT_PASSWORD=your-password
# Restart controller to pick up secret
kubectl rollout restart deployment/hass-crds-controller-manager -n hass-crds-systemgit clone https://github.com/spontus/hass-crds.git
cd hass-crds
# Install CRDs
make install
# Deploy controller (builds and pushes image)
make deployThe controller requires the following environment variables for MQTT connection:
| Variable | Required | Default | Description |
|---|---|---|---|
MQTT_BROKER |
Yes | - | MQTT broker hostname |
MQTT_PORT |
No | 1883 |
MQTT broker port |
MQTT_USERNAME |
No | - | MQTT username |
MQTT_PASSWORD |
No | - | MQTT password |
MQTT_CLIENT_ID |
No | auto-generated | MQTT client ID |
MQTT_USE_TLS |
No | false |
Enable TLS (true or 1) |
apiVersion: mqtt.home-assistant.io/v1alpha1
kind: MQTTButton
metadata:
name: garage-door-button
namespace: home-automation
spec:
name: "Garage Door"
commandTopic: "home/garage/door/command"
payloadPress: "TOGGLE"
icon: "mdi:garage"apiVersion: mqtt.home-assistant.io/v1alpha1
kind: MQTTSensor
metadata:
name: living-room-temperature
namespace: home-automation
spec:
name: "Living Room Temperature"
stateTopic: "home/living-room/temperature"
unitOfMeasurement: "°C"
deviceClass: "temperature"
stateClass: "measurement"
device:
name: "Living Room Sensor Hub"
identifiers:
- "living-room-hub-001"
manufacturer: "DIY"
model: "ESP32 Sensor Hub"apiVersion: mqtt.home-assistant.io/v1alpha1
kind: MQTTSwitch
metadata:
name: office-light
namespace: home-automation
spec:
name: "Office Light"
commandTopic: "home/office/light/set"
stateTopic: "home/office/light/state"
payloadOn: "ON"
payloadOff: "OFF"
availability:
- topic: "home/office/light/status"
payloadAvailable: "online"
payloadNotAvailable: "offline"
availabilityMode: "all"apiVersion: mqtt.home-assistant.io/v1alpha1
kind: MQTTClimate
metadata:
name: bedroom-thermostat
namespace: home-automation
spec:
name: "Bedroom Thermostat"
modeCommandTopic: "home/bedroom/hvac/mode/set"
modeStateTopic: "home/bedroom/hvac/mode/state"
temperatureCommandTopic: "home/bedroom/hvac/temp/set"
temperatureStateTopic: "home/bedroom/hvac/temp/state"
currentTemperatureTopic: "home/bedroom/hvac/current"
modes:
- "off"
- "heat"
- "cool"
- "auto"
minTemp: 16
maxTemp: 30
tempStep: 0.5apiVersion: mqtt.home-assistant.io/v1alpha1
kind: MQTTLight
metadata:
name: kitchen-light
namespace: home-automation
spec:
name: "Kitchen Light"
commandTopic: "home/kitchen/light/set"
stateTopic: "home/kitchen/light/state"
brightnessCommandTopic: "home/kitchen/light/brightness/set"
brightnessStateTopic: "home/kitchen/light/brightness/state"
brightnessScale: 255
rgbCommandTopic: "home/kitchen/light/rgb/set"
rgbStateTopic: "home/kitchen/light/rgb/state"- You create an MQTT entity CRD in Kubernetes
- The controller detects the new resource
- Controller builds an MQTT discovery payload
- Payload is published to
homeassistant/<component>/<namespace>-<name>/config - Home Assistant receives the discovery message and creates the entity
- When you delete the CRD, the controller publishes an empty payload to remove the entity
Discovery topics follow the pattern:
homeassistant/<component>/<namespace>-<name>/config
For example, an MQTTButton named garage-door in namespace home publishes to:
homeassistant/button/home-garage-door/config
Each entity gets a unique ID automatically generated from <namespace>-<name>. You can override this with the uniqueId field in the spec.
The controller includes a built-in web dashboard for managing MQTT entities. Access it at port 8080 on the controller pod.
- Dashboard: Overview of all entities with status indicators
- Entity List: Filter and search entities by type, namespace, or name
- Create Wizard: Dynamic forms generated from CRD schemas
- Edit/Delete: Modify or remove existing entities
- YAML Preview: View the generated Kubernetes manifest before creation
# Port forward to access the UI locally
kubectl port-forward -n hass-crds-system deployment/hass-crds-controller-manager 8080:8080
# Open in browser
open http://localhost:8080make build # Build controller binary
make docker-build # Build Docker imagemake test # Go unit tests with envtest
make test-api # API handler unit tests
make test-frontend # Frontend unit tests (Vitest)
make test-all # Run all tests (Go + Frontend)
make test-e2e # E2E tests (requires Docker, Kind)
make lint # Run lintermake generate # Generate DeepCopy methods
make crds # Generate CRD manifests (Python-based)
make manifests # Generate RBAC manifestsApache License 2.0