HomeAssistantHQ
A pink network of connected nodes and small cubes radiates from a central glowing disc on a dark purple isometric platform, evoking a microcontroller's wireless mesh links.
ESPHome

How to Install ESPHome on ESP32: Setup and First Flash

This guide explains ESPHome installation via the Home Assistant add-on, Docker, or pip, then covers ESP32 setup, USB flashing, and bootloader fixes.

By HomeAssistantHQ Editorial · · 7 min read

The honest answer to how to install ESPHome on ESP32 is that it is two installs, not one. First you put ESPHome itself somewhere: the Home Assistant add-on, a Docker container, or a pip package. Then you use it to compile firmware from a YAML file and push that firmware onto the board. The getting started guide is blunt about the part people try to skip: “The very first install has to happen over a USB cable; every update after that can happen wirelessly.” Below is the shortest path through each hosting option, the config you actually need, and the two things that stall most first flashes: a charge-only USB cable and a board that will not drop into its bootloader.

Who this is for, and who should skip it

You want this if you are building your own sensor, relay or display and you are comfortable editing YAML. Budget an evening for the first device, mostly spent on drivers and cables, and ten minutes for every device after it.

Skip it if you want a temperature sensor that just works. A Zigbee or Thread sensor pairs in a minute and never asks you about frameworks. ESPHome is for people who want to build the device, not just own it.

Pick the hosting option by where Home Assistant runs:

  • Home Assistant OS: use the add-on. It is the least friction and it sees USB directly.
  • Home Assistant Container, or a separate box: run the Docker image. Add-ons need the Supervisor, so the add-on route does not exist on a Container install; the install method comparison explains that split.
  • You want a terminal: pip. Same compiler, no web UI unless you ask for it.

Step 1: install ESPHome three ways

All three come from the official install page. The web UI is now called the ESPHome Device Builder; the compiler underneath is still esphome.

Home Assistant add-on. Open Settings, then Apps, then Install App, search for “ESPHome Device Builder”, then Install, Start and Open Web UI. If the store cannot find it, the add-on repository is https://github.com/esphome/home-assistant-addon.

Docker. The documented one-liner:

docker run --rm --net=host -v "${PWD}":/config -it ghcr.io/esphome/esphome

The dashboard listens on port 6052. The --net=host flag is there for mDNS, which is how the dashboard finds your devices for wireless updates. On Docker Desktop you have to substitute -p 6052:6052 and lose discovery, which the docs say outright. If host networking is new to you, Docker Homelab’s host networking guide covers why it exists and what it costs. To flash over USB from inside the container, the FAQ says to pass the port through with --device=/dev/ttyUSB0. Update later with docker pull ghcr.io/esphome/esphome:stable.

pip. The requirement is Python 3.12 or newer, and the docs add: “Install into a virtual environment if you can. Many Linux distributions now refuse to pip install into the system Python.”

python3 -m venv ~/esphome-venv
source ~/esphome-venv/bin/activate
pip install "esphome-device-builder[esphome]"
esphome-device-builder config

That gives you the same web UI on port 6052, pointed at a config directory. If you only want the CLI, pip install esphome is enough, and pip3 install -U esphome updates it.

Step 2: the ESP32 config

In the Device Builder, click Create device, choose New Device Setup, pick your platform and enter Wi-Fi credentials. On the CLI, esphome wizard office-sensor.yaml asks the same questions. Either way you end up with something close to this:

esphome:
  name: office-sensor
  friendly_name: Office Sensor

esp32:
  variant: esp32

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    ssid: "Office Sensor Fallback"
    password: !secret ap_password

logger:

api:
  encryption:
    key: !secret api_key

ota:
  - platform: esphome

What each block is doing, with the rules that bite:

  • name “may only contain lowercase characters, digits and hyphens” and is capped at 24 characters by default, per the core component docs. friendly_name is what Home Assistant shows as the device name.
  • variant is the chip family: esp32, esp32s2, esp32s3, esp32c3, esp32c6 and so on. The ESP32 platform docs now recommend variant over the older PlatformIO board ID, which has become optional. flash_size defaults to 4MB; set it if your module has more.
  • The framework defaults to ESP-IDF. The 2026.1.0 changelog lists it as a breaking change: “[esp32] Breaking Change: Change default framework to ESP-IDF”. Arduino is still available as an ESP-IDF component, but ESP-IDF is mandatory on the C2, C5, C6, C61, H2 and P4 variants. Do not add a framework: block unless a specific component tells you to.
  • !secret pulls from secrets.yaml next to your config. The wifi docs say it is “highly recommended to use secrets” for credentials. The ap: block is a fallback hotspot the device raises when it cannot join your network; it lets you fix a wrong Wi-Fi password without walking the board back to a USB port.
  • The api encryption key is “a 32-byte base64-encoded string”, and the API docs page has a generator for it. Home Assistant will ask for this key when it adopts the device, so keep it.
  • ota needs the platform key since 2024.6.0, per the OTA docs. Older tutorials that show a bare ota: will fail validation.

