fix(esphome): bind the remote-build peer-link to loopback; finish the rsync fix
ha-dev asked for the Device Builder 1.0.0 remote-build receiver to be turned off: one instance, builds run locally, so the feature has no role, and it was binding 0.0.0.0:6055 with mDNS advertisement on a privileged host-network container that writes firmware to devices. Reading the source first changed the framing. controllers/remote_build/ _state.py declares 'remote_builds_enabled: bool = True', so nobody enabled it — it arrived on by default with the rewrite. And the flag has no on-disk representation until it is changed: neither .device-builder.json nor .device-builder-preferences.json carries it, and the only writer is the app's own command API behind the UI. Setting it from a playbook would mean inventing a schema for a model I have not read. So this binds ESPHOME_REMOTE_BUILD_HOST=127.0.0.1 — a documented env var, no entrypoint override — which removes the LAN reachability now and is verifiable (ss reports 127.0.0.1:6055, was 0.0.0.0:6055). It is explicitly NOT the off switch ha-dev asked for and the compose comment says so; the Settings toggle is one UI click and the line can go once someone flips it. Also completes yesterday's deploy-stack.sh fix, which was half a fix. --no-o --no-g stopped rsync chgrp-ing a root:docker destination as a non-root identity, but the very next deploy failed the same way one layer along — 'failed to set times on ...' — because a non-root identity cannot utime() a root-owned directory either. Same exit 23 after a successful transfer. Added --omit-dir-times. Fixing only the group half looked fixed until the next run, which is the whole reason this is worth a line in the script's comment.
This commit is contained in:
@@ -163,13 +163,17 @@ for entry in "${PAIRS[@]}"; do
|
||||
|
||||
tmp_out=$(mktemp) tmp_err=$(mktemp)
|
||||
rc=0
|
||||
# --no-o --no-g: the deploy tree is root:docker 2775 (setgid) since the
|
||||
# --no-o --no-g --omit-dir-times: the deploy tree is root:docker 2775 (setgid) since the
|
||||
# 2026-09-14 fleet normalisation, and plain -a makes rsync try to chgrp the
|
||||
# destination as the deploy identity, which is not root. It fails with
|
||||
# "chgrp ... Operation not permitted" and exits 23 AFTER transferring the
|
||||
# content — a loud error on a deploy that actually succeeded. The setgid bit
|
||||
# already assigns the right group, so rsync should not be fighting it.
|
||||
rsync -az --no-o --no-g --delete --dry-run \
|
||||
# --omit-dir-times is the same problem one layer along: a non-root identity
|
||||
# cannot utime() a root-owned directory either, which produced the identical
|
||||
# "exit 23 after a successful transfer" on the next deploy. Both halves are
|
||||
# needed; fixing only the group half looks fixed until the next run.
|
||||
rsync -az --no-o --no-g --omit-dir-times --delete --dry-run \
|
||||
"${RSYNC_REMOTE[@]}" \
|
||||
--out-format='%i %n' \
|
||||
"${EXCLUDES[@]}" "${extra[@]}" \
|
||||
@@ -291,7 +295,7 @@ for entry in "${PAIRS[@]}"; do
|
||||
extra=()
|
||||
[ "$kind" = compose ] && extra+=(--exclude='conf/')
|
||||
printf 'pushing %s → %s\n' "$src" "$dest"
|
||||
rsync -az --no-o --no-g --delete \
|
||||
rsync -az --no-o --no-g --omit-dir-times --delete \
|
||||
"${RSYNC_REMOTE[@]}" \
|
||||
"${EXCLUDES[@]}" "${extra[@]}" \
|
||||
"$src" "$dest"
|
||||
|
||||
@@ -39,6 +39,23 @@ services:
|
||||
# the 2025.8.2 -> 2026.8.2 upgrade, 2026-09-14.
|
||||
- ESPHOME_USERNAME=${ESPHOME_USERNAME}
|
||||
- ESPHOME_PASSWORD=${ESPHOME_PASSWORD}
|
||||
#
|
||||
# Device Builder 1.0.0 added a remote-build peer-link receiver that binds
|
||||
# 0.0.0.0:6055 and advertises itself over mDNS as _esphomebuilder._tcp.
|
||||
# It is ON BY DEFAULT — controllers/remote_build/_state.py declares
|
||||
# `remote_builds_enabled: bool = True` — so nobody enabled it; it arrived
|
||||
# with the rewrite. There is exactly one Device Builder here and builds
|
||||
# run locally in this container, so the feature has no role: it is
|
||||
# unrequested LAN reachability on a privileged host-network container
|
||||
# whose job is writing firmware to devices.
|
||||
#
|
||||
# ⚠ This binds it to loopback; it does NOT disable it. The real off
|
||||
# switch is a Settings toggle in the UI, and its enabled flag has no
|
||||
# on-disk representation until it is changed, so there is nothing to set
|
||||
# from a playbook without inventing a schema. Flip it in Settings and
|
||||
# this line can go. (ha-dev's stated preference, correctly, is not
|
||||
# enabling a feature over restricting its bind address.)
|
||||
- ESPHOME_REMOTE_BUILD_HOST=127.0.0.1
|
||||
labels:
|
||||
- homepage.group=Apps
|
||||
- homepage.name=ESPHome
|
||||
|
||||
Reference in New Issue
Block a user