fix(docker): vendor drazzy.com board index + seed missing indexes at boot

drazzy.com (ATTinyCore index host) has had an expired TLS certificate
since 2026-06-22 and now 301-redirects http to https, defeating the
plain-http URL pinned to sidestep its TLS issues. Two failure modes:

1. A /root/.arduino15 volume from an older image can reference the index
   in config while lacking the file; arduino-cli then fails instance
   init outright, breaking EVERY compile, not just ATtiny (issue #254).
2. backend/Dockerfile chained update-index with &&, so any uncached
   image build fails hard while the host is broken (exit 1 verified).

A stale index is harmless (ATTinyCore 1.4.1's platform archive and its
micronucleus 2.0a4 both download from github.com); a missing one is
fatal. So: vendor the index under backend/board-indexes/, copy it to
/opt/arduino15-seed in Dockerfile.standalone, and teach entrypoint.sh
to seed any missing package_*.json into /root/.arduino15 at boot,
healing stale volumes. backend/Dockerfile seeds the index directly and
makes update-index best-effort; core install lines stay strict.

Verified: removing the index reproduces the reporter's exact
'Error initializing instance' brick; after seeding, instance init
exits 0 with the host still broken.
This commit is contained in:
David Montero 2026-07-17 06:41:44 +02:00
parent 108d330efd
commit a2df942d74
5 changed files with 7299 additions and 1 deletions

View File

@ -197,6 +197,12 @@ RUN curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/inst
# in the mounted /root/.arduino15 volume. # in the mounted /root/.arduino15 volume.
# ESP32 compilation uses ESP-IDF instead of arduino-cli. # ESP32 compilation uses ESP-IDF instead of arduino-cli.
# Vendored board-manager index seeds (issue #254): entrypoint.sh copies any
# of these missing from /root/.arduino15 at boot, so a flaky index host
# (drazzy.com) or a stale pre-existing volume cannot brick compilation.
# See backend/board-indexes/README.md.
COPY backend/board-indexes/package_*.json /opt/arduino15-seed/
WORKDIR /app WORKDIR /app
# Data directory for persistent SQLite database (mounted as a volume at runtime) # Data directory for persistent SQLite database (mounted as a volume at runtime)

View File

@ -29,10 +29,19 @@ ENV WASI_SDK=/opt/wasi-sdk
# the FQBN clock options we ship (clock=16pll, etc.). We never invoke # the FQBN clock options we ship (clock=16pll, etc.). We never invoke
# micronucleus — it is only required for USB upload, not compilation — # micronucleus — it is only required for USB upload, not compilation —
# but arduino-cli will not install a core whose tool deps cannot fetch. # but arduino-cli will not install a core whose tool deps cannot fetch.
# The drazzy.com index is vendored (board-indexes/README.md) and copied in
# BEFORE update-index: drazzy.com's TLS breaks often enough (issue #254)
# that a hard dependency on it fails image builds for weeks at a time.
# update-index is best-effort — a failed refresh keeps the seeded copy,
# and the strict `core install` lines below still catch a truly broken
# index. ATTinyCore 1.4.1's platform archive and micronucleus tool both
# download from github.com, so the install works from the seed alone.
COPY board-indexes/package_drazzy.com_index.json /root/.arduino15/package_drazzy.com_index.json
RUN arduino-cli config init \ RUN arduino-cli config init \
&& arduino-cli config add board_manager.additional_urls \ && arduino-cli config add board_manager.additional_urls \
http://drazzy.com/package_drazzy.com_index.json \ http://drazzy.com/package_drazzy.com_index.json \
&& arduino-cli core update-index \ && (arduino-cli core update-index \
|| echo "WARNING: some board indexes failed to refresh; using seeded copies") \
&& arduino-cli core install arduino:avr \ && arduino-cli core install arduino:avr \
&& arduino-cli core install ATTinyCore:avr@1.4.1 && arduino-cli core install ATTinyCore:avr@1.4.1

View File

@ -0,0 +1,45 @@
# Vendored board-manager indexes
Snapshot copies of third-party Arduino board-manager indexes whose hosting
has a history of outages breaking builds and fresh deployments.
## Why this exists
`package_drazzy.com_index.json` (Spence Konde's ATTinyCore index) is served
from drazzy.com, which has repeatedly had TLS problems — most recently a
certificate that expired on 2026-06-22 and stayed expired for weeks, while
the host also began 301-redirecting `http://` to `https://`, defeating the
plain-http URL we pin to sidestep exactly this. See issue #254.
Two things go wrong when that host is down:
1. `arduino-cli core update-index` exits non-zero, so any image build that
runs it in a `RUN ... && ...` chain fails hard.
2. Worse, at runtime: if the arduino-cli config references the index URL but
the index *file* was never downloaded, arduino-cli fails instance
initialization outright — which breaks every compile, including boards
that have nothing to do with ATtiny.
A stale index is fine (we pin ATTinyCore 1.4.1, whose platform archive and
micronucleus tool both download from github.com, not drazzy.com/azduino.com).
A missing index is not. So we vendor the index and seed it wherever it could
be missing:
- `Dockerfile.standalone` copies this directory to `/opt/arduino15-seed/`;
`docker/entrypoint.sh` copies any missing `package_*.json` into
`/root/.arduino15/` at boot. This also heals pre-existing named volumes
created by older images (the actual trigger of issue #254).
- `backend/Dockerfile` copies the index into `/root/.arduino15/` before
running a now-tolerant `core update-index`.
## Refreshing the snapshot
When drazzy.com is healthy:
```sh
curl -fL https://drazzy.com/package_drazzy.com_index.json \
-o backend/board-indexes/package_drazzy.com_index.json
```
There is no need to refresh on a schedule — the file only has to be recent
enough to describe the pinned ATTinyCore version.

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,24 @@ if [ ! -f /root/.arduino15/arduino-cli.yaml ]; then
https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json 2>/dev/null || true https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json 2>/dev/null || true
fi fi
# Seed board-manager indexes vendored into the image (issue #254).
# A /root/.arduino15 volume created by an older image can lack an index
# file that the config references; arduino-cli then fails instance init
# outright, which breaks EVERY compile — not just the boards from that
# index. A stale index is harmless, a missing one is fatal, so copy any
# vendored index the volume does not already have. `core update-index`
# below still refreshes whatever is reachable.
if [ -d /opt/arduino15-seed ]; then
for seed in /opt/arduino15-seed/package_*.json; do
[ -f "$seed" ] || continue
dest="/root/.arduino15/$(basename "$seed")"
if [ ! -f "$dest" ]; then
echo "Seeding board index $(basename "$seed") (missing from volume)"
cp "$seed" "$dest"
fi
done
fi
# Install missing cores. # Install missing cores.
# ESP32 core MUST be 2.0.17 (IDF 4.4.x) — newer 3.x is incompatible with QEMU ROM bins. # ESP32 core MUST be 2.0.17 (IDF 4.4.x) — newer 3.x is incompatible with QEMU ROM bins.
arduino-cli core update-index 2>/dev/null || true arduino-cli core update-index 2>/dev/null || true