Wi-Fi and Secrets
Scope: how a device with no screen and no keyboard joins a password-protected network, what it does when it can't, and where the passwords live in the meantime. The arrangement is genuinely clever and genuinely imperfect; this chapter says both, plainly.
The joining problem
A laptop asks you for the Wi-Fi password. A chip sealed in a greenhouse can't. So the password has to be in the firmware — compiled in, from the configuration, at build time. ESPHome's Wi-Fi section is therefore both a network setting and a custody arrangement for a secret:
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: "Greenhouse Fallback"
password: !secret ota_password
On boot the device joins the named
network and takes a DHCP address, and is
thereafter reachable by its mDNS name —
greenhouse.local — without anyone
recording the address. (A manual_ip:
block exists for readers who pin addresses;
the guide's specimen lets DHCP and mDNS
do their jobs.)
The fallback: a device that asks for help
The ap: block is the plan for failure.
If the device cannot join — wrong password,
router down, greenhouse moved out of range
of the network it remembers — it does not
sit in the dark. After a timeout it starts
its own little network, the fallback
hotspot ("Greenhouse Fallback" above), and
the captive_portal: component named back
in chapter 3 serves a page on it: connect
your phone to the hotspot, and the page
lets you hand the device new Wi-Fi
credentials, which it keeps and retries
with. This is the same trick every smart
plug uses on its first day, and it doubles
as the rescue path for the much commoner
accident: you changed the home Wi-Fi
password, and every device you own is now
stranded. The fallback password is a
secret too, and the specimen deliberately
reuses the OTA password for it — one fewer
password to invent, and a choice the file
makes visibly rather than by accident.
Honest limits of the rescue: it needs the device within radio reach of a person with a phone, and it needs the device running — a fallback hotspot does not fix a device whose configuration is broken (that is safe mode's job, chapter 7, and ultimately the USB cable's).
Secrets: the bargain
The !secret tag is a YAML-level promise:
this value lives somewhere else. At
validation and build time ESPHome looks
each name up in secrets.yaml, a file
beside the configuration:
# secrets.yaml — yours will differ in every value
wifi_ssid: "Marigold Cottage WiFi"
wifi_password: "correct-horse-battery-staple-42"
api_key: "..."
ota_password: "hummingbird-ota-1234"
(The values above are invented for a
fictional household and protect nothing;
examples/secrets.yaml.example is the
template with the key-generating command
in a comment. The lab's real secrets file
was never copied into this repository —
and, as chapter 3 noted, esphome config
echoes secrets back as !secret
references, so even the validation
transcript carries none of them.)
What the bargain buys:
- The configuration becomes shareable. You can post your greenhouse.yaml in a forum, commit it to a public repository, or print it in a guide, and it contains no password to steal. The interesting part of a configuration — the design — travels; the credentials don't.
- One file to guard, one file to rotate. Change the Wi-Fi password and you edit one line in one place; every device built from that folder follows at its next build.
And what it does not buy, stated plainly:
secrets.yamlis plaintext. It is a filing system, not a safe. Anyone who can read the file has the passwords; ESPHome offers no encryption for it. Treat the folder like a key drawer.- The secret still ends up in the firmware. It has to — the device must know the password to use it. Someone with the physical chip and determination can extract firmware; for home devices the realistic defence is that the password they would win is your Wi-Fi's, which is one more reason the fallback and OTA passwords should not be the password to anything else you value.
- The lookup is by folder. Move a
configuration without its
secrets.yamland validation fails on the spot, naming the missing file (Error reading file .../secrets.yaml: No such file or directory, transcript t11) — an alarming error the first time, and the correct behaviour every time.
A closing discipline worth adopting
verbatim: secrets.yaml goes in
.gitignore before the folder's first
commit. ESPHome's own tooling assumes the
habit; the guides in this series state it
because habits stated are habits kept.