॥ श्री ॥

Home Automation

Self-Hosting & Servers 2026-08-28

Smart home hubs, IoT bridges, camera NVRs, and automation pipelines — all running locally with no cloud dependency.

Why local? Cloud-dependent smart home devices can stop working when manufacturers shut down servers or change APIs. Local automation gives you sub-50ms response times, works during internet outages, and keeps all your sensor data on your own hardware.

Key Concepts

MQTT — the IoT messaging backbone

MQTT (Message Queuing Telemetry Transport) is a publish-subscribe protocol designed for constrained devices on unreliable networks. A device (ESP32, Shelly plug, Zigbee sensor via zigbee2mqtt) publishes a message to a topic (home/livingroom/temperature); any subscriber (Home Assistant, Node-RED, Telegraf) receives it. The broker (Mosquitto, EMQX) routes messages without the publisher knowing who reads them. Key concepts: QoS levels (0 = fire-and-forget, 1 = at-least-once with acknowledgement, 2 = exactly-once), retained messages (the broker stores the last message on a topic, so new subscribers immediately get the current state), and will messages (sent by the broker when a client disconnects unexpectedly — useful for device-offline detection). MQTT is ubiquitous in IoT engineering roles.

Zigbee, Z-Wave, and Matter — wireless protocol comparison

Three competing wireless protocols for smart home devices: Zigbee (2.4 GHz mesh, 250 kbps, up to 65,000 devices, most widely supported, requires a coordinator dongle), Z-Wave (sub-GHz mesh, less interference than Zigbee/WiFi, maximum 232 devices per network, better range through walls, proprietary silicon requires certification), and Matter (IP-based standard on Thread or WiFi, Apple/Google/Amazon/Amazon-endorsed, designed to unify the ecosystem, still maturing). The operational reality: Zigbee has the broadest device support and lowest device cost; Z-Wave is more reliable in RF-noisy environments; Matter is the future but current device selection is limited. Zigbee2MQTT's device database of 3,000+ supported devices makes it the practical choice today.

Home Assistant's entity model

Home Assistant's core abstraction is the entity — a representation of a single capability of a device (a smart bulb has entities for brightness, colour temperature, power state, and energy consumption). Entities have states (on, off, 23.5) and attributes (additional metadata). Automations, dashboards, and integrations all operate on entities. The entity registry maps entity IDs to their underlying devices and integration source. Understanding this model is essential for debugging: when a device behaves unexpectedly, you inspect the entity's state history in the developer tools to determine whether the problem is in the device, the integration, or the automation.

Event-driven automation and state machines

Home Assistant automations are event-driven: a trigger (state change, time, webhook, sunrise) fires the automation; conditions gate whether actions execute; actions change states or call services. Complex automations are state machines — a "good night" script transitions the house from "awake" to "sleeping" mode by setting multiple devices in sequence. The input_boolean and input_select helpers act as stateful flags for multi-step automations. AppDaemon exposes this same model in Python, enabling loops, timers, and external API calls that YAML automations can't express. Event-driven architecture is a core backend engineering pattern; Home Assistant is a concrete, hands-on implementation.

ESPHome and firmware-over-the-air updates

ESPHome compiles YAML device definitions to C++ and flashes them to ESP32/ESP8266 microcontrollers. Once a device has ESPHome flashed, subsequent updates happen over-the-air (OTA) via the WiFi network — no physical access required. ESPHome's native API (a protobuf-based binary protocol) integrates directly with Home Assistant without MQTT. The compilation and OTA update pipeline is a miniature CI/CD system: edit the YAML, compile, push to device, verify. This experience with embedded firmware deployment maps directly to IoT engineering roles dealing with fleet management and OTA update pipelines at scale.

WebRTC and zero-latency camera streams

