createRelay uit @evolu/nodejs neemt twee terugroepfuncties, isOwnerAllowed en isOwnerWithinQuota, en Trezor doet in createEvoluRelay.ts zelf niets anders. Hun hele quota-manager met Postgres bestaat alleen om de tabel te vullen die die twee raadplegen. Wij vullen ze met eigen logica en bouwen niets na. Weg 1 uit Bereikbaarheid 4b is daarmee veel goedkoper dan daar aangenomen, en dat is wat de keuze van de gebruiker mogelijk maakt. De logica zoals hij hem formuleerde: de eerste eigenaar die zich meldt wint, een schakelaar bepaalt of er nog nieuwe bij mogen, en data is per eigenaar te wissen. Dat laatste doet het relay-proces zelf, aangestuurd met een vlagbestand vanaf de pagina; geen tweede container die langszij in de SQLite schrijft en geen Docker-socket. Twee feiten uit de broncode van Evolu die het ontwerp sturen en die in de naslag staan met bron. De gepubliceerde image zet isOwnerWithinQuota op 1 MB per eigenaar en laat isOwnerAllowed weg, dus een kale relay is niet volledig ongelimiteerd, maar dat plafond geldt ook voor de echte gebruiker. En de relay-URL van de client bevat een pad dat letterlijk wordt overgenomen, wat een goedkope proxy-controle mogelijk maakt; die is bewust niet genomen nu de allowlist er komt. De poorten gaan om: pagina achter app_proxy met de inlog aan, relay op een eigen gepubliceerde poort waar Zoraxy met TLS naartoe wijst. Dat lost open punt 2 op zonder het bezwaar dat daar stond, en het volgt het patroon dat Electrum Gate in deze repo al gebruikt. De pagina volgt hetzelfde ontwerpsysteem, zonder de Google Fonts-verwijzing eruit. Open punt 8 en 2 zijn beslist, fase 5 staat als takenlijst. De gebruiker heeft de oude installatie van de Umbrel gehaald; er wordt niet geupdatet maar opnieuw gebouwd. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
425 lines
25 KiB
Markdown
425 lines
25 KiB
Markdown
# Umbrelapp - plan
|
|
|
|
> **App: Evolu Relay.** Ontwerp en afbakening. **Dit bestand lees je zelden**, alleen bij twijfel over
|
|
> scope of architectuur. Status staat in [TAKEN.md](TAKEN.md), geschiedenis in [PROGRESS.md](PROGRESS.md),
|
|
> onbesliste punten in [OPEN.md](OPEN.md).
|
|
>
|
|
> Gepromoveerd uit `Masterplannen/` op 25-08-2026, toen de gebruiker besloot het pakket meteen te maken in
|
|
> plaats van te wachten op de proefopstelling.
|
|
|
|
## 1. Doel
|
|
|
|
Een tweede app in deze store: `whatsnext-evolu-relay/`, met een manifest en een compose, geïnstalleerd op
|
|
de Umbrel van de gebruiker, met Trezor Suite die erop synchroniseert.
|
|
|
|
## 2. Afbakening
|
|
|
|
Het pakket en de installatie: manifest, compose, het bouwrecept voor de image, en de controles op het
|
|
apparaat zelf.
|
|
|
|
De store zelf valt hier buiten: die bestaat en serveert Electrum Gate al. Wat erbij komt is één map.
|
|
|
|
## 3. Niet-doelen
|
|
|
|
- **Geen bereikbaarheid van buiten het thuisnetwerk.** Masterplan **Bereikbaarheid**. Dit plan is af als
|
|
het op het eigen netwerk werkt.
|
|
- **Geen inlevering bij de officiële store.** Masterplan **Publicatie-Relay**.
|
|
- **Geen wijzigingen aan de relay zelf.** Wat Trezor levert, draaien we.
|
|
- **Geen eigen statuspagina.** Zie [OPEN.md](OPEN.md) punt 2.
|
|
|
|
## 4. Ontwerp
|
|
|
|
Alles hieronder rust op [Upstream-evolu-relay.md](../../../Referenties/Upstream-evolu-relay.md), waar de
|
|
feiten met bron-URL per stuk staan. De vorm van een Umbrel-app staat in
|
|
[Umbrel-appstore-spec.md](../../../Referenties/Umbrel-appstore-spec.md).
|
|
|
|
> **Let op de tweedeling in deze paragraaf.** §4a tot en met §4f beschrijven het pakket **zoals het op
|
|
> 25-08-2026 gebouwd is**, met de relay van Trezor, een Postgres en de quota-manager. Dat pakket gaat eruit:
|
|
> de proef van 28-08 (§6a) bewees dat de kale Evolu-relay werkt, en §4g en §4h beschrijven wat ervoor in de
|
|
> plaats komt. De oude paragrafen blijven staan tot de verbouwing gedaan is, want ze leggen uit waaróm er
|
|
> iets weggaat; daarna verdwijnen ze.
|
|
|
|
### 4a. Drie containers, twee images
|
|
|
|
De relay en de quota-manager komen uit **dezelfde** image met een ander `command`: bovenstrooms is het één
|
|
codebase met meerdere startscripts. Daarnaast een Postgres. Dat is de hele stack.
|
|
|
|
Het `command` staat expliciet in de compose en leunt niet op de `CMD` van de Dockerfile: daar staat
|
|
`yarn start`, met bovenstrooms zelf een commentaar dat het misschien een van de twee specifieke scripts had
|
|
moeten zijn.
|
|
|
|
### 4b. De quota-manager gaat mee, en waarom dat geen keuze was
|
|
|
|
De relay weigert elke eigenaar die geen rij in de limietentabel heeft (`isOwnerAllowed()`), en de
|
|
quota-manager maakt die rijen. Er is **geen** HTTP-koppeling tussen de twee: geen URL in de configuratie,
|
|
ze delen alleen de database.
|
|
|
|
Dat laatste opent een tweede weg, die hier bewust niet gekozen is: de rij met de hand in de database
|
|
zetten en de quota-manager weglaten. Minder bewegende delen, maar het is schrijven in andermans schema en
|
|
dat breekt bij de eerste migratie. De container kost weinig; het risico van zelf in hun tabellen schrijven
|
|
is groter dan de winst.
|
|
|
|
### 4c. De app-proxy zonder inlog, en dat is het patroon en geen omweg
|
|
|
|
Trezor Suite is geen browser met een sessiecookie. Achter `app_proxy` met de standaardinstelling krijgt het
|
|
een inlogpagina in plaats van de relay.
|
|
|
|
De oplossing is `PROXY_AUTH_ADD: "false"`, met `port` in het manifest als de poort waar Suite naartoe
|
|
wijst. **Dat is niet zelfbedacht:** de eigen `nostr-relay`-app in de officiële store doet exact dit, om
|
|
precies dezelfde reden, en Gitea en Budibase doen het ook. Daarmee is de zwaarste ontwerpvraag van dit plan
|
|
beantwoord met een precedent in plaats van met een gok.
|
|
|
|
Het alternatief dat is afgevallen: een eigen `ports:` op de service, zoals Electrum Gate met 50022 doet.
|
|
Dat kan, maar het vraagt een tweede poort die op de host vrij moet zijn, terwijl de proxy-poort er al is.
|
|
|
|
**De prijs staat in de compose genoemd en hoort ook hier:** wie die poort kan bereiken, bereikt de relay
|
|
zonder aanmelding. Wat de schade beperkt is de weigering uit §4b. Dat is een reden om deze app niet zonder
|
|
meer naar het internet open te zetten, en het is de kern van het risico in **Publicatie-Relay**.
|
|
|
|
### 4d. De poort is 3851 en niet 4000
|
|
|
|
`port` in het manifest is de poort waarop umbrelOS de app aanbiedt. 4000 zou aansluiten op de eigen poort
|
|
van de relay, maar het is een veelgebruikte poort en een botsing op de host merk je pas als de app niet
|
|
start. Dat heeft bij Electrum Gate een dag gekost, met 50002 tegen Fulcrum. 3851 sluit aan op de 3850 van
|
|
die app.
|
|
|
|
### 4e. De database
|
|
|
|
Postgres onder `${APP_DATA_DIR}/data/postgres`, niet in een naamloos Docker-volume: dat is wat umbrelOS
|
|
bewaart en in de back-up meeneemt. Het wachtwoord komt uit `${APP_PASSWORD}`, per installatie afgeleid,
|
|
want deze repo is publiek.
|
|
|
|
`PGDATA` staat op een submap van de mount en niet op de wortel: Postgres weigert een datamap die al iets
|
|
anders bevat, en een mount kan een `lost+found` hebben.
|
|
|
|
De image is `postgres:17-alpine` en niet `postgres` kaal zoals bovenstrooms: dat laatste is `latest`, en
|
|
een grote-versiesprong migreert de datamap niet vanzelf. Dan start de database niet meer.
|
|
|
|
`backupIgnore` blijft leeg. Electrum Gate gebruikt dat veld wel, maar daar gaat het om een log en een
|
|
statusbestand; hier ís de database de waarde van de app.
|
|
|
|
### 4f. De image bouwen we zelf, en het recept staat in de repo
|
|
|
|
Trezor publiceert geen image: hun werkproces duwt naar een eigen Amazon ECR en op Docker Hub staat niets.
|
|
Er is dus een bouwstap, en die moet ergens.
|
|
|
|
**Niet in de app-map.** Dat is technisch mogelijk (`build:` in plaats van `image:`, en umbreld roept gewoon
|
|
`docker compose` aan), maar drie dingen maken het verkeerd, en het derde is fataal: de broncode zou in onze
|
|
repo moeten staan, de bouw duurt minuten tijdens het starten van de app, en **een `Dockerfile` staat niet in
|
|
de update-whitelist**, dus elke nieuwe versie zou een deïnstallatie plus herinstallatie vragen.
|
|
|
|
De gekozen vorm: `tools/evolu-relay/build.sh` haalt de broncode op een **vastgezette commit** en bouwt hun
|
|
Dockerfile. Het recept is versiebeheerd en na te lezen, de uitkomst staat in de Docker-opslag of later in
|
|
een register, en de compose verwijst alleen naar de tag. We bouwen niet hun Dockerfile na; wat wij
|
|
toevoegen is uitsluitend de pin.
|
|
|
|
Voorlopig blijft die tag lokaal, op verzoek van de gebruiker: dat is de kortste weg naar een installatie
|
|
die je kunt proberen. Compose haalt niets op zolang de image lokaal bestaat, dus dezelfde regel werkt later
|
|
ook als de tag naar een register wijst. Waar dat register komt te staan is [OPEN.md](OPEN.md) punt 1.
|
|
|
|
### 4g. De limiter is niet een eigen relay maar twee functies
|
|
|
|
Beslist op 28-08-2026 door de gebruiker, na de geslaagde proef. De feiten met bron staan in
|
|
[Upstream-evolu-relay.md](../../../Referenties/Upstream-evolu-relay.md) §8.
|
|
|
|
`createRelay` uit `@evolu/nodejs` neemt twee terugroepfuncties: `isOwnerAllowed(ownerId)` en
|
|
`isOwnerWithinQuota(ownerId, requiredBytes)`. **Trezor doet precies dit en niets meer**; hun hele
|
|
quota-manager met Postgres bestaat alleen om de tabel te vullen die die twee functies raadplegen. Wij
|
|
vullen ze met eigen logica en houden verder alles van bovenstrooms. Er wordt dus **geen relay nagebouwd en
|
|
niets van Evolu aangepast**.
|
|
|
|
De logica die erin komt, zoals de gebruiker hem formuleerde:
|
|
|
|
- **de eerste eigenaar die zich meldt, wordt de eigenaar.** Geen id intikken, want Suite toont je `OwnerId`
|
|
nergens;
|
|
- **een schakelaar die bepaalt of er nog nieuwe eigenaars bij mogen.** Dit is wat de leer-variant bruikbaar
|
|
maakt in een huishouden: openzetten, tweede apparaat koppelen, weer dichtzetten;
|
|
- **data per eigenaar wissen**, zodat een verkeerd geleerde eigenaar geen herinstallatie kost.
|
|
|
|
**De prijs die we hiermee accepteren:** de bouwstap en het eigen register komen terug, want dit vraagt een
|
|
eigen image. Wat níet terugkomt is de Postgres, het wachtwoord en het onderhoud aan andermans schema. Het
|
|
bouwrecept in `tools/evolu-relay/` blijft dus bestaan, maar het bouwt straks niet meer de repo van Trezor;
|
|
het bouwt een klein eigen programma tegen `@evolu/nodejs`.
|
|
|
|
**Twee dingen om niet over te slaan.** De gepubliceerde image zet `isOwnerWithinQuota` op **1 MB per
|
|
eigenaar** en laat `isOwnerAllowed` weg. Nemen wij die grens over zonder erbij na te denken, dan stopt het
|
|
synchroniseren zodra de labelgeschiedenis daar tegenaan loopt, en dat merk je pas als het gebeurt. En de
|
|
allowlist is **staat**: die hoort onder `${APP_DATA_DIR}/data/`, naast de relay-database en niet erin.
|
|
|
|
**Wat er bewust níet in gaat: een geheim pad in de URL.** De cliënt neemt een pad in de relay-URL letterlijk
|
|
over, dus Zoraxy had alleen een onraadbaar pad kunnen doorlaten. Dat is een laag vóór de relay in plaats van
|
|
erin, en het is met één proxyregel alsnog toe te voegen. De gebruiker ziet er geen reden voor nu de
|
|
allowlist er komt, en dat klopt: het beschermt tegen hetzelfde, alleen eerder in de keten.
|
|
|
|
### 4h. De poorten omgedraaid: pagina achter de inlog, relay ernaast
|
|
|
|
Beslist op 28-08-2026, en het draait §4c om. Daar stond de relay achter de app-proxy met de inlog uit, en
|
|
dat maakte een statuspagina onmogelijk zonder die pagina net zo bloot te leggen.
|
|
|
|
De nieuwe indeling volgt het patroon dat Electrum Gate in deze repo al gebruikt:
|
|
|
|
- **de pagina achter `app_proxy`, met de umbrelOS-inlog gewoon aan.** Dat is de app-tegel op het dashboard;
|
|
- **de relay op een eigen `ports:`-regel**, waar Zoraxy met TLS op een eigen subdomein naartoe wijst.
|
|
|
|
Suite ziet daarmee nooit een inlogpagina en de pagina is nooit onbeschermd. Dat lost open punt 2 op zonder
|
|
de tweede poort die daar als bezwaar stond, want die tweede poort is er toch al.
|
|
|
|
**Zoraxy moet de WebSocket-upgrade doorlaten**, anders lijkt het beeld op dat van 28-08: een server die
|
|
leeft en een cliënt die niets doet. De handshake-curl uit §6a stap 3 is de test.
|
|
|
|
**De pagina volgt hetzelfde ontwerpsysteem als Electrum Gate**, aangewezen door de gebruiker op
|
|
28-08-2026: `HomeGit/Docs/website-design-system.html`. Dat is geen kwestie van smaak maar van herkenning,
|
|
want de twee apps staan straks naast elkaar op hetzelfde dashboard. Electrum Gate neemt die tokens
|
|
letterlijk over (`data-theme` maal `data-accent`, dezelfde accentkleur) en dat is het vertrekpunt. **Eén
|
|
ding niet overnemen uit het bronbestand: de verwijzing naar Google Fonts.** De pagina van Electrum Gate
|
|
heeft die bewust niet, en een app op een Umbrel hoort niet stuk te gaan of te vertragen op een lettertype
|
|
dat van buiten moet komen.
|
|
|
|
**De pagina praat niet met Docker.** Dezelfde regel als bij Electrum Gate: geen socket. De pagina en het
|
|
relay-proces delen een map onder `${APP_DATA_DIR}/data/`, en een knop op de pagina zet daar een vlagbestand
|
|
neer dat het relay-proces oppakt. Dat geldt zowel voor de schakelaar als voor het wissen: het wissen raakt
|
|
de SQLite van de relay, en dat hoort het proces te doen dat die database bezit, niet een tweede container
|
|
die er langszij in schrijft.
|
|
|
|
## 5. Raakvlakken
|
|
|
|
- **Proefopstelling** leverde alle feiten waarop §4 rust, en heeft nog twee open vragen die dit plan raken:
|
|
of Trezor Suite een eigen relay accepteert, en hoe je een eigenaar registreert.
|
|
- **Bereikbaarheid** begint waar dit plan ophoudt.
|
|
- **Publicatie-Relay** erft §4c als grootste review-risico, en §4f als grootste praktische eis.
|
|
- **Appstore** (Electrum Gate) leverde de les die §4d stuurt, en de ervaring dat een store-URL wisselen een
|
|
herinstallatie is.
|
|
|
|
## 6. Verificatie
|
|
|
|
Automatisch, en dat draait al: `tests/test_appstore_vorm.py` controleert voor élke app in deze repo dat het
|
|
`id` gelijk is aan de mapnaam, dat het store-voorvoegsel klopt, dat de manifestvelden in de voorgeschreven
|
|
volgorde staan, dat de `app_proxy` naar een bestaande service wijst en dat elke gemounte map in de repo
|
|
bestaat. Het pint niets af op digests; dat is bewust, zie de kop van dat bestand.
|
|
|
|
Op de Umbrel, en dat is waar dit plan om gaat:
|
|
|
|
1. de image bouwen met `tools/evolu-relay/build.sh`;
|
|
2. de app installeren en zien dat alle drie de containers blijven draaien. **De database is hier de
|
|
twijfel:** of het schema zichzelf aanmaakt is niet uitgezocht;
|
|
3. Trezor Suite naar `<umbrel>:3851` laten wijzen en een label synchroniseren. Dit is de enige controle die
|
|
telt, en hij kan mislukken op de registratie uit §4b zonder dat er iets mis is met het pakket;
|
|
4. de app stoppen en starten, en controleren dat de database het overleeft;
|
|
5. controleren dat het toevoegen van deze app Electrum Gate niet raakt.
|
|
|
|
Meld per controle of hij gedaan is, en meld ook expliciet welke niet.
|
|
|
|
### 6a. Testprotocol: praat Trezor Suite met de kale relay?
|
|
|
|
Geschreven 28-08-2026, als uitwerking van de eerste taak in [TAKEN.md](TAKEN.md) en van
|
|
[OPEN.md](OPEN.md) punt 6. Deze proef gaat **niet** over het pakket dat er nu staat: hij draait de kale
|
|
`docker.io/evoluhq/relay:latest` los ernaast, met één commando, en raakt de app niet aan.
|
|
|
|
**De vraag die hij beantwoordt:** past de protocolversie van Suite (`@evolu/web@3.0.0-next.1`, met een
|
|
eigen patch in `.yarn/patches/`) op de gepubliceerde image van Evolu? Dat is het enige dat nog niet uit de
|
|
broncode af te leiden was.
|
|
|
|
**Wat hij níet beantwoordt:** of de relay veilig genoeg is om zo te draaien. Dat is de limiter uit
|
|
[OPEN.md](OPEN.md) punt 8, en die vraag komt pas ná een geslaagde uitslag.
|
|
|
|
**Eigenaar: gebruiker.** Dit is niet vanaf een laptop met alleen de repo te doen.
|
|
|
|
#### Voorbereiding
|
|
|
|
1. Een host met Docker en poort 4000 vrij. De Umbrel is het handigst; daar moet het met `sudo`, want de
|
|
gebruiker `umbrel` zit niet in de groep `docker`. Naast Suite op de PC mag ook.
|
|
2. De app `whatsnext-evolu-relay` staat uit, en dat blijft zo. Er is dus geen botsing, ook niet op 3851.
|
|
3. Het Trezor-apparaat bij de hand: het aanzetten van de synchronisatie vraagt een bevestiging op het
|
|
apparaat zelf.
|
|
4. Een tweede Suite-installatie is **niet** nodig, maar wel de enige manier om de proef helemaal rond te
|
|
krijgen. Zie stap 7.
|
|
|
|
#### De stappen
|
|
|
|
**1. De image halen en bekijken.** Dit legt meteen twee dingen vast die verderop nodig zijn: waar de relay
|
|
zijn data neerzet, en de digest waarop later te pinnen valt.
|
|
|
|
```
|
|
sudo docker pull docker.io/evoluhq/relay:latest
|
|
```
|
|
|
|
```
|
|
sudo docker image inspect docker.io/evoluhq/relay:latest --format '{{index .RepoDigests 0}} | cmd={{.Config.Cmd}} | ports={{.Config.ExposedPorts}} | volumes={{.Config.Volumes}}'
|
|
```
|
|
|
|
Noteer de digest en het datapad. Onze naslag zegt `/app/data`, maar dat komt uit de documentatie van Evolu
|
|
en niet uit de image; wat hier uitkomt is de waarheid.
|
|
|
|
**Gemeten op 28-08-2026:** `evoluhq/relay:latest` staat op
|
|
`sha256:dbbe0ca13a78beffcfcbedadd4081c4452e81599801d375d93b0861b411535d2`. Dat is de digest die bij een
|
|
pull op tag gemeld wordt, dus de index-digest, en daarmee precies wat er bij een pin in de compose hoort.
|
|
Nog niet gecontroleerd is of die index arm64 bevat; dat telt pas bij **Publicatie-Relay**.
|
|
|
|
**2. Starten, op de voorgrond.** Het log is de helft van de meting, dus laat dit venster staan.
|
|
|
|
```
|
|
sudo docker run --rm --name evolu-proef -p 4000:4000 docker.io/evoluhq/relay:latest
|
|
```
|
|
|
|
**Een goede start meldt één regel: `Evolu Relay started on port 4000`** (gemeten 28-08-2026). Meer komt er
|
|
bij het opstarten niet, dus dat is het hele startsignaal.
|
|
|
|
**En `healthy` in `docker ps` betekent hier minder dan het lijkt.** De healthcheck van de image opent met
|
|
Node een TCP-verbinding naar 127.0.0.1:4000 en sluit hem meteen; er gaat geen enkel verzoek overheen. Groen
|
|
zegt dus alleen dat de poort binnen de container accepteert, niet dat de relay iets zinnigs doet. Dat is
|
|
dezelfde fout als de bovenstroomse Postgres-healthcheck uit §4e, en de les herhaalt zich: **nemen we deze
|
|
image in het pakket op, dan hoort er een healthcheck bij die wél iets vraagt.** Vergat je `--name`, dan vind je de naam met
|
|
`sudo docker ps --filter ancestor=evoluhq/relay:latest --format '{{.ID}} {{.Names}}'`.
|
|
|
|
**3. Luistert hij, en spreekt hij WebSocket?** In een tweede venster:
|
|
|
|
```
|
|
curl -si --max-time 5 -H 'Connection: Upgrade' -H 'Upgrade: websocket' -H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==' http://127.0.0.1:4000/
|
|
```
|
|
|
|
Het antwoord hoort `HTTP/1.1 101 Switching Protocols` te zijn (gemeten 28-08-2026). `Connection refused`
|
|
betekent dat er niets luistert, en dan is stap 1 het antwoord.
|
|
|
|
**Doe dit niet met een gewone GET, en al helemaal niet met een browser.** Dat is op 28-08-2026 een half uur
|
|
zoeken geworden: de relay negeert een verzoek zonder upgrade-headers volledig, dus `curl` geeft niets terug
|
|
en de browser meldt na een minuut dat de site niet bereikbaar is. Dat ziet er identiek uit aan een dode
|
|
poort of een firewall, terwijl er niets aan de hand is. **Alleen de handshake hierboven meet iets.**
|
|
|
|
**4. Een nulmeting van de opslag.** Hierop rust de belangrijkste conclusie, dus doe hem vóór je Suite
|
|
aansluit.
|
|
|
|
**Niet met `docker diff`, en dat is een valstrik die hier op 28-08-2026 is ingelopen.** De image
|
|
declareert `/app/data` als VOLUME (gemeten: `volumes=map[/app/data:{}]`), dus Docker hangt daar een naamloos
|
|
volume in. `docker diff` toont uitsluitend de schrijflaag van de container en kijkt niet in een volume: die
|
|
uitvoer blijft leeg, ook na een geslaagde synchronisatie. Een lege uitkomst zou dan als "er landt niets"
|
|
gelezen worden, en dat is precies de verkeerde conclusie.
|
|
|
|
Meet daarom op het volume zelf. Eerst het hostpad opzoeken:
|
|
|
|
```
|
|
sudo docker inspect evolu-proef --format '{{range .Mounts}}{{.Type}} {{.Name}} -> {{.Source}}{{end}}'
|
|
```
|
|
|
|
En dan, met dat pad, de meting die je later herhaalt:
|
|
|
|
```
|
|
sudo ls -la <hostpad>
|
|
```
|
|
|
|
Schrijf de uitkomst op; leeg of alleen een verse database is een prima nulmeting. `sudo du -sb <hostpad>`
|
|
geeft er een getal bij dat makkelijker te vergelijken is.
|
|
|
|
**De nulmeting van 28-08-2026, meteen na de start:** één bestand, `evolu-relay.db`, 40960 bytes, eigenaar
|
|
uid 1001. Twee dingen die dat vastlegt. De relay maakt zijn eigen SQLite-database aan bij de start, dus de
|
|
schemavraag die bij het Trezor-pakket openstaat bestaat hier niet. En hij draait niet als root, wat precies
|
|
de reden is dat een zelfgemaakte bind-mount hier niet gebruikt wordt.
|
|
|
|
**Wij openen dat bestand niet.** Ook niet om te kijken of het label erin staat; dat is data van de
|
|
gebruiker. `ls` en `du` zeggen genoeg.
|
|
|
|
**5. Suite ernaartoe wijzen.** Instellingen, **dev-utils**, het veld voor de relay-URL:
|
|
`http://<host>:4000`, met de eigen opslaan-knop van dat veld. `http://` volstaat, dat blijkt uit Trezor's
|
|
eigen e2e-test. **De quota-manager-URL laat je met rust**: bij een eigen relay-URL negeert Suite hem toch,
|
|
en dat is precies de bevinding waar deze richting op rust. Zet daarna de synchronisatie aan en bevestig op
|
|
het apparaat.
|
|
|
|
**6. Eén label maken**, of een account hernoemen. Kijk daarna naar de drie signalen, in deze volgorde:
|
|
|
|
- **het log in venster 1**: komt er een verbinding binnen, en blijft die staan?
|
|
- **`sudo ls -la <hostpad>`** uit stap 4: is er in het volume iets bijgekomen of gegroeid? **Kijk vooral
|
|
naar de tijdstempel van `evolu-relay.db` en niet alleen naar de omvang:** SQLite schrijft in pagina's, en
|
|
een enkel label past mogelijk in de ruimte die er al is. Verschijnen er `-wal` of `-shm`-bestanden naast,
|
|
dan is dat op zichzelf al bewijs van schrijfverkeer;
|
|
- **Suite zelf**: zegt hij iets over de sync-status? Dit is het zwakste signaal van de drie, zie de
|
|
valkuil hieronder.
|
|
|
|
**7. Alleen met een tweede cliënt: de rondgang.** Wijs een tweede Suite naar dezelfde relay, met dezelfde
|
|
Trezor, en kijk of het label vanzelf verschijnt. Dit is de enige controle die beide richtingen bewijst.
|
|
Heb je die niet, dan is stap 6 het eindpunt en meld je dat de leeskant ongemeten bleef.
|
|
|
|
#### De uitslag lezen
|
|
|
|
| Waarneming | Wat het betekent |
|
|
|-|-|
|
|
| Geen verbinding in het log, curl uit stap 3 werkte wel | Suite komt er niet bij. Adresvorm, firewall of het verkeerde IP. **Nog geen uitspraak over het protocol**, dus eerst dit oplossen |
|
|
| Verbinding komt op en valt meteen weg, herhaald in een cyclus | Dit is het beeld van een geweigerde handshake, en dus de meest waarschijnlijke vorm van een protocolmismatch. **Uitslag: mislukt**, en het log is de bevinding: schrijf het letterlijk over |
|
|
| Verbinding blijft staan, maar het volume verandert niet na een label | Verbonden, maar er landt niets. Ook mislukt, en interessanter dan de vorige: dan zit het niet in de handshake maar in de laag erboven. **Controleer eerst dat je naar het volume kijkt en niet naar `docker diff`** |
|
|
| Verbinding blijft staan én het volume groeit | **Geslaagd op de schrijfkant.** Dit is genoeg om de richting uit punt 6 te bevestigen en aan de limiter te beginnen |
|
|
| En de tweede cliënt ziet het label | **Volledig geslaagd.** Beide richtingen bewezen |
|
|
|
|
#### De valkuil, en hij is groot
|
|
|
|
**Dat je het label in Suite ziet staan bewijst niets.** Evolu is local-first: de schrijfactie landt eerst
|
|
in de lokale database en daarna pas bij de relay. Bij een mislukte verbinding ziet de interface er dus
|
|
precies hetzelfde uit. Vandaar dat de conclusie in de tabel hierboven aan de **relaykant** hangt en niet
|
|
aan wat Suite toont.
|
|
|
|
#### Opruimen
|
|
|
|
Ctrl-C in venster 1; door `--rm` verdwijnt de container en met hem de opslag. Dat is voor een proef prima,
|
|
maar het betekent ook dat een herhaling opnieuw bij nul begint, en dat je een geslaagde meting niet per
|
|
ongeluk op oude data doet.
|
|
|
|
**Zet daarna de relay-URL in Suite terug**, anders blijft hij naar een relay wijzen die er niet meer is.
|
|
|
|
**En laat de proefcontainer niet staan.** Hij is onbeschermd bereikbaar op het hele netwerk, en dat is nu
|
|
juist het gat dat de limiter uit [OPEN.md](OPEN.md) punt 8 moet dichten.
|
|
|
|
#### Wat je terugkoppelt
|
|
|
|
Het log uit venster 1 (letterlijk, ook als het er saai uitziet), de inhoud van het volume van vóór en
|
|
na, de digest uit stap 1, en of stap 7 gedaan is. Met die vier is de vervolgsessie beslisbaar zonder de
|
|
proef te herhalen.
|
|
|
|
#### Wat er op 28-08-2026 gemeten is, en wat nog steeds niet
|
|
|
|
**De proef is geslaagd: de protocolversie klopt.** Trezor Suite op de desktop stuurde elf labels naar de
|
|
kale relay en die kwamen aan. De database in het volume groeide van 40960 naar 49152 bytes en de
|
|
tijdstempel verzette van 07:55 naar 08:38. Geen Postgres, geen quota-manager, geen eigenaarsregistratie,
|
|
en toch verkeer. Daarmee is `docker.io/evoluhq/relay:latest` bruikbaar als zelf-gehoste relay en is de
|
|
richting uit [OPEN.md](OPEN.md) punt 6 een gemeten feit in plaats van een verwachting.
|
|
|
|
**Wat daarmee níet bewezen is: de leeskant.** Er is geen tweede cliënt geweest, dus dat een ander apparaat
|
|
die labels ook terugkrijgt is nog niet gezien. Stap 7 blijft open.
|
|
|
|
De weg ernaartoe kostte een halve dag en leverde het volgende op, zodat het niet opnieuw uitgezocht hoeft
|
|
te worden.
|
|
|
|
**De relay zelf is in orde.** Hij haalt, start en luistert. De WebSocket-handshake slaagt zowel vanaf de
|
|
Umbrel zelf als vanaf een Mac elders op het netwerk, met een correcte `Sec-WebSocket-Accept`. De poort is
|
|
gepubliceerd op alle interfaces. Aan de serverkant is er dus niets te repareren.
|
|
|
|
**Hij maakt zijn database zelf aan.** Direct na de start staat er één bestand in het volume,
|
|
`evolu-relay.db` van 40960 bytes, eigenaar uid 1001. Daarmee vervalt in deze richting de schemavraag die bij
|
|
het Trezor-pakket nog openstaat, en het bevestigt dat de relay niet als root draait.
|
|
|
|
**Drie meetinstrumenten bleken onbruikbaar, en alle drie op dezelfde manier: ze gaven een vals negatief.**
|
|
Dit is de duurste les van de dag, want elk ervan leek een probleem aan te wijzen dat er niet was.
|
|
|
|
- **`docker diff` kijkt niet in een volume.** Omdat `/app/data` als VOLUME gedeclareerd is, blijft die
|
|
uitvoer leeg, ook na een geslaagde synchronisatie. Meet op het hostpad uit `docker inspect`.
|
|
- **Een browser of een gewone `curl` krijgt niets terug.** De relay negeert een verzoek zonder
|
|
upgrade-headers volledig: geen antwoord, geen foutcode. Dat ziet er identiek uit aan een dode poort of een
|
|
firewall. Alleen de handshake uit stap 3 meet iets.
|
|
- **`healthy` in `docker ps` zegt niets over werking.** De healthcheck opent een TCP-verbinding en sluit hem
|
|
meteen.
|
|
|
|
**iOS is voor deze proef geen bruikbaar platform gebleken.** Wat er werkt: het veld voor de relay-URL
|
|
bestaat in de iOS-app onder dev-utils, het valideert (`ws://` wordt geweigerd met "Enter a valid url", dus
|
|
het wil `http(s)://`, precies zoals Trezor's eigen e2e-test), en de ingevulde waarde overleeft een
|
|
geforceerde afsluiting. Wat er niet werkt: de app maakt geen enkele verbinding. Met een wachter die elke
|
|
halve seconde keek is er nooit een poging op poort 4000 aangekomen, en in de iOS-instellingen verscheen
|
|
geen schakelaar voor "Lokaal netwerk", wat erop wijst dat de app het nooit geprobeerd heeft.
|
|
|
|
Twee lezingen blijven mogelijk en zijn van buitenaf niet te scheiden: de app kan op dit platform geen eigen
|
|
relay gebruiken, of het synchroniseren zelf kwam niet op gang omdat de bevestiging op het apparaat
|
|
ontbrak. **Dat is een eigen vraag geworden en niet langer deel van deze proef**, want anders sluiten we twee
|
|
onbekenden tegelijk uit. De proef verhuist naar de desktop-Suite op de Mac, die aantoonbaar bij de relay
|
|
kan.
|
|
|
|
**Op de Mac lukte het meteen**, en daar hoort één waarschuwing bij die de proef bijna alsnog verkeerd deed
|
|
aflopen: **de relay logt geen enkele verbinding.** Het venster blijft na de startregel stil, ook terwijl er
|
|
labels binnenkomen. "Ik zie niets gebeuren" is hier dus geen waarneming maar een eigenschap van de relay.
|
|
Alleen het volume vertelt of er iets geland is, en dat is precies waarom de nulmeting uit stap 4 niet
|
|
overgeslagen mag worden.
|