This post may contain affiliate links. As an Amazon Associate we earn from qualifying purchases. Disclosure.

TL;DR

ESPHome 2026.9.0 shipped on 16 September 2026 with 275 merged pull requests. The one that needs a plan is encrypted OTA: firmware images stop crossing your network in plaintext, but moving a device off an OTA password takes two installs in a fixed order, and the wrong order fails with a message the release notes quote verbatim. Here is what the notes and the OTA documentation commit to, read from a house with one ESP32 that matters.

Quick take: ESPHome 2026.9.0 landed on 16 September 2026 and 2026.9.1 followed on 29 September. The headline is Noise-encrypted OTA updates that reuse the API key you already have. Migrating off an OTA password is two installs in a fixed order, and the plaintext fallback goes away in 2027.3.0. Encryption also got about half as expensive in flash, builds got faster, and the Modbus controller changed enough to fail validation on older configs.

Where I'm writing from, so you can weigh the rest. The house runs Home Assistant OS on a Raspberry Pi 5 in the electrical cabinet, and the one ESPHome device that matters here is an ESP32 sitting on the back of the Gree Versati III heat pump controller, bridging its Modbus port to Wi-Fi. The config for that bridge is the one in our Gree Versati III ESPHome guide, and it was validated against ESPHome 2026.9, which is exactly why I read this release more carefully than usual. I haven't walked a fleet of twenty boards through the password migration, and I'm not going to pretend otherwise. What follows is what the release notes and the OTA documentation actually commit to, plus where I'd be careful.

Why Does Encrypted OTA Need a Plan?

The release notes put it in one sentence: until now the firmware image was sent over the network unencrypted. Think about what's inside that image. Your Wi-Fi password. The API encryption key that protects the link to Home Assistant. Anything in secrets.yaml the config pulled in. An OTA password only decided whether the uploader was allowed to send; it never hid what was sent.

2026.9.0 encrypts that image. It adds Noise encryption (ChaCha20-Poly1305, the same protocol the native API already uses) to the esphome OTA platform. The design choice I like most is that there's one key per device. Leave the key out of the encryption: block and ESPHome reuses the API encryption key. Set a separate key only on a device with no api: block at all, such as something that talks MQTT only. If you do give it an explicit key while a static API key exists, the two must match or validation refuses the config. No second secret to lose.

The two-step migration, in the order that works

This is the part people will get wrong, because the obvious shortcut fails. Per the OTA platform documentation:

  1. Keep password: in the config and install 2026.9.0 or newer. The firmware already on the device still checks that password until it's replaced. Afterwards the log should read Encryption: offered, plaintext accepted.
  2. Replace password: with encryption: and install again. The log should now read Encryption: required.

Remove the password before step one and the upload stops with ESP requests password, but no password given!. Swap in encryption: before step one and you get the device did not offer encryption; refusing to send the image in plaintext. Neither does any damage. Both cost you a confused ten minutes if you didn't know they were coming.

The finished config is short:

api:
  encryption:
    key: !secret versati_modbus_api_key

ota:
  - platform: esphome
    encryption:

Devices with no api: need a detour the docs spell out: add a temporary api: block with a generated key and reboot_timeout: 0s for step one, then in step two delete that block and move the same key under ota: encryption: key:.

What you're signing up for

Once encryption is on, the device refuses plaintext OTA. Lose the key and the documented recovery is a serial flash, or the web_server OTA platform if the config includes it. That second route is also why adding web_server OTA next to encryption: produces a validation warning: that endpoint accepts the same firmware over plain HTTP, so it undoes the point. The captive portal's update page gets no such warning, because it only exists while the fallback access point is up.

And there's a clock. The release notes say unencrypted updates on older firmware stop working from 2027.3.0. After that, a board still on pre-2026.9 firmware needs a cable. Six months sounds like plenty. It isn't if the board is inside a wall.

Worth sharing

An OTA password never protected the firmware. It decided who could send a file that carried your Wi-Fi password in the clear.

How Did Encryption Get Smaller?

You can't ask an ESP8266 to encrypt one more thing if encryption already eats 80 KB. So the same release nearly halved the cost. These are the figures the release notes give, 2026.8.0 against 2026.9.0:

BoardFlash beforeFlash afterStatic RAM beforeStatic RAM afterNoise handshake
ESP8266 d1 mini80.9 KB41.9 KB1376 B48 B~580 ms to ~300 ms
ESP32 AtomU (IDF)65.9 KB37.7 KB56 B32 B63 ms to 46 ms
Pico W (RP2040)65.5 KB34.7 KB48 B24 B~260 ms to ~200 ms

The d1 mini line is the one to stare at. 1376 bytes of static RAM down to 48 on a chip with roughly 40 KB usable heap is not a rounding error. Separately, the release moved 211 conditional log strings across 60 files into flash, which the notes say saves 80 bytes of RAM on a sample d1 mini config, and dropped the base64 alphabet table for another 64. Small numbers. On an ESP8266 that reboots when the heap runs dry, small numbers are the whole game.

Is any of that visible from Home Assistant? No. Your sensor doesn't get a new entity. What you get is a board that used to be marginal staying up through an OTA.

Who Benefits From the Faster Builds?

Three things in the notes, all with numbers attached. Library and tool downloads and PlatformIO package installs now run in parallel, and on the project's own CI the package phase dropped from 17.1 s to 10.3 s, from 36% of the build down to 25%. Registry and tool downloads were parallelized too, cutting a step of about 100 s to about 46 s on every architecture leg. And a no-op rebuild of a six-library config fell from 2.9 s to 0.4 s, which the notes quote as about 2.2 s saved on a desktop and several times more on a single-board computer.

That last one is the one you'll feel on a Pi, because the ESPHome add-on compiles on the same machine that runs your house.

There's also groundwork nobody can use yet. The notes say this release lays the entire scaffolding for building ESP8266 firmware without PlatformIO: a resumable, sha256-verified installer for Arduino ESP8266 core 3.1.2 and xtensa gcc 10.3. It ships dormant, with no user-facing option, so the native toolchain itself can land in 2026.10.0. Worth knowing when the next release note reads like a non-event.

What Happens Now When Memory Runs Out?

Before 2026.9.0, an allocation that failed when the heap was exhausted aborted and rebooted the device instead of returning null. The release changes that in a handful of specific places: a Wi-Fi scan whose results can't be allocated is dropped with a warning and retried; each API connection now keeps one reusable overflow buffer with a capped backlog instead of growing; and OTA verification no longer fragments the heap in a way that, in the notes' own words, could take a low-heap device down during the 90 second OTA confirmation window. The Nextion queue and the W5500 SPI context got the same treatment.

A reboot during the confirmation window is the worst kind of failure, because the device comes back on the old firmware and reports nothing. If you've watched a d1 mini go quiet after an update and then reappear as if nothing happened, this is probably the paragraph that explains it.

What Changed in Provisioning, Improv, and Modbus?

The provisioning change is small and sharp. The Wi-Fi access point and captive portal are now torn down when the provisioning window closes. Good for security, with one consequence the notes state plainly: an unprovisioned device that times out is fully unprovisionable until it's power-cycled. Config validation now also warns when Wi-Fi is set up with an access point and no station credentials, which is the exact combination that produces a board you can see but never join.

improv_serial became aware of the whole network stack rather than Wi-Fi alone, so it works on Ethernet-only boards and, on Wi-Fi-less builds, reports STOPPED so a client doesn't offer a Wi-Fi form that can't succeed. If you flash from a browser, that's the fix for a form that silently did nothing.

Then Modbus. The modbus_controller component was overhauled: writer entities become their own heap-free hub device, range polling is unified, and continuous reads are supported. The breaking list is what matters before you press Install:

  • custom_command is renamed custom_pdu
  • address: 0 is rejected
  • skip_updates is retired; the notes say to split those sensors onto a second controller
  • register_count and force_new_range are replaced by one reuse_previous_range option
  • switch and output write offsets are now applied byte-accurately, and a switch write_lambda returns the wire value only
  • lambdas using ModbusCommandItem or queue_command() are deprecated, with removal in 2027.3.0

That list is why the Versati bridge config was checked against 2026.9 before the guide went out. A register map written for 2026.7 isn't wrong, it's just on options the validator will now name and refuse. The errors are specific, which is more than most firmware gives you.

What Is the Upgrade Checklist?