go2rtc introduces the difference between streaming protocols: RTSP (Real-Time Streaming Protocol, used by IP cameras) has 2–10 second latency due to buffering. WebRTC (used by browsers and go2rtc) achieves sub-second latency by using UDP with SRTP (Secure Real-time Transport Protocol) and a direct peer connection to the browser. HLS (HTTP Live Streaming) has the lowest compatibility requirements but highest latency (5–30 seconds). For home security applications, WebRTC is required for live view of camera streams; HLS is acceptable for recorded playback. Frigate uses go2rtc internally for its live view.

Home Assistant

Purpose: The leading open-source home automation platform. Integrates with 3,000+ devices and services — lights, sensors, thermostats, cameras, locks, media players, energy monitors. Supports automations, dashboards, voice assistants (local and cloud), and a mobile app.

# ~/homeassistant/compose.yaml
services:
  homeassistant:
    image: ghcr.io/home-assistant/home-assistant:stable
    network_mode: host
    volumes:
      - /home/user/homeassistant/config:/config:Z
    environment:
      TZ: Asia/Kolkata
    restart: unless-stopped
cd ~/homeassistant && podman-compose up -d
--network host is required for Home Assistant to discover devices on your local network via mDNS and UPnP.

Access at http://localhost:8123. On first run, Home Assistant automatically discovers many devices on your network.

Backup your config
# The built-in backup tool (Settings → System → Backups) creates .tar archives
# Back them up offsite with Restic
restic backup /home/user/homeassistant/config

Common operations

# Check Home Assistant config validity
podman exec homeassistant hass --script check_config -c /config

# Restart Home Assistant (soft restart, keeps docker running)
curl -X POST http://localhost:8123/api/services/homeassistant/restart   -H "Authorization: Bearer YOUR_LONG_LIVED_TOKEN"   -H "Content-Type: application/json"

# View live logs
podman logs -f homeassistant

# Call a service via API
curl -X POST http://localhost:8123/api/services/light/turn_on   -H "Authorization: Bearer YOUR_LONG_LIVED_TOKEN"   -H "Content-Type: application/json"   -d '{"entity_id": "light.living_room"}'

# Get current state of an entity
curl http://localhost:8123/api/states/sensor.bedroom_temperature   -H "Authorization: Bearer YOUR_LONG_LIVED_TOKEN"

# List all entities
curl http://localhost:8123/api/states   -H "Authorization: Bearer YOUR_LONG_LIVED_TOKEN" | python3 -m json.tool

# Run a one-off backup
curl -X POST http://localhost:8123/api/backup   -H "Authorization: Bearer YOUR_LONG_LIVED_TOKEN"

Mushroom Cards, Mini Graph Card, Browser Mod, Local Tuya, Adaptive Lighting.


Mosquitto (MQTT Broker)

Purpose: Lightweight MQTT message broker. Required for Zigbee2MQTT, ESPHome, and many other IoT integrations. Acts as the communication backbone between devices and Home Assistant.

# ~/mosquitto/compose.yaml
services:
  mosquitto:
    image: eclipse-mosquitto
    ports:
      - 127.0.0.1:1883:1883
    volumes:
      - /home/user/mosquitto/config:/mosquitto/config:Z
      - /home/user/mosquitto/data:/mosquitto/data:Z
      - /home/user/mosquitto/log:/mosquitto/log:Z
    restart: unless-stopped
cd ~/mosquitto && podman-compose up -d
Require authentication (do this before anything connects)

Mosquitto ships with no config — create one that rejects anonymous clients:

cat > /home/user/mosquitto/config/mosquitto.conf << 'EOF'
listener 1883 0.0.0.0
allow_anonymous false
password_file /mosquitto/config/passwd
EOF

# Create the password file (user "user", prompts for a password)
podman run --rm -v /home/user/mosquitto/config:/mosquitto/config:Z \
  eclipse-mosquitto mosquitto_passwd -c /mosquitto/config/passwd user

podman-compose restart

Monitor MQTT traffic

# Subscribe to all topics (useful for debugging)
podman exec mosquitto mosquitto_sub -u user -P yourpassword -t '#' -v

Common operations

