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.
STM32 Blue/Black Pill sketches failed to compile with "Platform
'STMicroelectronics:stm32' not found" because the arduino-cli STM32 core
and its board-manager URL were never set up. Add the stm32duino board
manager URL (first-run block) and `core install STMicroelectronics:stm32`
alongside the other cores so a fresh arduino-libs volume can compile STM32.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
ATTinyCore >=1.5.0 declares ATTinyCore:micronucleus@2.5-azd1b as a tool
dependency, hosted at https://azduino.com/bin/micronucleus/. That host
has been unreachable (connection refused) for extended periods, causing
every ATtiny85 compile to fail at the core-install step with:
Download failed: performing HEAD request: ... dial tcp ...: connection refused
Failed to install required core: ATTinyCore:avr
micronucleus is only used for USB upload — never for compilation — but
arduino-cli refuses to install a core whose tool deps cannot fetch.
Pin to 1.4.1, the last release whose micronucleus binary is hosted on
github.com (digistump release, reachable). The FQBN clock options we
ship (clock=16pll on attinyx5, etc.) are unchanged across 1.4.x.
- backend/app/services/arduino_cli.py: new CORE_INSTALL_VERSIONS map
consulted by ensure_core_for_board so the runtime auto-install
passes "ATTinyCore:avr@1.4.1" instead of unversioned latest.
- backend/Dockerfile and docker/entrypoint.sh: same pin so a fresh
image bakes 1.4.1 in and never hits the runtime fallback path.
Existing regression tests in test/backend/unit/test_arduino_cli_attinycore.py
still pass (they assert presence, not version).
Browsers were reporting:
Unsafe attempt to load URL http://velxio.dev/examples/
from frame with URL https://velxio.dev/examples.
Repro:
curl -I https://velxio.dev/examples
→ 301 Location: http://velxio.dev/examples/ ← protocol downgraded
Why: docker/nginx.conf has the container listening on `:80` only — TLS
is terminated by the host nginx in front of it (which then proxies to
http://127.0.0.1:3080). When nginx generates a trailing-slash 301 it
uses the listening protocol (http) for the absolute Location header,
not the X-Forwarded-Proto. The browser correctly blocks the redirect.
Fix: `absolute_redirect off;` makes nginx emit relative Location
headers (`Location: /examples/`), so the browser resolves them
against the original request URL and HTTPS is preserved end-to-end.
After fix:
curl -I https://velxio.dev/examples
→ 301 Location: /examples/
Goes in the same branch as the BMP280 ninja-timeout fix because both
are deploy-blocking and small.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Cold ESP-IDF compiles (esp32, esp32-cam, etc.) can legitimately take
5–10 minutes — first time the project is built, ninja has to compile
the entire IDF + Arduino-ESP32 component graph from scratch. Nginx was
cutting the connection at 5 min, which surfaced as 'No response from
server' in the frontend even though the build was still progressing.
Worse, since the backend doesn't cancel the compile on client
disconnect, repeated user clicks pile up parallel ninja jobs that
saturate CPU and slow every concurrent build further.
10 min covers cold builds with comfortable margin. Long-term we should
make compile a job (POST → job_id, GET status) and cancel duplicates
server-side, but the timeout bump unblocks users today.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The folder only holds the in-container nginx + entrypoint that the
standalone Dockerfile copies. Calling it "deploy" implied host-level
production glue, which now lives in github.com/velxio/velxio-prod.
"docker/" makes the build-time vs deploy-time split obvious.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>