Een eigen image is te verdedigen, maar niet met het argument dat voor de hand ligt
Masterplan Eigenimage: van de code die nu uit app-data gemount wordt een image maken, in het eigen Gitea-register. Het plan begint met wat het niet oplost. De vanzelfsprekende motivatie zou zijn dat wijzigingen een bestaande installatie niet bereiken, maar dat is niet meer waar: alle code van deze app staat in een .template en die staan in de update-whitelist. Alleen icon.png valt erbuiten, en dat is te klein om een plan op te bouwen. Wat overblijft weegt nog steeds: de code gaat uit app-data, het shell-blok van honderd regels verlaat de compose en wordt een leesbaar entrypoint, en er is nog een eigen digest in plaats van twee vreemde. De kosten staan er even hard in: een bouwronde per wijziging, precies terwijl Webinterface op tier A itereert. De registervraag is het echte open punt. Gitea werkt en dat is bij Evolu Relay bewezen, maar bij inlevering zou het domein van de gebruiker in het pakket staan en zou zijn thuisserver een afhankelijkheid van andermans installatie worden. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -64,6 +64,7 @@ daaronder, dus deze tabel en de mapinhoud kunnen niet uit elkaar lopen.
|
|||||||
| [Bereikbaarheid.PLAN.md](Plannen/Masterplannen/Bereikbaarheid.PLAN.md) | Relay | Umbrelapp: er valt niets bereikbaar te maken zolang er niets draait | Synchroniseren buiten het thuisnetwerk. **Suite eist geen TLS**, dus Tailscale blijft open en een certificaat is geen voorwaarde. Het risico van een publiek eindpunt is niet vertrouwelijkheid (dat regelt de versleuteling) maar misbruik als gratis opslag: een kale relay kent geen accounts. Wil je tóch open, dan is een eigenaars-allowlist nodig; drie manieren in §4b |
|
| [Bereikbaarheid.PLAN.md](Plannen/Masterplannen/Bereikbaarheid.PLAN.md) | Relay | Umbrelapp: er valt niets bereikbaar te maken zolang er niets draait | Synchroniseren buiten het thuisnetwerk. **Suite eist geen TLS**, dus Tailscale blijft open en een certificaat is geen voorwaarde. Het risico van een publiek eindpunt is niet vertrouwelijkheid (dat regelt de versleuteling) maar misbruik als gratis opslag: een kale relay kent geen accounts. Wil je tóch open, dan is een eigenaars-allowlist nodig; drie manieren in §4b |
|
||||||
| [Publicatie-Relay.PLAN.md](Plannen/Masterplannen/Publicatie-Relay.PLAN.md) | Relay | Umbrelapp, plus een image die te pinnen valt | Inleveren bij de officiële appstore. Twee dingen kunnen dit blokkeren: een image die niet als multi-arch digest in een registry bestaat, en de eis dat de umbrelOS-inlog aan blijft terwijl de relay een cliënt zonder sessie moet bedienen |
|
| [Publicatie-Relay.PLAN.md](Plannen/Masterplannen/Publicatie-Relay.PLAN.md) | Relay | Umbrelapp, plus een image die te pinnen valt | Inleveren bij de officiële appstore. Twee dingen kunnen dit blokkeren: een image die niet als multi-arch digest in een registry bestaat, en de eis dat de umbrelOS-inlog aan blijft terwijl de relay een cliënt zonder sessie moet bedienen |
|
||||||
| [Publicatie-Gate.PLAN.md](Plannen/Masterplannen/Publicatie-Gate.PLAN.md) | Gate | Appstore: de herstart-controle | **Doel van de gebruiker sinds 20-08-2026:** de app inleveren als standaard-app voor Umbrel. Dat verandert de maatstaf van "hij werkt hier" naar "iemand anders keurt het pakket goed". Het meeste is al goed; wat er nog moet is de images pinnen, het app-id kaal maken en de manifestvelden op orde. Het risico zit niet in die lijst maar in de leesmount op de certificaten van Zoraxy |
|
| [Publicatie-Gate.PLAN.md](Plannen/Masterplannen/Publicatie-Gate.PLAN.md) | Gate | Appstore: de herstart-controle | **Doel van de gebruiker sinds 20-08-2026:** de app inleveren als standaard-app voor Umbrel. Dat verandert de maatstaf van "hij werkt hier" naar "iemand anders keurt het pakket goed". Het meeste is al goed; wat er nog moet is de images pinnen, het app-id kaal maken en de manifestvelden op orde. Het risico zit niet in die lijst maar in de leesmount op de certificaten van Zoraxy |
|
||||||
|
| [Eigenimage.PLAN.md](Plannen/Masterplannen/Eigenimage.PLAN.md) | Gate | – | Van de code die nu uit `app-data` gemount wordt een eigen image maken, in het eigen Gitea-register. **Het lost níet het updateprobleem op**, want alle code staat al in een `*.template` en die staan in de whitelist. Wat het wel doet: code uit `app-data`, het shell-blok van honderd regels uit de compose, en één eigen digest in plaats van twee vreemde. Kosten: een bouwronde per wijziging, en multi-arch is nog nooit geprobeerd |
|
||||||
| [Configuratie.PLAN.md](Plannen/Masterplannen/Configuratie.PLAN.md) | Gate | – | **Grotendeels ingehaald op 19-08-2026** en moet opgeschoond worden voordat promotie nog zin heeft: de agent doet de certificaatbronnen en de keuze al, en het hardgecodeerde domein is uit de compose en uit `nginx.conf.template` verdwenen. Wat er nog in zit is een configuratiebestand voor de poort- en padoverstemmingen, plus de README |
|
| [Configuratie.PLAN.md](Plannen/Masterplannen/Configuratie.PLAN.md) | Gate | – | **Grotendeels ingehaald op 19-08-2026** en moet opgeschoond worden voordat promotie nog zin heeft: de agent doet de certificaatbronnen en de keuze al, en het hardgecodeerde domein is uit de compose en uit `nginx.conf.template` verdwenen. Wat er nog in zit is een configuratiebestand voor de poort- en padoverstemmingen, plus de README |
|
||||||
|
|
||||||
Cross-plan kennis staat in [KNOWLEDGE.md](KNOWLEDGE.md). Naslag staat niet in deze boom maar in
|
Cross-plan kennis staat in [KNOWLEDGE.md](KNOWLEDGE.md). Naslag staat niet in deze boom maar in
|
||||||
|
|||||||
@@ -0,0 +1,171 @@
|
|||||||
|
# Eigenimage - masterplan
|
||||||
|
|
||||||
|
> **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.
|
||||||
|
>
|
||||||
|
> Nog geen tier en geen nummer. Wat er eerst beslist moet worden staat in §7, en het moment staat in §9.
|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
|
1. **Blijft het Gitea-register ook bij publicatie de bron?** Voor eigen gebruik is het antwoord ja, en het
|
||||||
|
is bewezen. Voor het masterplan **Publicatie-Gate** zitten er twee bezwaren aan die geen van beide een
|
||||||
|
spec-eis zijn maar allebei echt:
|
||||||
|
|
||||||
|
- **het domein van de gebruiker komt in de compose van een publieke repo**, en dat is precies wat het
|
||||||
|
plan **Configuratie** eruit gehaald heeft. Nu staat het in de store-URL van een repo die niemand
|
||||||
|
aangekondigd heeft; dan zou het in het pakket staan dat aan de officiële store aangeboden wordt;
|
||||||
|
- **iedereen die de app installeert haalt dan een image van de thuisserver van de gebruiker.** Dat maakt
|
||||||
|
die server een afhankelijkheid van andermans installatie, met het verkeer en de beschikbaarheid die
|
||||||
|
daarbij horen.
|
||||||
|
|
||||||
|
De spec eist alleen `registry/repo:versie-of-commit@sha256:<digest>` met beide architecturen, en zegt
|
||||||
|
niets over wélk register. Gitea voldoet dus aan de letter. De vraag is of je dat wilt.
|
||||||
|
**Moment:** voordat dit actief wordt · **Eigenaar:** gebruiker
|
||||||
|
|
||||||
|
2. **Eén image of twee?** §6 stelt één voor. Twee is netter gescheiden en verdubbelt het bouwwerk.
|
||||||
|
**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 amd64. Bouwen op
|
||||||
|
de werkplek van de gebruiker vraagt daar Docker.
|
||||||
|
**Moment:** bij de start van het werk · **Eigenaar:** gebruiker
|
||||||
|
|
||||||
|
## 8. Wat dit voor Evolu Relay betekent
|
||||||
|
|
||||||
|
Voor die app is dit plan grotendeels al uitgevoerd: `tools/evolu-relay/build.sh` bestaat, het register is
|
||||||
|
gekozen en de anonieme pull is gecontroleerd. Wat hier eventueel bijkomt is de multi-arch-stap, want ook
|
||||||
|
dat recept bouwt vandaag één architectuur.
|
||||||
|
|
||||||
|
**Trek dat werk niet in dit plan.** Het plan **Umbrelapp** staat op tier A met de conclusie dat de
|
||||||
|
gepakketteerde relay in de kern niet kan werken, en dat de volgende stap de kale
|
||||||
|
`docker.io/evoluhq/relay:latest` is. Wordt dat de weg, dan is er een gepubliceerde image en vervalt het
|
||||||
|
hele bouwrecept. Iets verbeteren aan een recept dat misschien weggaat, is de verkeerde volgorde.
|
||||||
|
|
||||||
|
## 9. Wanneer dit actief zou moeten worden
|
||||||
|
|
||||||
|
**Niet nu, en om dezelfde reden 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 vandaag ontbreekt.
|
||||||
|
|
||||||
|
Het natuurlijke moment is als **Webinterface** klaar is met itereren op de pagina, en vóór de inlevering
|
||||||
|
uit **Publicatie-Gate**. Dan valt dit samen met het werk dat toch aan de compose gedaan moet worden: 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.
|
||||||
|
|
||||||
|
Harde afhankelijkheid heeft dit plan niet. Het kan technisch morgen.
|
||||||
Reference in New Issue
Block a user