# Subscribe to all topics (debug)
podman exec mosquitto mosquitto_sub -h localhost -u user -P yourpassword -t '#' -v

# Subscribe to a specific topic
podman exec mosquitto mosquitto_sub -h localhost -u user -P yourpassword -t 'home/bedroom/temperature'

# Publish a message
podman exec mosquitto mosquitto_pub -h localhost -u user -P yourpassword   -t 'home/bedroom/temperature' -m '22.5'

# Check broker stats
podman exec mosquitto mosquitto_sub -h localhost -u user -P yourpassword   -t '$SYS/#' -C 10

# View connected clients count
podman exec mosquitto mosquitto_sub -h localhost -u user -P yourpassword   -t '$SYS/broker/clients/connected' -C 1

Zigbee2MQTT

Purpose: Bridges Zigbee devices (lights, sensors, plugs, locks) to MQTT using a $10–15 USB Zigbee coordinator. Works with 3,000+ Zigbee devices from any manufacturer — no proprietary hubs, no cloud bridges, no subscriptions.

Supported coordinators

Sonoff Zigbee 3.0 USB Dongle Plus, CC2652R/P, HUSBZB-1, Conbee II.

# ~/zigbee2mqtt/compose.yaml
services:
  zigbee2mqtt:
    image: koenkk/zigbee2mqtt
    volumes:
      - /home/user/zigbee2mqtt/data:/app/data:Z
    devices:
      - /dev/ttyUSB0:/dev/ttyUSB0
    environment:
      TZ: Asia/Kolkata
    restart: unless-stopped
cd ~/zigbee2mqtt && podman-compose up -d

Common operations

# Enable pairing mode (permit join for 60 seconds)
podman exec mosquitto mosquitto_pub -h localhost -u user -P yourpassword   -t 'zigbee2mqtt/bridge/request/permit_join' -m '{"value":true,"time":60}'

# List all paired devices
podman exec mosquitto mosquitto_sub -h localhost -u user -P yourpassword   -t 'zigbee2mqtt/bridge/devices' -C 1 | python3 -m json.tool

# Get current state of a device
podman exec mosquitto mosquitto_sub -h localhost -u user -P yourpassword   -t 'zigbee2mqtt/MY_DEVICE' -C 1

# Rename a device
podman exec mosquitto mosquitto_pub -h localhost -u user -P yourpassword   -t 'zigbee2mqtt/bridge/request/device/rename'   -m '{"from":"0x1234abcd5678","to":"bedroom_sensor"}'

# Remove (unlink) a device
podman exec mosquitto mosquitto_pub -h localhost -u user -P yourpassword   -t 'zigbee2mqtt/bridge/request/device/remove' -m '{"id":"bedroom_sensor"}'

# View Z2M logs
podman logs -f zigbee2mqtt
Find your coordinator: ls /dev/tty* or dmesg | grep tty after plugging it in.
Minimal configuration.yaml
homeassistant: true
mqtt:
  server: mqtt://localhost:1883
  user: user
  password: yourpassword
serial:
  port: /dev/ttyUSB0
frontend:
  port: 8080

Access the web UI at http://localhost:8080 to pair devices and view the network map.


ESPHome

Purpose: Compile and flash YAML-based firmware to ESP32/ESP8266 microcontrollers. Build custom sensors, switches, displays, and automations that integrate directly with Home Assistant over Wi-Fi — no cloud, no pairing apps.

# ~/esphome/compose.yaml
services:
  esphome:
    image: esphome/esphome
    ports:
      - 127.0.0.1:6052:6052
    volumes:
      - /home/user/esphome/config:/config:Z
    environment:
      TZ: Asia/Kolkata
    restart: unless-stopped
cd ~/esphome && podman-compose up -d
Example device config (temperature + humidity sensor)
# /home/user/esphome/config/bedroom-sensor.yaml
esphome:
  name: bedroom-sensor

esp32:
  board: esp32dev

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

api:
  encryption:
    key: !secret api_key

ota:
  password: !secret ota_password

