Eigenimage afgerond en gearchiveerd: beide apps op een eigen image

Relay 0.6.0 draait en synct; de gebruiker haalde de achtergebleven
programmabestanden met de hand uit de app-datamap. Het plan verhuist naar
Docs/Plannen/Archief/Eigenimage/, de eerste in die map. CONTINUE_HERE krijgt
een archiefsectie; Publicatie-Relay wacht niet meer op een te pinnen image,
en in Publicatie-Gate en Images-pinnen.md is het pinnen van vreemde images
geschiedenis. Wat er voor publicatie nog ontbreekt is linux/arm64.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Harmen
2026-09-08 17:08:47 +02:00
co-authored by Claude Fable 5.1
parent 4d859c2727
commit fa0aa6c8d8
9 changed files with 53 additions and 31 deletions
+54
View File
@@ -0,0 +1,54 @@
# Open punten - Eigenimage
> Beslissingen die nog een **eigenaar** of een **moment** nodig hebben. Staat een punt hier zonder
> allebei, dan is dat de eerste fout om op te lossen. Wordt een punt een taak, dan verhuist het naar
> [TAKEN.md](TAKEN.md).
>
> **Nummers blijven staan**, ook als een punt beslist is: er kan elders naar verwezen worden, ook vanuit
> codecommentaar. Beslissen betekent verplaatsen naar de kop hieronder, niet hernummeren.
>
> Deze drie punten stonden als §7 in het masterplan en zijn bij de promotie op 27-08-2026 hierheen
> verhuisd.
## Nog te beslissen
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).
De twee bezwaren die dit punt opriep gelden allebei pas bij inlevering, en dat is niet aan de orde: "dit
is echt mijn eigen app voor eigen gebruik, ik ben nog niet toe aan publiceren." Het domein van de
gebruiker staat dan in een pakket dat niemand aangeboden krijgt, en de enige die een image van zijn
thuisserver haalt is hij zelf. Daarmee vervallen ze niet, ze zijn alleen nog niet actueel.
**Wat dat voor dit plan betekent:** `build.sh` duwt naar `sc.kamenier-hamer.nl/sysop/...`, net als bij
Evolu Relay, en de compose pint op een digest daaruit. Het bouwrecept hoeft er niet omheen ontworpen te
worden dat het register later kan wisselen; een register wisselen is één regel in `build.sh` en één in
de compose, plus een versieverhoging.
**Wat er wél voor terugkomt is een taak in Publicatie-Gate en niet hier.** Bij inlevering moet het
register opnieuw beoordeeld worden, samen met het kaal maken van het app-id en het pinnen; dat zijn
toch al drie dingen die een herinstallatie vragen en die je één keer wilt doen. De gebruiker noemde er
nog iets bij dat de moeite van het uitzoeken waard is voordat het zover is: **umbrelOS zou een eigen
register toestaan.** Dat is niet nagetrokken, en het is precies het soort aanname dat je niet wilt
ontdekken op het moment van inleveren.
De spec zoals we hem kennen eist alleen `registry/repo:versie-of-commit@sha256:<digest>` met beide
architecturen erin, en zegt niets over wélk register. Naar de letter mag Gitea dus ook dan.
**Moment:** afgerond voor dit plan; het vervolg hoort bij **Publicatie-Gate** · **Eigenaar:**
+179
View File
@@ -0,0 +1,179 @@
# Eigenimage - plan
> **App: Electrum Gate**, met een korte paragraaf over wat het voor Evolu Relay betekent (§8). Voorgesteld
> door de gebruiker op 27-08-2026: van de uitvoerbare bestanden die nu in de app-map staan een image maken
> en die in het eigen Gitea-register zetten.
>
> **Gepromoveerd van masterplan naar `Actief/` op 27-08-2026**, toen **Webinterface** afgerond was; dat was
> de volgorde die de gebruiker die dag afsprak. Het origineel staat in `Plannen/Masterplannen/Archief/` en
> is historie: hier wordt gewerkt.
>
> Taken staan in [TAKEN.md](TAKEN.md), de open beslissingen in [OPEN.md](OPEN.md). §7 en §9 hieronder zijn
> daarheen verhuisd en staan er niet meer; wat hier blijft is het ontwerp en de afweging.
## 1. Waar dit over gaat, en wat het uitdrukkelijk níet oplost
Electrum Gate is de enige app in deze store zonder eigen image. Hij draait op `python:3-alpine` en
`nginx:alpine` en mount zijn eigen programmacode uit `app-data`. Dat is geen ongeluk maar een besluit uit
het plan **Appstore**: geen eigen image bouwen betekende toen geen bouwstap, geen register en geen
inloggegevens, en de app werkte.
Dit plan stelt dat besluit ter discussie, en het begint met wat het **niet** is:
**Dit is geen oplossing voor het updateprobleem, want dat is er niet meer.** De valkuil die dit project een
dag gekost heeft is dat een update alleen een whitelist ververst. Maar `*.template` staat in die whitelist,
en alle code van deze app staat inmiddels in een `.template`-bestand: `agent.py.template`,
`index.html.template`, `nginx.conf.template` en `stream.conf.template`. Een `git push` met een
versieverhoging bereikt een bestaande installatie dus gewoon. Wie dit plan verkoopt met "dan komen
wijzigingen eindelijk aan", verkoopt iets wat al werkt.
Er is één uitzondering en die is echt: **`icon.png` is geen template** en bereikt een bestaande installatie
nooit. Dat staat als zodanig in de compose. Voor een plaatje dat vrijwel nooit wijzigt is dat goed genoeg,
en het is te klein om dit plan op te bouwen.
Wat het wél is, staat in §3.
## 2. Wat er vandaag uit `app-data` gemount wordt
De inventaris, want dit is precies de lijst die in een image zou verdwijnen.
| Bestand | Container | Wat het is |
|-|-|-|
| `agent.py` | agent | het programma: certificaten lezen, de Electrum-server bevragen, `status.json` schrijven, de keuze aannemen |
| `nginx.conf` | server | de configuratie van de pagina en de proxy naar de agent |
| `stream.conf` | server | het TLS-blok voor poort 50022, bewust apart |
| `index.html` | server | het dashboard |
| `icon.png` | server | het plaatje in de kop en het tabblad |
| het `command`-blok | server | ruim honderd regels shell in `docker-compose.yml`: log-format, TLS aan- en uitzetten, de sessieteller en de herlaadlus |
Die laatste regel is de interessantste. Dat blok staat in de compose omdat de compose in de whitelist
staat, en het moet daar dollartekens ontsnappen als `$$` omdat umbreld elk `${...}` in een template
leegmaakt. Het is dus shell in een YAML-string met een eigen ontsnappingsregel eroverheen: het enige stuk
van deze app waar de vorm door de verpakking bepaald wordt en niet door wat het doet.
## 3. Wat een eigen image oplevert
Op volgorde van hoe zwaar het weegt.
1. **De programmacode gaat uit `app-data`.** Dat is de afwijking die de gebruiker zelf opmerkte op
20-08-2026, uitgezocht in `Umbrel-appstore-spec.md`: bij andere apps staat in `app-data` alleen
configuratie en data, want hun code zit in een image. Voor eigen gebruik is dat cosmetisch. Voor het
masterplan **Publicatie-Gate** is het meer dan dat, want daar kijkt iemand anders naar het pakket.
2. **Het `command`-blok wordt een gewoon script.** Een `entrypoint.sh` in de image is te lezen, te
controleren en desnoods te testen, en hoeft geen dollartekens te verdubbelen. Dat is de grootste
inhoudelijke winst en de enige die de code zelf beter maakt.
3. **Eén digest in plaats van twee vreemde.** De pin-eis uit **Publicatie-Gate** gaat nu over
`python:3-alpine` en `nginx:alpine`, images van iemand anders die bij elke beveiligingsupdate opnieuw
gepind moeten worden. Met een eigen image pin je één ding dat je zelf uitgeeft. Let op de andere kant
hiervan: de basisimage zit dan ín jouw image, dus het onderhoud verdwijnt niet, het verhuist naar het
bouwrecept.
4. **`icon.png` wordt updatebaar**, zie §1.
## 4. Wat het kost, en dit is de reden dat het moment ertoe doet
**Elke wijziging wordt een bouwronde.** Vandaag is een wijziging aan het dashboard: bestand aanpassen,
`version` ophogen, committen, in umbrelOS updaten. Met een eigen image wordt dat: aanpassen, bouwen, naar
het register duwen, de digest opzoeken, de compose bijwerken, `version` ophogen, committen, updaten. Dat is
geen ramp, maar het is een veelvoud, en het moet op de machine met Docker gebeuren en niet op de machine
waar geschreven wordt.
Dat is precies het probleem met "nu": het plan **Webinterface** staat op tier A en itereert op
`index.html.template`. Een bouwronde per UI-wijziging remt het plan dat op dit moment het meeste oplevert.
**Multi-arch is een tweede kostenpost.** De eis is `linux/amd64` én `linux/arm64` in de manifest-lijst. De
Umbrel van de gebruiker is amd64 (vastgesteld 20-08-2026 uit de nginx-startlog), dus een `docker build`
daar levert de helft. Dat vraagt `buildx` met QEMU, en dat is trager en kan bij een Python-image met
gecompileerde afhankelijkheden stukgaan. Deze app heeft die afhankelijkheden niet, dus de kans is klein,
maar hij is niet nul en het is nog nooit geprobeerd.
## 5. Het register: Gitea werkt, en dat is bewezen
Dit is het deel waar het minste onzeker aan is, want de weg is al een keer gelopen.
Op 25-08-2026 faalde de eerste installatie van Evolu Relay met `pull access denied` op een image die alleen
lokaal gebouwd was. De verklaring staat in `Umbrel-appstore-spec.md`: umbreld haalt elke image zelf op via
de Docker Engine API, dus lokaal bouwen bestaat niet voor hem en `pull_policy: never` verandert daar niets
aan. De oplossing werd het Gitea-register op dezelfde server als de store,
`sc.kamenier-hamer.nl/sysop/evolu-relay`, gepind op tag plus digest.
Twee dingen zijn daarbij al vastgesteld en gelden hier onverkort:
- **anoniem halen moet werken**, want umbreld krijgt geen inloggegevens mee. Controleer dat met een
uitgelogde pull in dezelfde context waarin je inlogde, anders meet je je eigen sessie. Het commando staat
onderaan `tools/evolu-relay/build.sh`;
- **het bouwrecept hoort in `tools/`**, nooit in de app-map. Een `Dockerfile` staat niet in de
update-whitelist, dus bouwen-in-de-app kost bij elke versie een deïnstallatie.
## 6. Hoe het eruit zou zien
Eén image, niet twee. De agent en nginx blijven wel twee containers, want ze doen verschillend werk en de
sessieteller moet in de netwerk-namespace van nginx zitten; maar één image met beide erin scheelt een
bouwrecept, en `nginx` plus `python3` in één alpine is klein.
```
tools/electrum-gate/
Dockerfile de basisimage, agent.py, de nginx-configuratie, de pagina, entrypoint.sh
build.sh pin op de basisimage, bouwt multi-arch, duwt naar het register, drukt de digest af
```
Wat er in de app-map overblijft: `docker-compose.yml`, `umbrel-app.yml`, `icon.png` en `data/` met zijn
twee `.gitkeep`-bestanden. De compose houdt zijn `environment`-blok, want dat is hoe
`${APP_ELECTRS_NODE_IP}` binnenkomt, en die weg is op 27-08-2026 juist bewezen bij de omschakeling naar
Fulcrum.
Eén ding om bij het ontwerp niet over te slaan: `index.html.template` bevat vandaag
`${APP_ELECTRS_NODE_IP}:${APP_ELECTRS_NODE_PORT}`, ingevuld door umbreld bij het starten. Zit de pagina in
de image, dan bestaat die invulling niet meer en moet het 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
en straks niet meer.
## 7. Open punten
Verhuisd naar [OPEN.md](OPEN.md) bij de promotie op 27-08-2026. Het gaat om drie vragen: blijft het
Gitea-register ook bij publicatie de bron, wordt het één image of twee, en waar wordt er gebouwd. De eerste
moet vóór de eerste taak beantwoord zijn.
Dit kopje blijft staan met deze verwijzing en is niet weggehaald, want de nummering van de paragrafen
hierna wordt elders aangehaald.
## 8. Wat dit voor Evolu Relay betekent
**Herschreven op 30-08-2026, want de vorige versie van deze paragraaf gokte verkeerd.** Daar stond dat het
bouwrecept van die app misschien zou vervallen omdat de kale `docker.io/evoluhq/relay:latest` de weg zou
worden, en dat je daarom niets aan dat recept moest verbeteren. Die verwachting is ingehaald: de app draait
sinds 28-08-2026 op een **eigen** image, omdat wij twee terugroepfuncties aan `createRelay` meegeven en die
in de gepubliceerde image niet zitten. Het recept in `tools/evolu-relay/` is dus geen tijdelijke toestand
maar de vaste weg.
Wat daarmee de stand is, en het is minder ver dan hier stond:
- **de relay zelf: klaar.** Eigen image, eigen recept, register gekozen, anonieme pull gecontroleerd, en
gepind op tag plus digest bij elke verhoging. Voor dat deel is dit plan uitgevoerd;
- **de agent en de pagina: niet.** Die zitten daar precies zoals bij Electrum Gate: `agent.py.template`,
`index.html.template` en `nginx.conf.template` in de app-map, gemount in `python:3-alpine` en
`nginx:alpine`. Alles in §1 tot §4 geldt dus onverkort ook voor die app;
- **multi-arch: open**, want ook dat recept bouwt vandaag één architectuur. Dat staat bij
**Publicatie-Relay**.
**De volgorde die hieruit volgt en die verder reikt dan dit plan:** zolang de agent en de pagina op vreemde
images draaien, valt er voor die twee niets zinnig te pinnen, want ze verdwijnen hier. Dat is de regel in
[KNOWLEDGE.md](../../../KNOWLEDGE.md), en Evolu Relay is er het tweede geval van.
Wat wél blijft gelden: **trek het werk aan de relay-image niet in dit plan.** Niet meer omdat het recept
misschien weggaat, maar omdat het dat níet doet en het al af is. Wat hier hoort is de agent en de pagina,
voor beide apps.
## 9. Waarom dit nú actief is
**Beslist door de gebruiker op 27-08-2026: na Webinterface**, en dat moment is er. Dat was dezelfde
afweging als waarom de pin-eis in **Publicatie-Gate** op "niet nu doen" staat: zolang er nog gedraaid en
verbeterd wordt, betaalt elke wijziging de bouwronde uit §4 en levert het niets op wat er dan ontbreekt.
**Webinterface** iterereerde die dag juist op de pagina, en dat was het werk dat er het meeste onder zou
lijden. Dat plan is dezelfde dag afgerond en naar tier B gezakt.
Het valt daarmee ook samen met het werk dat toch aan de compose gedaan moet worden vóór de inlevering uit
**Publicatie-Gate**: het pinnen en het kaal maken van het app-id vragen allebei een herinstallatie, en die
kun je één keer doen in plaats van drie keer.
**Wat dit niet is: een harde afhankelijkheid.** Technisch kon dit plan altijd al. De volgorde was een
keuze, geen feit over het plan.
@@ -0,0 +1,86 @@
# Voortgang - Eigenimage
> 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).
## 08-09-2026 (avond) - Relay gebouwd en in gebruik; het plan is af
De gebruiker bouwde en duwde de Relay-image; ook deze slaagde in één keer, ondanks apt en `www-data`. Digest
drie keer in de compose, update gedaan, pagina toont v0.6.0 en een sync werkt. Niet herinstalleerd, want de
database moest blijven; de zes achtergebleven programmabestanden zijn met de hand uit de app-datamap
gehaald. Daarmee is Eigenimage voor beide apps af en verhuist de map naar `Archief/`. Gevolg voor de rest:
de pin-taak in **Umbrelapp** is vervallen, **Publicatie-Relay** wacht niet meer op "een image die te pinnen
valt", en het enige dat er nog aan de images ontbreekt voor publicatie is `linux/arm64`.
## 08-09-2026 (later) - Evolu Relay: alles in één image, in de repo klaar
Direct erna, op verzoek van de gebruiker en met zijn keuze: één image met de relay erbij, geen tweede
recept. De drie templates zijn met `git mv` naar `tools/evolu-relay/` gegaan, naast `src/`; de Dockerfile
blijft op `node:24-slim` (om `better-sqlite3`) en haalt nginx en python3 uit apt. Twee dingen die Debian
anders doet dan de nginx-image en die je moet kennen: geen gebruiker `nginx` (dus `www-data`), en geen
`USER` meer in de image, zodat de compose de relay met `user: node` laat draaien en de andere twee als root.
De versie in de kop loopt nu via `api/status`, zoals bij Gate. Versie 0.6.0 in manifest, `VERSION` en drie
keer in de compose, ongepind. Tests: alle zes groen, niets overgeslagen; de vormtest toetst de drie tags
tegen `VERSION`. In de voorbeeldpagina staat v0.6.0 in de kop. **Niet geverifieerd: de image**, en dit is
de eerste met apt erin. Bouwen is aan de gebruiker.
## 08-09-2026 - gebouwd, gepind, geïnstalleerd: Gate draait op zijn eigen image
De gebruiker bouwde en duwde de image op de Umbrel; de bouw slaagde in één keer, dus de zorg over `apk add
python3` en de paden in de Dockerfile was ongegrond. Digest `sha256:97fee09b…7cfd8f`, twee keer in de
compose gezet, en de anonieme pull gaf dezelfde digest terug. Daarna geüpdatet, en de gebruiker heeft de
app ook gedeïnstalleerd en opnieuw geïnstalleerd zodat de oude templates uit de app-datamap zijn. De pagina
toont v0.1.0, dus de weg via `status.json` werkt. Voor Electrum Gate is dit plan af; bij die app is niets
meer over van `python:3-alpine` en `nginx:alpine`. Volgende stap is Evolu Relay, §8.
## 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
opriep, het domein in een publiek pakket en andermans installaties die aan de thuisserver hangen, gelden
allebei pas bij inlevering, en de gebruiker is daar uitdrukkelijk nog niet aan toe: dit is voorlopig zijn
eigen app voor eigen gebruik.
Daarmee is de enige vraag weg die vóór het bouwen beantwoord moest zijn, en kan fase 1 zo beginnen. Wat er
bij het antwoord hoort en niet vergeten mag worden staat in [OPEN.md](OPEN.md): bij inlevering moet het
register opnieuw beoordeeld worden, en de opmerking van de gebruiker dat umbrelOS een eigen register zou
toestaan is niet nagetrokken.
**Het plan ligt daarna meteen stil**, op zijn verzoek: hij gaat eerst verder met Evolu Relay, die getest
moet worden en op dit moment uitstaat. Er is aan dit plan nog niets gebouwd, dus er ligt ook niets half af.
**Geraakt:** alleen documentatie. **Tests:** niet van toepassing.
## 27-08-2026 - gepromoveerd naar Actief, er is nog niets gebouwd
Het masterplan is omgezet naar een plan onder `Actief/` met nummer 006, direct nadat **Webinterface**
afgerond en naar tier B gezakt was. Dat was de volgorde die de gebruiker diezelfde dag afsprak toen het
plan geschreven werd.
Er is aan de app zelf nog **niets** gedaan. Wat hier ligt is ontwerp: de inventaris van wat er vandaag uit
`app-data` gemount wordt, wat een eigen image wel en niet oplevert, en wat het kost. De drie open
beslissingen uit §7 zijn naar [OPEN.md](OPEN.md) verhuisd.
Het eerste wat er moet gebeuren is geen bouwtaak maar open punt 1: blijft het Gitea-register ook bij
publicatie de bron. Dat bepaalt waar het bouwrecept naartoe duwt.
**Geraakt:** alleen documentatie. **Tests:** niet van toepassing.
+122
View File
@@ -0,0 +1,122 @@
# Taken - Eigenimage
> **Afgerond op 08-09-2026.** Beide apps draaien op een eigen image, gepind, met een lege app-datamap.
> Dit plan staat in `Archief/` en wordt niet meer bewerkt.
>
> Prioriteit: (was **A**) | Wacht op:
>
> **Gepromoveerd van masterplan naar `Actief/` op 27-08-2026**, direct na het afronden van
> **Webinterface**. Dat was de volgorde die de gebruiker die dag afsprak, en de reden staat in
> [PLAN.md](PLAN.md) §9: een eigen image maakt van elke paginawijziging een bouwronde, en dat had het
> werk aan de webinterface geremd. Dat werk is nu klaar.
>
> **Het register is beslist (27-08-2026): Gitea, net als bij Evolu Relay.** Bij inlevering wordt het
> opnieuw bekeken, en dat is dan een taak van **Publicatie-Gate**. De gebruiker is uitdrukkelijk nog niet
> toe aan publiceren: dit is voorlopig zijn eigen app voor eigen gebruik. Zie [OPEN.md](OPEN.md) punt 1,
> inclusief het ene ding dat daar nog uitgezocht moet worden.
>
> **En lees §1 van het plan.** Het argument dat voor de hand ligt, "dan komen wijzigingen eindelijk aan bij
> een bestaande installatie", geldt hier níet: alle code staat in een `*.template` en die staan in de
> update-whitelist. Wat dit plan wél oplevert, staat in §3.
## Volgende stap
> **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. **Op 08-09-2026 is de image op de Umbrel gebouwd, geduwd, gepind
> en geïnstalleerd**; de bouw slaagde in één keer en de app draait. Voor Electrum Gate is dit plan af.
> Wat overblijft is Evolu Relay (§8 van het plan) en, voor **Publicatie-Gate**, multi-arch.
- [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)
- [x] **Fase 4 gedaan (08-09-2026): gebouwd, geduwd, gepind, geüpdatet, herinstalleerd.** Electrum Gate
draait op zijn eigen image en de app-datamap is schoon. Voor Gate is dit plan klaar
- [x] **Evolu Relay gedaan (08-09-2026), als 0.6.0:** één image met de relay erbij, gebouwd, gepind en in
gebruik. Zie fase 5
- [x] **Dit plan is af voor beide apps** en staat in `Archief/`. Wat overblijft is geen werk van dit plan:
multi-arch bouwen en de anonieme pull per verhoging horen bij **Publicatie-Gate** en
**Publicatie-Relay**; `build.sh` van beide apps heeft er de schakelaar voor
- [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 - Het bouwrecept
- [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
- [x] **Anoniem te halen, gecontroleerd 08-09-2026.** Na `docker logout` gaf `docker pull` dezelfde digest
terug als de push. umbreld krijgt geen inloggegevens mee, dus dit was de laatste voorwaarde voor de
update
## Fase 2 - Het `command`-blok wordt een script
- [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
- [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
- [x] Image gebouwd en geduwd op de Umbrel (08-09-2026) en gepind als `0.1.0@sha256:97fee09b…7cfd8f`,
twee keer in de compose. `version` stond al op 0.1.0
- [x] Op de Umbrel geüpdatet en daarna ook gedeïnstalleerd en opnieuw geïnstalleerd (08-09-2026), zodat
de app-datamap geen oude templates meer bevat. De gebruiker meldt dat alles werkt; welke van de vijf
controles hij precies deed staat niet vast, de pagina en de versie zijn gezien
- [x] **De versie in de kop van de pagina** toont v0.1.0, dus de weg via `status.json` werkt
- [x] **`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
## Fase 5 - Evolu Relay
- [x] **Beslist (08-09-2026, gebruiker): één image met de relay erbij**, geen tweede recept. Basis blijft
`node:24-slim` om `better-sqlite3`; nginx en python3 komen uit apt
- [x] **Agent, nginx-config en pagina naar `tools/evolu-relay/`** met `git mv`, zonder `.template`.
Dockerfile en build.sh herschreven; bouwcontext is de repo-root, zoals bij Gate. `VERSION` 0.6.0,
manifest 0.6.0, drie keer dezelfde tag in de compose, ongepind tot de eerste push
- [x] **Wat er anders is dan verplaatst:** `user www-data;` in nginx.conf (Debian heeft geen gebruiker
nginx), `user: node` op de relay-service in de compose (de image heeft geen `USER` meer), de versie
via `api/status` met `RELAY_APP_VERSION`, en `PYTHONUNBUFFERED` als `ENV` in de image
- [x] Tests mee: `test_relay_agent.py` laadt `tools/evolu-relay/agent.py`; de vormtest toetst de drie
tags tegen `VERSION`; de paginatest en `voorbeeldpagina.mjs` vinden de pagina zelf
- [x] **Gebouwd, geduwd, gepind, geüpdatet en nagekeken (08-09-2026).** De bouw met apt erin slaagde in
één keer; digest `sha256:4dc56b8a…08b5b54` drie keer in de compose. Na de update toont de pagina
v0.6.0 en werkt een sync vanuit Trezor Suite, dus de relay schrijft als `node` nog in `data/relay`.
Niet herinstalleerd, want de database moest blijven; de gebruiker heeft de zes achtergebleven
programmabestanden met de hand uit de app-datamap gehaald
## Geblokkeerd / wacht op
Niets. Het plan is af.