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
+14 -8
View File
@@ -12,17 +12,23 @@
## Nog te beslissen
2. **Eén image of twee?** [PLAN.md](PLAN.md) §6 stelt één voor: de agent en nginx blijven twee containers,
maar ze delen één image. Twee images is netter gescheiden en verdubbelt het bouwwerk en het pinwerk.
**Moment:** bij de start van het werk · **Eigenaar:** sessie, met de gebruiker mee
3. **Waar wordt gebouwd?** Op de Umbrel staat Docker, maar dat is een productiemachine en hij is amd64,
terwijl arm64 ook een eis is. Bouwen op de werkplek van de gebruiker vraagt daar Docker. Dit hangt samen
met de multi-arch-stap uit §4 van het plan, die nog nooit geprobeerd is.
**Moment:** bij de start van het werk · **Eigenaar:** gebruiker
Niets.
## Beslist
2. **Eén image of twee?** - **Eén** (07-09-2026, sessie, volgens het voorstel in [PLAN.md](PLAN.md) §6).
De agent en nginx blijven twee containers met dezelfde image; de compose geeft de agent een eigen
`command`. Basis is `nginx:1.30-alpine` met `python3` uit apk, en niet andersom: de officiële
nginx-image heeft de stream-module ingebouwd, bij alpine's eigen nginx is dat een los pakket.
**Moment:** afgerond · **Eigenaar:**
3. **Waar wordt gebouwd?** - **Op de Umbrel** (07-09-2026), om een eenvoudige reden: het is de enige
machine met Docker; de werkplek heeft het niet. Dat het een productiemachine is weegt minder dan dat
het de plek is waar Evolu Relay ook al gebouwd wordt. Gevolg: één architectuur, amd64, en dat is voor
eigen gebruik genoeg. Multi-arch zit in `build.sh` als schakelaar (`PLATFORMS=...`) en is werk voor
**Publicatie-Gate**; het is nog nooit geprobeerd.
**Moment:** afgerond · **Eigenaar:**
1. **Blijft het Gitea-register ook bij publicatie de bron?** - **Voor nu Gitea, bij inlevering opnieuw
kijken** (27-08-2026, gebruiker).
@@ -3,6 +3,25 @@
> Chronologisch sessielog, nieuwste bovenaan. Kort: 3 tot 6 regels per entry. Wat er is gebeurd en
> waarom, niet wat er nog moet: dat staat in [TAKEN.md](TAKEN.md).
## 07-09-2026 - fase 1 tot en met 3 in één sessie: het recept staat, de app-map is leeg
Op verzoek van de gebruiker opgepakt, direct na Relay 0.5.6. De vier templates zijn met `git mv` naar
`tools/electrum-gate/` verhuisd en heten daar gewoon `agent.py`, `nginx.conf`, `stream.conf` en
`index.html`. Daarnaast nieuw: `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. Open punt 2
en 3 zijn beslist: één image, gebouwd op de Umbrel.
Wat er inhoudelijk veranderde en niet alleen verhuisde: het `log_format` staat nu in `stream.conf` zelf,
het backend-adres komt via twee plaatshouders zonder dollarteken uit de omgeving (ook de server-service
krijgt ze nu), en de pagina haalt versie en adres uit `status.json`, waarvoor de agent `GATE_APP_VERSION`
doorgeeft. De compose is voor het eerst sinds 0.0.3 zonder shellblok.
Tests: alle zes groen, niets overgeslagen. Drie mutaties (het `exec` voor nginx weg, `ENTRYPOINT []` weg,
één tag in de compose verhoogd) lieten precies de bedoelde toetsen omvallen, ook de nieuwe in
`test_appstore_vorm.py`. **Niet geverifieerd: de image zelf.** Er is hier geen Docker, dus of `apk add
python3` het gedraagt zoals gedacht en of de container start, blijkt pas bij fase 4 op de Umbrel.
Electrum Gate staat op 0.1.0 in het manifest, met de tag ongepind tot de eerste push.
## 27-08-2026 - het register is beslist, en daarna ging de aandacht naar Evolu Relay
Open punt 1 beantwoord: **voor nu Gitea, bij inlevering opnieuw kijken.** De twee bezwaren die dat punt
+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.