sensor:
  - platform: dht
    pin: GPIO4
    temperature:
      name: "Bedroom Temperature"
    humidity:
      name: "Bedroom Humidity"
    update_interval: 60s

Create a secrets.yaml alongside your device configs defining every !secret key (wifi_ssid, wifi_password, api_key, ota_password) — the dashboard compiles each device against it.


Node-RED

Purpose: Flow-based visual programming for wiring devices, APIs, and automations. Great for complex logic that is easier to build visually than in Home Assistant's YAML automations. Useful for integrating non-HA services (e.g., MQTT → database → notification).

# ~/node-red/compose.yaml
services:
  node-red:
    image: nodered/node-red
    ports:
      - 127.0.0.1:1880:1880
    volumes:
      - /home/user/nodered/data:/data:Z
    environment:
      TZ: Asia/Kolkata
    restart: unless-stopped
cd ~/node-red && podman-compose up -d

Access at http://localhost:1880. Install the node-red-contrib-home-assistant-websocket palette to connect to Home Assistant. Install node-red-node-sqlite to log sensor data locally.


Matter Server

Purpose: Bridges Matter/Thread smart home devices to Home Assistant. Matter is the new unified smart home standard supported by Apple, Google, Amazon, and hundreds of device manufacturers — all locally, no cloud required.

# ~/matter-server/compose.yaml
services:
  matter-server:
    image: ghcr.io/home-assistant-libs/python-matter-server:stable
    network_mode: host
    volumes:
      - /home/user/matter-server/data:/data:Z
    restart: unless-stopped
cd ~/matter-server && podman-compose up -d

In Home Assistant: Settings → Devices & Services → Add Integration → Matter (BETA). Point it at ws://localhost:5580/ws.

You need a Thread border router to use Thread devices. Apple HomePod mini, Google Nest Hub, or a dedicated USB Thread dongle all work.

Frigate

Purpose: Network Video Recorder (NVR) with real-time AI object detection — people, cars, animals, packages. Runs detection locally using your GPU or a Coral TPU. Integrates deeply with Home Assistant for automations triggered by detections.

# ~/frigate/compose.yaml
services:
  frigate:
    image: ghcr.io/blakeblackshear/frigate:stable
    ports:
      - 127.0.0.1:5000:5000
      - 127.0.0.1:8554:8554
      - 127.0.0.1:8555:8555/udp
    volumes:
      - /home/user/frigate/config:/config:Z
      - /home/user/frigate/media:/media/frigate:Z
    devices:
      - /dev/dri:/dev/dri
    shm_size: 256m
    restart: unless-stopped
cd ~/frigate && podman-compose up -d
Minimal config.yml
mqtt:
  enabled: true
  host: localhost
  user: user
  password: yourpassword

cameras:
  front-door:
    ffmpeg:
      inputs:
        - path: rtsp://camera-ip:554/stream
          roles: [detect, record]
    detect:
      width: 1280
      height: 720
      fps: 5

detectors:
  cpu1:
    type: cpu
Add a Google Coral USB TPU (--device /dev/bus/usb) for hardware-accelerated detection at 100+ FPS with minimal CPU usage.

Double Take (Facial Recognition)

Purpose: Integrates with Frigate to identify specific people by face. When Frigate detects a person, Double Take runs recognition against a library of known faces and publishes the result to MQTT — letting Home Assistant trigger "welcome home" automations by person.

# ~/double-take/compose.yaml
services:
  double-take:
    image: jakowenko/double-take
    ports:
      - 127.0.0.1:3002:3000
    volumes:
      - /home/user/double-take/.storage:/.storage:Z
    restart: unless-stopped
cd ~/double-take && podman-compose up -d

Configure recognisers (CompreFace, DeepStack, or CodeProject.AI) in the Double Take UI, then add face images to the library.


go2rtc (WebRTC Camera Gateway)