Step 3: the first flash over USB

Two hardware checks before you click anything. The physical connection guide warns that “a power only USB cable that usually comes presupplied with powerbanks won’t work”. Then the driver: the ESP32-DevKitC and most clones carry a USB-to-UART bridge, and the same guide links drivers for the CH34x, CP2102 and PL2303 chips. On Linux the CP210x driver is maintained in the kernel tree according to Silicon Labs, so the board usually just appears; run dmesg after plugging in to find the port name. Windows and macOS may need the download.

From there you have two routes:

Browser. Click Install in the Device Builder and choose to plug the board into the computer you are browsing from. This uses Web Serial, which ESP Web Tools says “is available in Mozilla Firefox, Google Chrome and Microsoft Edge browsers (but not on your iOS device)”. This is also the escape hatch when the machine running ESPHome cannot see USB at all, such as Docker Desktop or Home Assistant in a VM without passthrough: download the compiled binary and flash it from web.esphome.io, which the FAQ notes processes the file locally rather than uploading it anywhere.

CLI. esphome run office-sensor.yaml compiles and then asks whether to upload over the serial port or over the air. esphome logs office-sensor.yaml tails the serial log so you can watch it join Wi-Fi.

When it will not connect

The classic symptom is Connecting....____.... repeating until it times out. That means the chip is not in its bootloader. Espressif’s boot mode documentation states the rule: “The ESP32 will enter the serial bootloader when GPIO0 is held low on reset.” Development boards do this automatically because the flasher “resets ESP32 automatically by asserting DTR and RTS control lines of the USB to serial converter chip”, but the same page notes that some third-party boards omit a capacitor on the EN pin and reset unreliably.

The manual fix is on the DevKitC user guide: “Holding down Boot and then pressing EN initiates Firmware Download mode.” Hold BOOT, tap EN, release BOOT, then start the upload. Boards without buttons need GPIO0 bridged to GND with a wire, and the ESPHome guide adds that you may need to power-cycle between erasing and uploading.

Two more from the FAQ: check that the port name has not changed between unplugs, and try a double-press on reset on boards that expect it. If it browns out mid-flash, the DevKitC guide’s rule applies: power from “one and only one” of the USB port, 5V pin or 3V3 pin.

Step 4: adopt it in Home Assistant

Once the board is on Wi-Fi, Home Assistant “can be auto-discovered” and shows the device as Discovered on the Integrations page, per the ESPHome integration docs. Click it and paste the encryption key when prompted; the field is noise_psk if you are adding it by hand. If nothing appears, add it manually by hostname, office-sensor.local, then work out why mDNS is not crossing; a Docker install without host networking and a VLAN boundary are the usual causes.

One quirk worth knowing: the API component has a reboot_timeout that reboots the device after 15 minutes without a client connection, because sometimes the ESP reports itself connected when it is not. If you are running a board without Home Assistant attached, set it to 0s.

After adoption, every change is the same loop: edit the YAML, click Install, choose Wirelessly. The USB cable goes back in the drawer until you brick something. If you are still deciding what should run Home Assistant itself, the hardware guide covers the hub side.

Sources

  1. Install ESPHome (ESPHome docs)
  2. Getting Started with ESPHome and Home Assistant (ESPHome docs)
  3. ESP32 Platform (ESPHome docs)
  4. ESPHome 2026.1.0 changelog
  5. Native API Component (ESPHome docs)
  6. OTA Update Component (ESPHome docs)
  7. Frequently Asked Questions (ESPHome docs)
  8. Physically Connecting to your Device (ESPHome docs)
  9. Boot Mode Selection (esptool docs, Espressif)
  10. ESP32-DevKitC V4 User Guide (Espressif)
  11. ESP Web Tools
  12. ESPHome integration (Home Assistant docs)
  13. CP210x USB to UART Bridge VCP Drivers (Silicon Labs)
#esphome#esp32 #home-assistant #installation #docker#diy-sensors

Related