Gate 0.1.0: eigen image, het command-blok is een script, de app-map is leeg

Plan Eigenimage, fase 1 tot en met 3. De vier templates verhuizen naar
tools/electrum-gate/ zonder extensie; daarnaast Dockerfile (nginx:1.30-alpine
plus python3), entrypoint.sh (het command-blok van de compose, zonder $$) en
build.sh naar het voorbeeld van Evolu Relay. Een image voor beide containers,
gebouwd op de Umbrel; open punt 2 en 3 daarmee beslist.

Inhoudelijk anders dan alleen verplaatst: het log_format staat in stream.conf
zelf, het backend-adres komt via twee plaatshouders zonder dollarteken uit de
omgeving (ook in de server-service), en de pagina haalt versie en adres uit
status.json via GATE_APP_VERSION.

Tests mee verhuisd en uitgebreid: entrypoint.sh en Dockerfile in plaats van het
command-blok, en de tag in de compose gelijk aan VERSION in build.sh voor elke
eigen image. Mutatie-getest met drie ingrepen.

Nog niet gebouwd: er is hier geen Docker. De tag staat ongepind tot de eerste
push; dat is fase 4 en die is van de gebruiker.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Harmen
2026-09-07 20:20:42 +02:00
co-authored by Claude Fable 5.1
parent 7b3804df89
commit 973b24a23f
25 changed files with 981 additions and 410 deletions
+67 -41
View File
@@ -18,65 +18,91 @@
## Volgende stap
> **Dit plan ligt stil op verzoek van de gebruiker (27-08-2026): hij gaat eerst verder met Evolu Relay,
> zie het plan Umbrelapp.** Dat is een volgordekeuze en geen blokkade; er is aan dit plan nog niets
> gebouwd, dus er ligt ook niets half af. Beginnen kan met fase 1, en het antwoord dat daarvoor nodig was
> staat er.
> **Opgepakt op 07-09-2026 op verzoek van de gebruiker.** Fase 1 tot en met 3 zijn in één sessie gedaan
> en gecommit als Electrum Gate 0.1.0, ongebouwd. **Wat nu volgt is van de gebruiker en kan alleen op de
> Umbrel**, want daar staat Docker:
>
> 1. `sh tools/electrum-gate/build.sh`, dan `docker login` en `docker push` zoals het script afdrukt;
> 2. de digest uit de push-uitvoer achter de tag in de compose, **twee keer** (agent en server);
> 3. committen en pushen, dan de app in umbrelOS updaten;
> 4. de vijf controles van fase 4 hieronder.
>
> Dit is de eerste keer dat deze image gebouwd wordt, dus reken op minstens één ronde: een `apk add` die
> anders uitpakt dan gedacht, of een pad dat de Dockerfile wél kent en de container niet. De tests
> hierboven toetsen de tekst van het recept, niet het resultaat.
- [x] **Fase 1 tot en met 3 gedaan (07-09-2026), als 0.1.0.** De vier `*.template`-bestanden staan nu in
`tools/electrum-gate/` zonder de extensie, plus `Dockerfile`, `build.sh` en `entrypoint.sh`. De
compose gebruikt één image voor beide containers, ongepind tot de eerste push. Tests aangepast en
mutatie-getest; details in [PROGRESS.md](PROGRESS.md)
- [ ] **Fase 4: bouwen, duwen, pinnen, installeren, nakijken.** Van de gebruiker; zie hierboven
- [x] **Open punt 1 beantwoord (27-08-2026): voor nu Gitea, bij inlevering opnieuw kijken.** Daarmee is de
enige vraag weg die vóór het bouwen beantwoord moest zijn. Zie [OPEN.md](OPEN.md)
- [ ] **Fase 1 beginnen: het bouwrecept in `tools/electrum-gate/`.** Open punt 2 en 3 horen bij die start
en niet ervoor: één image of twee, en op welke machine er gebouwd wordt. Dat laatste is de enige die
de gebruiker moet beantwoorden, en pas op het moment dat het recept er is en gedraaid moet worden
## Fase 1 - Het bouwrecept
- [ ] Beslissen: één image of twee (open punt 2). [PLAN.md](PLAN.md) §6 stelt één voor
- [ ] Beslissen: waar wordt gebouwd (open punt 3). De Umbrel is amd64 en een productiemachine
- [ ] `tools/electrum-gate/Dockerfile` schrijven: basisimage, `agent.py`, de nginx-configuratie, de pagina,
en een `entrypoint.sh`. **Niet in de app-map**: een `Dockerfile` staat niet in de update-whitelist,
dus bouwen-in-de-app kost bij elke versie een deïnstallatie
- [ ] `tools/electrum-gate/build.sh` naar het voorbeeld van `tools/evolu-relay/build.sh`: pin op de
basisimage, bouwen, naar het register duwen, en de digest afdrukken die in de compose moet
- [ ] **Multi-arch bouwen, en dat is nieuw werk.** `linux/amd64` én `linux/arm64` in de manifest-lijst.
Vraagt `buildx` met QEMU en is hier nog nooit geprobeerd; zie [PLAN.md](PLAN.md) §4
- [x] Beslissen: één image of twee (open punt 2). **Eén**, zoals [PLAN.md](PLAN.md) §6 voorstelt; beslist
07-09-2026, zie [OPEN.md](OPEN.md)
- [x] Beslissen: waar wordt gebouwd (open punt 3). **Op de Umbrel**, want dat is de enige machine met
Docker; de werkplek heeft het niet. Zie [OPEN.md](OPEN.md)
- [x] `tools/electrum-gate/Dockerfile`: `nginx:1.30-alpine` plus `python3` uit apk, de vijf bestanden
erin, `ENTRYPOINT []` zodat het envsubst-script van de nginx-image niet meedraait. De bouwcontext is
de repo-root, want `icon.png` blijft in de app-map (het manifest wijst ernaar) en wordt van daar
gekopieerd; `.dockerignore` in de root houdt de context klein
- [x] `tools/electrum-gate/build.sh` naar het voorbeeld van Evolu Relay: `VERSION`, controles vooraf
(ontbrekende bestanden, een `${` die niemand meer invult), bouwen, en de vervolgstappen afdrukken
- [ ] **Multi-arch bouwen, en dat is nieuw werk.** `build.sh` heeft er een schakelaar voor:
`PLATFORMS="linux/amd64,linux/arm64"` bouwt met `buildx` en duwt meteen. Nog nooit geprobeerd, en
niet nodig voor eigen gebruik op een amd64-Umbrel. Hoort bij **Publicatie-Gate**; zie
[PLAN.md](PLAN.md) §4
- [ ] **Controleren dat de image anoniem te halen is.** umbreld krijgt geen inloggegevens mee. Uitloggen in
dezelfde context waarin je inlogde, anders meet je je eigen sessie. Het commando staat onderaan
`tools/evolu-relay/build.sh`
dezelfde context waarin je inlogde, anders meet je je eigen sessie. Het commando drukt `build.sh` af.
**Eigenaar: gebruiker**, bij fase 4
## Fase 2 - Het `command`-blok wordt een script
- [ ] Het inline `command`-blok uit `docker-compose.yml` omzetten naar `entrypoint.sh` in de image. Dat is
ruim honderd regels shell in een YAML-string met een eigen ontsnappingsregel voor het dollarteken;
zie [PLAN.md](PLAN.md) §2. **Dit is de grootste inhoudelijke winst van het hele plan**
- [ ] Let op wat daarbij niet mag sneuvelen: het `log_format` met `$$`, de sessieteller uit
`/proc/net/tcp`, de herlaadlus met zijn vangnettak, en het feit dat nginx met `exec` het hoofdproces
wordt. Die laatste is geen detail: andersom blijft de shell PID 1, geeft signalen niet door, en ziet
Docker een geslaagde afsluiting als nginx omvalt
- [x] `tools/electrum-gate/entrypoint.sh`, uit het `command`-blok van de compose. Zelfde gedrag, geen
`$$` meer, en het `log_format` staat nu gewoon in `stream.conf` in plaats van in een los bestand dat
het script wegschreef. Nieuw erin: het invullen van het backend-adres in het stream-blok (zie fase 3)
- [x] Wat niet mocht sneuvelen en er staat: de sessieteller uit `/proc/net/tcp`, de herlaadlus met zijn
vangnettak, en `exec nginx` als laatste regel. Alle drie met een toets in
`test_server_start_zonder_certificaat.py`, en die zijn gezien te falen
## Fase 3 - De app-map opschonen
- [ ] `agent.py.template`, `nginx.conf.template`, `stream.conf.template` en `index.html.template` uit de
app-map halen zodra ze in de image zitten
- [ ] **`index.html` heeft dan geen template-invulling meer.** Vandaag staat er
`${APP_ELECTRS_NODE_IP}:${APP_ELECTRS_NODE_PORT}` in, ingevuld door umbreld bij het starten. Zit de
pagina in de image, dan moet dat adres langs de omgeving naar binnen, bijvoorbeeld doordat de agent
het in `status.json` zet en de pagina het daaruit leest. Dat is werk dat nu nog gratis is
- [ ] De compose houdt zijn `environment`-blok; dat is hoe `${APP_ELECTRS_NODE_IP}` binnenkomt, en die weg
is op 27-08-2026 bewezen bij de omschakeling naar Fulcrum
- [ ] Wat er in de app-map overblijft: `docker-compose.yml`, `umbrel-app.yml`, `icon.png` en `data/` met
zijn twee `.gitkeep`-bestanden
- [x] De vier templates uit de app-map, met `git mv` naar `tools/electrum-gate/` zonder `.template`
- [x] **`index.html` heeft geen template-invulling meer.** `${APP_VERSION}` en het backend-adres komen uit
`status.json`: de agent krijgt `GATE_APP_VERSION: ${APP_VERSION}` uit de compose en zet `version` in
de status; het adres stond er al als `backend.address`
- [x] **`stream.conf` heeft geen template-invulling meer.** Twee plaatshouders zonder dollarteken,
`__GATE_ELECTRUM_HOST__` en `__GATE_ELECTRUM_PORT__`, die `entrypoint.sh` uit de omgeving invult;
de server-service krijgt daarvoor dezelfde twee variabelen als de agent
- [x] De compose houdt zijn `environment`-blok; de mounts van de vijf losse bestanden zijn eruit
- [x] Wat er in de app-map overblijft: `docker-compose.yml`, `umbrel-app.yml`, `icon.png` en `data/` met
zijn twee `.gitkeep`-bestanden. Precies wat [PLAN.md](PLAN.md) §6 zei
- [x] De tests mee verhuisd: `test_agent_certificates.py` laadt `tools/electrum-gate/agent.py`;
`test_server_start_zonder_certificaat.py` toetst `entrypoint.sh` en de Dockerfile in plaats van het
`command`-blok, plus dat de tag in de compose `VERSION` uit `build.sh` is; `test_appstore_vorm.py`
leest ook de nginx-config onder `tools/` en toetst tag gelijk aan `VERSION` voor élke eigen image;
`test_paginas_parsen.mjs` en `tools/voorbeeldpagina.mjs` vinden een pagina op beide plekken
## Fase 4 - Uitrollen en verifiëren
- [ ] Image gepind als `repo:tag@sha256:<digest>` in de compose, en `version` verhoogd in het manifest.
Zonder die verhoging rolt umbrelOS niets uit
- [ ] Image gepind als `repo:tag@sha256:<digest>` in de compose (twee keer), en `version` verhoogd in het
manifest. Dat laatste staat al op 0.1.0
- [ ] Op de Umbrel installeren en controleren dat alles het nog doet: de pagina, de certificaatkeuze, de
TLS-poort, de zelfcontrole en het activiteitenlog
- [ ] **`icon.png` wordt hiermee updatebaar**, want die zit dan in de image. Dat was de enige echte
uitzondering op "alles komt al aan bij een update"; zie [PLAN.md](PLAN.md) §1
- [ ] **De versie in de kop van de pagina**, want die loopt nu via `status.json` en niet meer via umbreld
- [ ] **`icon.png` is hiermee updatebaar**, want die zit in de image. Dat was de enige echte uitzondering
op "alles komt al aan bij een update"; zie [PLAN.md](PLAN.md) §1
## Daarna - Evolu Relay
- [ ] **Hetzelfde voor de agent en de pagina van Evolu Relay**, die nog als `*.template` op
`python:3-alpine` en `nginx:alpine` draaien; zie [PLAN.md](PLAN.md) §8. Pas na fase 4 hierboven:
eerst zien dat de weg werkt voordat de tweede app hem gaat
## Geblokkeerd / wacht op
Niets, behalve open punt 1 hierboven, en dat is een vraag van één regel aan de gebruiker.
Fase 4 wacht op de gebruiker: bouwen kan alleen op de Umbrel.