Purpose: Universal camera streaming gateway. Takes any RTSP, RTMP, ONVIF, USB, or HTTP camera stream and re-serves it as WebRTC (browser-viewable), MSE, HLS, or RTSP. Zero-latency browser previews, multi-stream support, and deep Frigate and Home Assistant integration — go2rtc powers the camera streams in Frigate 0.13+ and Home Assistant's WebRTC camera card.

# ~/go2rtc/compose.yaml
services:
  go2rtc:
    image: alexxit/go2rtc
    ports:
      - 127.0.0.1:1984:1984
      - 8554:8554
      - 8555:8555/tcp
      - 8555:8555/udp
    volumes:
      - /home/user/go2rtc/go2rtc.yaml:/config/go2rtc.yaml:ro,Z
    restart: unless-stopped
cd ~/go2rtc && podman-compose up -d
Example go2rtc.yaml
streams:
  front-door: rtsp://admin:password@192.168.1.101:554/stream1
  back-yard: rtsp://admin:password@192.168.1.102:554/h264Preview_01_main
  doorbell: rtspx://192.168.1.103:7441/api/camera/proxy/...

webrtc:
  candidates:
    - 192.168.1.10:8555  # your server's LAN IP

api:
  listen: ":1984"

Access the web UI at http://localhost:1984 to view live streams in the browser. In Frigate config, set go2rtc.streams to reference the same stream names.


Z-Wave JS UI (Z-Wave Device Bridge)

Purpose: Full-featured Z-Wave device manager and MQTT bridge. Similar to Zigbee2MQTT but for Z-Wave — manages your Z-Wave USB controller (Aeotec Z-Stick, HUSBZB-1, Zooz ZST10), pairs devices, exposes them to Home Assistant via MQTT or WebSocket, and provides a visual mesh network map. Required for Z-Wave devices like Yale/Schlage smart locks, Fibaro sensors, and Qubino modules.

# ~/zwave-js-ui/compose.yaml
services:
  zwave-js-ui:
    image: zwavejs/zwave-js-ui:latest
    ports:
      - 127.0.0.1:8091:8091
      - 127.0.0.1:3003:3000   # host port 3002 is used by Double Take — mapped to 3003 here
    volumes:
      - /home/user/zwave-js-ui/store:/usr/src/app/store:Z
    devices:
      - /dev/ttyUSB1:/dev/ttyUSB1
    environment:
      TZ: Asia/Kolkata
    restart: unless-stopped
cd ~/zwave-js-ui && podman-compose up -d
Find your Z-Wave stick: ls /dev/ttyUSB* after plugging it in (may be ttyUSB0 or ttyACM0 depending on the model).

In Home Assistant: Settings → Devices & Services → Add Integration → Z-Wave JS → use WebSocket URL ws://host.containers.internal:3003.


Scrypted (Camera Hub & NVR)

Purpose: Camera management and NVR platform with a focus on HomeKit Secure Video integration. Supports 40+ camera brands, transcodes streams to HomeKit format, and integrates with Google Home, Alexa, Home Assistant, and Frigate. If you want your RTSP cameras to appear natively in Apple Home or Google Home, Scrypted is the bridge.

# ~/scrypted/compose.yaml
services:
  scrypted:
    image: koush/scrypted
    network_mode: host
    volumes:
      - /home/user/scrypted/volume:/server/volume:Z
    restart: unless-stopped
cd ~/scrypted && podman-compose up -d
--network host is required for mDNS discovery of cameras and HomeKit pairing. Access the UI at https://localhost:10443 (self-signed cert on first run).

Caddy:

scrypted.home.local { tls internal; reverse_proxy localhost:10443 }

AppDaemon (Python Automation Engine)

Purpose: Python scripting environment for Home Assistant automations. Write complex automation logic in Python instead of YAML — full access to Home Assistant's state machine, events, and services. Ideal for automations that require loops, data structures, external API calls, or logic that would be unwieldy in HA's built-in automation editor. Also includes HADashboard for building kiosk-style tablet wall panels.