Beyond OTA and Modbus, the release notes flag these, and each one is the kind of thing you only discover at 11 pm:

  • Custom eFuse MAC on ESP32. It's now applied to Ethernet, Bluetooth and 802.15.4, not only Wi-Fi, so those interfaces get new MAC addresses. Update DHCP reservations, firewall rules and Bluetooth pairings before the device vanishes from your network map.
  • UART components with non-default settings now raise config errors rather than being silently accepted.
  • esp32_hosted requires ESP-IDF 5.3 or newer.
  • homeassistant.event lambdas must be tagged !lambda; untagged variables are now treated as values.
  • ESP8266 user-defined actions must keep their metadata under 384 bytes per action.
  • ESP8266 Arduino cores below 3.0.0 are rejected outright.
  • The on-device POSIX TZ string parser is gone, so a hand-written timezone string that worked by accident may not.

Then go to 2026.9.1 rather than stopping at .0. Its thirteen fixes include keeping the OTA encryption key without the API server so safe-mode uploads work, an ESP32-P4 build fix for boards without Wi-Fi, honoring build_flags when generating lv_conf.h for LVGL, and masking a password text entity's value in the web server rather than only its state. The first of those is directly on the migration path above: safe mode is where you end up when something goes wrong mid-update, and .0 could lose the key there.

Where Does It Land in a Home Assistant House?

Home Assistant 2026.10, out on 7 October, added the other half of a story: ESPHome devices can now initiate the connection to Home Assistant themselves, behind an outgoing_connection option on the device, per the 2026.10 release notes. Read the two releases together and the direction is clear. The device talks to the server rather than waiting to be found, the firmware that reaches it is encrypted with the same key, and the chip spends less of its memory proving who it is. None of that changes an automation. All of it changes how much you trust the board you can't reach without a ladder.

What would I actually do here? The heat pump bridge first, on a weekday morning, with the serial cable within reach. It's the one ESPHome device whose silence would cost comfort rather than a sensor reading. Step one with the password still in place, check the log line, step two, check again. Then the rest of the small boards, one at a time, because a board that refuses plaintext and has lost its key is a board you're climbing to. The irrigation controller from our ESP32 irrigation guide would be last; it's in a shed, and the shed has a socket.

If you've never set ESPHome up at all, our ESPHome with Home Assistant primer covers the workflow from a blank YAML, and the broader security posture for the machine on the other end of that encrypted link is in our Home Assistant hardening guide. The network conditions that make Matter and Thread misbehave, covered in our Home Assistant 2026.9 write-up, are the same ones that make an OTA time out, so if an update stalls at the same percentage twice, look at the Wi-Fi before the firmware.

One opinion to end on, and people will disagree. The OTA password was theatre once the image itself was plaintext, and I'd rather a release force a slightly awkward two-step migration than keep offering a lock that only guarded the door and not the room. The two-step is a nuisance for an afternoon. The 2027.3.0 deadline is the part I'd put in a calendar today, because the device that misses it is always the one behind the plasterboard. Which of yours is that?

Frequently Asked Questions

How do I switch an ESPHome device from an OTA password to encryption?

In two installs, and the order is not optional. First, update the device to 2026.9.0 or newer with password still in the config, because the old firmware on the device checks that password until it is replaced. The device log should then say "Encryption: offered, plaintext accepted". Second, replace password with an empty encryption block under the esphome OTA platform and install again. The log should now say "Encryption: required". With no key given, ESPHome reuses the API encryption key, so one key protects both the Home Assistant connection and firmware uploads.

What happens if I remove the OTA password before the first update?

The install fails before anything is written. The documented error is "ESP requests password, but no password given!", because the firmware already on the device still expects a password and the uploader no longer has one to offer. Swapping password for encryption too early fails differently: "the device did not offer encryption; refusing to send the image in plaintext". Neither bricks the device. Put the password back, do the 2026.9.0 install, then remove it.

Is there a deadline for moving to encrypted OTA?

Yes. The release notes say unencrypted updates on older firmware stop working from release 2027.3.0. After that, a device still on pre-2026.9 firmware can no longer be updated over the air through the esphome platform; it needs a serial flash or the web server OTA platform. That gives about six months. Devices that already run 2026.9.0 and have made the switch are unaffected.

Does ESPHome 2026.9.0 break Modbus configurations?

It can, and the changelog marks several modbus_controller changes as breaking. The custom_command option is renamed custom_pdu, address 0 is rejected, skip_updates is retired, and register_count plus force_new_range are replaced by a single reuse_previous_range option. Lambdas that use ModbusCommandItem or queue_command still work but are deprecated with a 2027.3.0 removal date. Validate the config before pressing Install and read the errors; they name the option to change.

Sources & References