1
0
Fork 0
mirror of https://github.com/imjasonh/esp32 synced 2026-07-06 23:52:24 +00:00
No description
Find a file
Jason Hall 0ebc860e6f README: refresh to reflect operational OTA, add CI badges
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 14:53:44 -04:00
.cargo initial commit 2026-05-02 11:43:41 -04:00
.github Add Dependabot config: weekly grouped updates for GHA + Cargo deps 2026-05-02 14:41:15 -04:00
src Auto-publish from GHA on push to main; sign by immutable digest 2026-05-02 13:58:44 -04:00
tools/publisher publisher: use hex::encode for SHA digests (sha2 0.11 dropped LowerHex) 2026-05-02 14:47:32 -04:00
trust Add cosign signature verification (OTA phase 4a) 2026-05-02 13:50:03 -04:00
.gitignore Add CI workflow, bump GHA actions, refresh + commit Cargo.lock 2026-05-02 14:16:55 -04:00
build.rs Add device-side OTA loop (OTA phase 2) 2026-05-02 12:53:19 -04:00
Cargo.lock Add CI workflow, bump GHA actions, refresh + commit Cargo.lock 2026-05-02 14:16:55 -04:00
Cargo.toml Add cosign signature verification (OTA phase 4a) 2026-05-02 13:50:03 -04:00
eink-plan.md initial commit 2026-05-02 11:43:41 -04:00
LICENSE Initial commit 2026-05-02 11:43:06 -04:00
Makefile Makefile: nuke stale python-shim symlinks before recreating 2026-05-02 14:50:41 -04:00
notes.txt Switch to OTA partition layout and document Wi-Fi + HTTPS demo 2026-05-02 12:14:21 -04:00
ota-plan.md Mark phase 4a done in ota-plan.md 2026-05-02 13:50:49 -04:00
partitions.csv Add cosign signature verification (OTA phase 4a) 2026-05-02 13:50:03 -04:00
README.md README: refresh to reflect operational OTA, add CI badges 2026-05-02 14:53:44 -04:00
rust-toolchain.toml initial commit 2026-05-02 11:43:41 -04:00
sdkconfig.defaults.in Add device-side OTA loop (OTA phase 2) 2026-05-02 12:53:19 -04:00

ESP32 Rust

CI Publish OTA

Std Rust on an Inland ESP-WROOM-32 dev board with end-to-end OTA over GHCR + cosign keyless signing. E-ink display work coming next (see eink-plan.md).

What it does today

  • Connects to Wi-Fi, fetches public IP and weather over HTTPS.
  • Polls ghcr.io/imjasonh/esp32:latest every ~60s for new firmware.
  • For each new digest, fetches the cosign Sigstore Bundle, verifies the signature, the cert chain to the bundled Sigstore root, and that the signer's identity matches the compile-time allowlist in src/trust.rs.
  • On verify-pass, streams the layer to the inactive OTA partition, reboots, and only marks the new image valid after Wi-Fi + registry bringup checks pass. Any post-OTA failure auto-rolls back via the bootloader.

Push to main → CI builds → publish workflow pushes a signed image to GHCR → device picks it up on its next poll. See ota-plan.md for the full design.

Hardware

  • Board: Inland ESP-WROOM-32 (Micro Center SKU 027466). Connects as /dev/cu.usbserial-0001 on macOS via the onboard CP210x USB-UART.
  • No user LED on this variant — only a power LED. Watch logs via make monitor.

Prerequisites (one-time, macOS)

cargo install espup espflash ldproxy
brew install cmake ninja dfu-util cosign
espup install --targets esp32
curl -LsSf https://astral.sh/uv/install.sh | sh   # if you don't have uv

First flash (USB)

make wifi.env             # creates wifi.env from template
$EDITOR wifi.env          # fill in WIFI_SSID and WIFI_PASS
make flash-all run        # full erase + bootloader + partition + app, then monitor

The first build clones ESP-IDF v5.2.2 into .embuild/ (510 min). Subsequent builds are fast.

Day-to-day

make build      Compile (requires wifi.env)
make flash      Build + flash app (use flash-all after partitions change)
make monitor    Open serial monitor; Ctrl+C to exit
make run        Build + flash + monitor
make publish    Build, push OCI artifact to ghcr.io/imjasonh/esp32, cosign sign
make clean      cargo clean

make publish requires gh.env (see ota-plan.md for PAT setup) and a real cosign OIDC flow the first time per ~10min window — a browser pops to authenticate. CI does this automatically via the GitHub Actions workflow's ambient OIDC token.

Project layout

src/main.rs            firmware entrypoint, Wi-Fi + HTTPS + OTA loop
src/ota.rs             OTA polling, manifest fetch, blob streaming
src/sig.rs             cosign Sigstore Bundle verification
src/trust.rs           compile-time allowlist of signer identities
trust/                 bundled Sigstore Fulcio root + intermediate certs
tools/publisher/       host-side Rust tool that pushes signed OCI artifacts
.github/workflows/     ci.yml (PRs) + publish.yml (push to main)
Cargo.toml             firmware deps
partitions.csv         OTA-capable partition table (1.75 MB app slots)
sdkconfig.defaults.in  ESP-IDF kconfig (Makefile substitutes paths)
Makefile               build / flash / monitor / publish entrypoints
wifi.env.example       template for compile-time Wi-Fi creds
eink-plan.md           planned e-ink display work
ota-plan.md            full OTA design + per-phase status
notes.txt              internal design notes and setup gotchas