# ~/appdaemon/compose.yaml
services:
  appdaemon:
    image: acockburn/appdaemon:latest
    ports:
      - 127.0.0.1:5050:5050
    volumes:
      - /home/user/appdaemon/config:/conf:Z
    environment:
      HA_URL: http://host.containers.internal:8123
      TOKEN: your-long-lived-access-token
      TZ: Asia/Kolkata
    restart: unless-stopped
cd ~/appdaemon && podman-compose up -d
Example app (/conf/apps/notify_on_door.py)
import appdaemon.plugins.hass.hassapi as hass

class DoorNotifier(hass.Hass):
    def initialize(self):
        self.listen_state(self.door_opened, "binary_sensor.front_door", new="on")

    def door_opened(self, entity, attribute, old, new, kwargs):
        self.notify("Front door opened!", name="mobile_app_phone")
        self.call_service("light/turn_on", entity_id="light.porch", brightness=255)

evcc (EV Charging Optimiser)

Purpose: Electric vehicle charging automation — charges your EV using surplus solar power, off-peak tariff windows, or a combination of both. Integrates with 200+ EV chargers (go-e, Wallbox, ABB, etc.), inverters (SMA, Fronius, Huawei, Shelly EM), and energy meters. Displays a real-time dashboard showing solar yield, grid import/export, and charging state.

# ~/evcc/compose.yml
services:
  evcc:
    image: evcc/evcc:latest
    ports: ["127.0.0.1:7070:7070"]
    volumes:
      - /home/user/evcc/evcc.yaml:/etc/evcc.yaml:ro,Z
      - /home/user/evcc/data:/root/.evcc:Z
    environment:
      TZ: Asia/Kolkata
    restart: unless-stopped
cd ~/evcc && podman-compose up -d
Minimal evcc.yaml
network:
  schema: http
  host: evcc.home.local
  port: 7070

interval: 30s

meters:
  - name: grid
    type: template
    template: shelly-3em
    host: 192.168.1.50

chargers:
  - name: wallbox
    type: template
    template: go-e
    host: 192.168.1.60

vehicles:
  - name: mycar
    type: template
    template: generic
    title: My EV
    capacity: 60  # kWh

Access at http://localhost:7070. Set charging mode to PV for solar-only charging, MinPV for guaranteed minimum current topped up by solar, or Now for maximum speed regardless of source.


Caddy Configuration

homeassistant.home.local  { tls internal; reverse_proxy localhost:8123 }
zigbee.home.local         { tls internal; reverse_proxy localhost:8080 }
esphome.home.local        { tls internal; reverse_proxy localhost:6052 }
nodered.home.local        { tls internal; reverse_proxy localhost:1880 }
frigate.home.local        { tls internal; reverse_proxy localhost:5000 }
doubletake.home.local     { tls internal; reverse_proxy localhost:3000 }
appdaemon.home.local      { tls internal; reverse_proxy localhost:5050 }
evcc.home.local           { tls internal; reverse_proxy localhost:7070 }

Troubleshooting

IssueSolution
Home Assistant can't discover devicesEnsure --network host is set; check that mDNS/multicast is not blocked on your LAN
Zigbee2MQTT can't open serial portVerify the device path with ls /dev/ttyUSB*; add your user to the dialout group: sudo usermod -aG dialout $USER
MQTT connection refusedCheck Mosquitto is running and the password file is correct; verify the port is not blocked by firewalld
Frigate using too much CPUSet fps: 5 or lower in detect config; add a Coral TPU or use GPU detection with --device /dev/dri
ESPHome OTA upload failsEnsure the ESP32 is on the same network as the server; check the API encryption key matches in both config and device
Node-RED flows lost after updateFlows are stored in /home/user/nodered/data/flows.json — ensure the volume is mounted correctly
Home Assistant automations not triggeringCheck logs (Settings → System → Logs); verify MQTT messages are arriving with mosquitto_sub -t '#' -v
Matter pairing failsEnsure both the Matter Server and Home Assistant are on the same LAN/VLAN; Matter devices need mDNS broadcast to work
Double Take not recognising facesEnsure Frigate is publishing snapshots to MQTT; check the face library has enough reference images per person (5+ recommended)
WLED not discovered by Home AssistantEnsure WLED and Home Assistant are on the same LAN/VLAN; mDNS must be allowed between them; try adding via IP manually in the WLED integration
WLED LEDs flicker or show wrong coloursCheck data wire connection quality; add a 300–500 Ohm resistor on the data line; ensure GND is shared between the ESP32 and LED strip power supply

WLED (LED Controller)

Purpose: Open-source firmware and web server for addressable LED strips (WS2812B, SK6812, WS2811, and more) running on ESP8266/ESP32. Flash WLED onto a cheap ESP32 board, wire it to your LED strip, and get a full web UI, Home Assistant integration via MQTT and native API, effects library (100+ built-in animations), segments, palettes, and a JSON API. No cloud — WLED runs entirely on the microcontroller and your LAN.

WLED runs on the ESP32 microcontroller itself — not as a container on your server. Your server hosts the Home Assistant integration and optionally a WLED configuration backup.

Flash WLED onto an ESP32 (from your server)

# Install esptool
pip install esptool --break-system-packages

# Download latest WLED firmware
# Replace 0.15.0 with the latest version from https://github.com/Aircoookie/WLED/releases
curl -LO https://github.com/Aircoookie/WLED/releases/latest/download/WLED_0.15.0_ESP32.bin

# Flash (replace /dev/ttyUSB0 with your ESP32 port)
esptool.py --port /dev/ttyUSB0 write_flash 0x0 WLED_0.15.0_ESP32.bin  # update filename to match downloaded version
Or use the browser-based installer at install.wled.me

— plug the ESP32 into any computer and flash directly from the browser without installing tools.

Wire the circuit

ESP32 GPIO2 (Data) ──► LED Strip Data In
ESP32 GND           ──► LED Strip GND   ──► Power Supply GND
5V Power Supply     ──► LED Strip VCC
                                         (do NOT power strip from ESP32 5V)
For more than ~30 LEDs, always use an external 5V power supply. A 60-LED strip at full white draws ~3.6A — far more than USB can provide.

Home Assistant integration

Once WLED is on your network, Home Assistant auto-discovers it via mDNS. Accept the integration and your LED strip appears as a light entity with brightness, colour, and effect controls.

Manual WLED config backup (save to your server)
# Export WLED config via its HTTP API
curl http://192.168.1.XXX/cfg.json -o /home/user/wled/backups/strip-1-cfg.json
curl http://192.168.1.XXX/presets.json -o /home/user/wled/backups/strip-1-presets.json

Control via JSON API

# Set colour to warm white
curl -X POST http://192.168.1.XXX/json/state \
  -H "Content-Type: application/json" \
  -d '{"on":true,"bri":200,"seg":[{"col":[[255,200,100]]}]}'

# Set a built-in effect (effect ID 9 = "Colorloop")
curl -X POST http://192.168.1.XXX/json/state \
  -d '{"seg":[{"fx":9,"sx":128,"ix":200}]}'

# Turn off
curl -X POST http://192.168.1.XXX/json/state -d '{"on":false}'

MQTT control (integrates with Mosquitto)

In WLED web UI → Config → Sync → MQTT:

  • Server: 192.168.1.X (your Mosquitto host)
  • Port: 1883
  • User/Password: your MQTT credentials
  • Topic: wled/strip1
# Control via MQTT
podman exec mosquitto mosquitto_pub -u user -P password \
  -t "wled/strip1" -m "ON"

podman exec mosquitto mosquitto_pub -u user -P password \
  -t "wled/strip1/col" -m "#FF6400"
WLED is one of the most popular DIY smart home projects. A single ESP32 (~$4) + WS2812B strip (~$8/m) gives you full-colour, effect-capable smart lighting at a fraction of the cost of Philips Hue or LIFX.

See Also