218 lines
13 KiB
Markdown
218 lines
13 KiB
Markdown
# Configuratie - masterplan
|
|||
|
|
|
||
|
|
> **Status: nog niet actief.** Dit is één bestand en dat is bewust: er is nog geen `TAKEN.md`,
|
||
|
|
> `PROGRESS.md` of `OPEN.md`, want er wordt nog niet aan gewerkt. Bij promotie naar
|
||
|
|
> `Plannen/Actief/NNN-Configuratie/` worden de paragrafen hieronder over die vier bestanden verdeeld; zie
|
||
|
|
> `HomeGit/Docs/Werkproces.md` §1b.
|
||
|
|
>
|
||
|
|
> Afhankelijk van: het plan **Appstore**, omdat dit dezelfde bestanden herschrijft en die eerst hun
|
||
|
|
> nieuwe vorm moeten hebben.
|
||
|
|
|
||
|
|
## 1. Doel
|
||
|
|
|
||
|
|
De app is nu op één installatie toegesneden: het domein `sync.kamenier-hamer.nl`, het pad naar de
|
||
|
|
certificaten van Zoraxy en de poortnummers staan in de scripts en de compose. Daardoor kan hij niet
|
||
|
|
gedeeld worden, en, belangrijker, kan de repo niet publiek staan zonder de indeling van een privéserver
|
||
|
|
mee te publiceren. Dat laatste is geen theoretisch bezwaar: een community app store **moet** anoniem
|
||
|
|
kloonbaar zijn, anders kan umbrelOS hem niet ophalen.
|
||
|
|
|
||
|
|
Als dit af is, staat elke installatiespecifieke waarde in één configuratiebestand en bevat de repo zelf
|
||
|
|
niets persoonlijks meer.
|
||
|
|
|
||
|
|
## 2. Afbakening
|
||
|
|
|
||
|
|
- Alle vaste waarden uit de scripts, de compose en de web-UI halen: domein, certificaatpad,
|
||
|
|
certificaatbestandsnamen, TLS-poort, backend-poort.
|
||
|
|
- Eén configuratiebestand met verstandige standaardwaarden, dat bij een eerste start wordt aangemaakt als
|
||
|
|
het er nog niet is.
|
||
|
|
- De certificaatbron volledig instelbaar maken, met Zoraxy als standaard. Zo besloten op 18-08-2026.
|
||
|
|
**Uitgebreid op 19-08-2026** op verzoek van de gebruiker: er moeten drie bronnen zijn, en er moet
|
||
|
|
binnen zo'n bron een certificaat te **kiezen** zijn. Zie §4e.
|
||
|
|
- ~~Beslissen welke TLS-poort de standaard wordt, gezien de botsing met Fulcrum.~~ **Beslist op
|
||
|
|
19-08-2026: 50022.** De app draait er al op; zie open punt 1.
|
||
|
|
- Documenteren wat er ingesteld kan worden, in de README die de gebruiker op de repo-pagina ziet.
|
||
|
|
|
||
|
|
## 3. Niet-doelen
|
||
|
|
|
||
|
|
- **Een instellingenscherm in de web-UI**, met **één uitzondering: de keuze van het certificaat.**
|
||
|
|
Op 18-08-2026 was dit een heel niet-doel: instelbaar in een configuratiebestand is genoeg, en een
|
||
|
|
formulier dat configuratie wegschrijft vraagt een backend. Op 19-08-2026 heeft de gebruiker voor de
|
||
|
|
certificaatkeuze het tegendeel gekozen, en dat is te verdedigen omdat het de enige instelling is waar
|
||
|
|
de app de mogelijke waarden zélf al kent: hij kijkt in de gemounte mappen. Een keuzelijst met wat
|
||
|
|
gevonden is, is dan iets anders dan een configuratieformulier. De rest blijft in het bestand. Hoe de
|
||
|
|
keuze wordt weggeschreven staat in §4f.
|
||
|
|
- **Zelf certificaten aanvragen.** ACME, Let's Encrypt en verlenging blijven bij Zoraxy. Deze app leest
|
||
|
|
alleen. Dat is de hele reden dat hij zo klein kan blijven.
|
||
|
|
- **Meerdere domeinen of meerdere backends tegelijk.** Eén certificaat, één backend. Zolang daar geen
|
||
|
|
concrete aanleiding voor is, is dat onnodige complexiteit.
|
||
|
|
- **De poort die van buiten open staat.** Die is in de router doorgestuurd en staat daar op een ander
|
||
|
|
nummer; dat is netwerkbeheer en niet iets wat deze app kan of moet weten.
|
||
|
|
|
||
|
|
## 4. Ontwerp
|
||
|
|
|
||
|
|
### 4a. Waar de configuratie staat
|
||
|
|
|
||
|
|
In `${APP_DATA_DIR}/config/`. Dat is de map die umbrelOS aan de app toewijst, die een herinstallatie van
|
||
|
|
de app overleeft en die in de back-up meegaat. De repo bevat alleen een sjabloon; het werkelijke bestand
|
||
|
|
wordt bij de eerste start aangemaakt als het ontbreekt, en daarna nooit meer overschreven. Anders wist een
|
||
|
|
app-update de instellingen van de gebruiker, en dat is precies het soort fout dat je pas maanden later
|
||
|
|
merkt.
|
||
|
|
|
||
|
|
Vorm: een `.env`-achtig bestand met `SLEUTEL=waarde`, want dat is zonder hulpmiddelen te lezen door een
|
||
|
|
shellscript en met de hand te bewerken over SSH. YAML zou een parser vragen die er nu niet is.
|
||
|
|
|
||
|
|
### 4b. Wat er instelbaar wordt
|
||
|
|
|
||
|
|
| Sleutel | Standaard | Waarvoor |
|
||
|
|
|-|-|-|
|
||
|
|
| `TLS_DOMAIN` | leeg, dan automatisch detecteren | de naam waar het certificaat op staat |
|
||
|
|
| `CERT_DIR` | het Zoraxy-certificatenpad | de map met certificaat en sleutel |
|
||
|
|
| `CERT_FILE` | `${TLS_DOMAIN}.pem` | naam van het certificaat, voor bronnen die anders benoemen |
|
||
|
|
| `KEY_FILE` | `${TLS_DOMAIN}.key` | naam van de sleutel |
|
||
|
|
| `TLS_PORT` | open punt 1 | de poort waarop TLS binnenkomt |
|
||
|
|
| `CHECK_INTERVAL` | 300 | seconden tussen twee certificaatcontroles |
|
||
|
|
|
||
|
|
De backend komt hier bewust **niet** in te staan: die volgt uit `${APP_ELECTRS_NODE_IP}` en
|
||
|
|
`${APP_ELECTRS_NODE_PORT}`, die umbrelOS aanlevert op grond van de app die de gebruiker als
|
||
|
|
Electrum-server gekozen heeft. Zie het plan **Appstore**, en
|
||
|
|
[Referenties/Umbrel-appstore-spec.md](../../Referenties/Umbrel-appstore-spec.md) §4 voor waarom dat werkt.
|
||
|
|
|
||
|
|
### 4c. Automatisch detecteren van het domein
|
||
|
|
|
||
|
|
Staat `TLS_DOMAIN` leeg, dan zoekt de app in `CERT_DIR` naar een `.pem` met een gelijknamige `.key`
|
||
|
|
ernaast. Is er precies één paar, dan is dat het. Zijn het er meer, dan stopt de app met een leesbare
|
||
|
|
foutmelding die de gevonden namen noemt en vraagt om `TLS_DOMAIN` in te vullen.
|
||
|
|
|
||
|
|
Bewust **niet** "pak de nieuwste". Bij meer certificaten is de nieuwste een gok, en een verkeerd
|
||
|
|
certificaat kiezen levert een verbinding op die het lijkt te doen maar bij de wallet op een
|
||
|
|
naamsverificatiefout stukloopt. Dat is lastiger te vinden dan een app die netjes weigert te starten.
|
||
|
|
|
||
|
|
### 4d. Het certificaat lezen zonder een pad vast te leggen
|
||
|
|
|
||
|
|
Het Zoraxy-pad is nu twee keer als absoluut pad in de compose gemonteerd. Dat wordt
|
||
|
|
`${UMBREL_ROOT}/app-data/zoraxy/...`, wat hetzelfde oplevert maar niet aanneemt waar Umbrel staat.
|
||
|
|
|
||
|
|
Blijft over dat de mount in `docker-compose.yml` staat en de configuratie in een bestand: een gebruiker
|
||
|
|
die `CERT_DIR` naar iets buiten die mount wijst, ziet de map niet in de container. Dat moet in de README,
|
||
|
|
en de foutmelding moet het noemen. Het alternatief, de hele `${UMBREL_ROOT}/app-data` monteren, geeft de
|
||
|
|
app leestoegang tot de gegevens van elke andere app en dat weegt niet op tegen het gemak.
|
||
|
|
|
||
|
|
### 4e. Drie certificaatbronnen, met een keuze binnen de bron
|
||
|
|
|
||
|
|
Toegevoegd 19-08-2026 op verzoek van de gebruiker. De app moet kunnen terugvallen op meer dan Zoraxy:
|
||
|
|
|
||
|
|
| `CERT_SOURCE` | Waar de app kijkt | Wie beheert de vernieuwing |
|
||
|
|
|-|-|-|
|
||
|
|
| `zoraxy` (standaard) | `${UMBREL_ROOT}/app-data/zoraxy/data/config/conf/certs` | Zoraxy |
|
||
|
|
| `npm` | de certificatenmap van Nginx Proxy Manager | Nginx Proxy Manager |
|
||
|
|
| `own` | `${APP_DATA_DIR}/certs` | de gebruiker, met de hand |
|
||
|
|
| `custom` | wat er in `CERT_DIR` staat | onbekend |
|
||
|
|
|
||
|
|
Twee dingen die dit groter maken dan "nog een pad erbij", en die het ontwerp sturen:
|
||
|
|
|
||
|
|
- **Het is een keuze binnen een map, niet alleen een keuze van een map.** Zoraxy en Nginx Proxy Manager
|
||
|
|
beheren de certificaten van *alle* diensten op die machine, dus er staan er meestal meerdere. Welke van
|
||
|
|
die certificaten deze app moet gebruiken, is een aparte instelling. De detectie uit §4c is daarmee de
|
||
|
|
uitzondering en niet de regel: hij werkt alleen als er precies één paar staat, en dat is bij een
|
||
|
|
gedeelde certificatenmap juist zelden zo. Vandaar het harde weigeren bij meerdere treffers, met de
|
||
|
|
gevonden namen in de melding, want dát is de lijst waar de gebruiker uit kiest.
|
||
|
|
- **Nginx Proxy Manager benoemt anders.** Waar Zoraxy `<domein>.pem` en `<domein>.key` schrijft, zet NPM
|
||
|
|
zijn certificaten in genummerde mappen (`npm-<n>/fullchain.pem` en `privkey.pem`), dus het domein staat
|
||
|
|
níet in de naam. De detectie op naam werkt daar dus niet en de nummer-naar-domein-koppeling zit in de
|
||
|
|
database van NPM, die deze app niet mag lezen. **Voorlopige aanname, te verifiëren op de Umbrel voordat
|
||
|
|
dit gebouwd wordt.** Voor `npm` wordt de instelling daarom waarschijnlijk de map en niet het domein, en
|
||
|
|
leest de app het domein uít het certificaat in plaats van uit de bestandsnaam.
|
||
|
|
|
||
|
|
Gevolg voor de compose: elke bron die gemount moet worden, moet dat vooraf zijn, want een pad instellen
|
||
|
|
naar iets wat niet gemount is levert een map op die de container niet ziet. Drie read-only mounts dus
|
||
|
|
(Zoraxy, NPM, en de eigen map), en `custom` werkt alleen binnen een van die drie. Dat hoort in de README
|
||
|
|
en in de foutmelding, net als in §4d.
|
||
|
|
|
||
|
|
Sleutels die hierbij horen, bovenop de tabel in §4b: `CERT_SOURCE` met `zoraxy` als standaard, en
|
||
|
|
`CERT_NAME` voor de keuze binnen de bron. De twee samen vormen de id die §4f gebruikt, in de vorm
|
||
|
|
`bron/naam`.
|
||
|
|
|
||
|
|
### 4f. De keuze wegschrijven vanaf het dashboard
|
||
|
|
|
||
|
|
Besloten 19-08-2026 door de gebruiker: de keuze gaat via een keuzelijst op het dashboard en niet via het
|
||
|
|
configuratiebestand. Zie de uitzondering in §3.
|
||
|
|
|
||
|
|
De app kent de mogelijke waarden zelf, want ze staan in de gemounte mappen. De agent zet ze als
|
||
|
|
`certificates` in `status.json`, met per certificaat de bron, de bestandsnaam, het domein uit het
|
||
|
|
certificaat en de einddatum. De pagina toont die lijst met een keuzerondje en stuurt de gekozen id terug.
|
||
|
|
|
||
|
|
**Terugschrijven gaat via de agent**, een `PUT` op `api/certificate` die nginx doorstuurt. Dat is de
|
||
|
|
tweede container uit het plan **Webinterface** §4a0, waar ook staat waarom die er is.
|
||
|
|
|
||
|
|
Onderweg is dit twee keer van vorm veranderd, en de tussenstap is het opschrijven waard omdat hij eruit
|
||
|
|
zag als de goedkoopste oplossing:
|
||
|
|
|
||
|
|
- **eerst: de WebDAV-module van nginx.** Eén `location` met `dav_methods PUT` zet het bestand neer, geen
|
||
|
|
extra proces, geen taal erbij. Nadeel dat het onderuit haalde: WebDAV kan alleen een bestand neerzetten
|
||
|
|
en niets controleren. De validatie moest dan alsnog in de leeslus, en dan valideer je iets wat er al
|
||
|
|
staat in plaats van het te weigeren;
|
||
|
|
- **nu: de agent.** Die neemt de `PUT` aan, vergelijkt de id met wat hij zelf gevonden heeft, en weigert
|
||
|
|
met een leesbare fout als het niet klopt. Dat is dezelfde guard, maar op de plek waar hij hoort.
|
||
|
|
|
||
|
|
Waarom dit ook nu geen echt instellingenformulier is: de mogelijke waarden komen uit de gemounte mappen en
|
||
|
|
niet uit invoer van de gebruiker, dus er is niets vrij te typen. Het pad hangt achter de app-proxy van
|
||
|
|
umbrelOS, die er zijn eigen inlog voor zet, en de TLS-poort staat er los van. Het ergste wat een geslaagde
|
||
|
|
aanroep kan doen is een ander, ook bestaand, certificaat kiezen.
|
||
|
|
|
||
|
|
**De keuze staat in `${APP_DATA_DIR}/runtime/config/selected-cert`**, dus buiten de container, zodat hij
|
||
|
|
een herstart en een app-update overleeft. Dat is de eis uit §4a en hij geldt hier net zo goed.
|
||
|
|
|
||
|
|
## 5. Het werk in grote lijnen
|
||
|
|
|
||
|
|
**Fase 1 - Het configuratiebestand.** Sjabloon, aanmaken bij eerste start, inlezen in het startscript,
|
||
|
|
standaardwaarden. Uitkomst: de app leest zijn instellingen uit één bestand.
|
||
|
|
|
||
|
|
**Fase 2 - De waarden eruit.** Domein, paden en poorten uit `entrypoint.sh`, `cert-watch.sh`,
|
||
|
|
`docker-compose.yml` en `web/index.html` vervangen door de ingelezen waarden. Uitkomst: `grep` op
|
||
|
|
`kamenier` in de repo levert niets meer op buiten `Docs/`.
|
||
|
|
|
||
|
|
**Fase 3 - Automatisch detecteren en falen.** Detectie van het certificaatpaar, en leesbare fouten bij
|
||
|
|
nul of meer dan één treffer. Uitkomst: een verse installatie werkt zonder iets in te vullen, en een
|
||
|
|
onduidelijke situatie stopt met een bruikbare melding.
|
||
|
|
|
||
|
|
**Fase 4 - Documenteren.** De instellingen in de README, met de valkuil uit §4d. Uitkomst: iemand anders
|
||
|
|
kan de app installeren zonder de scripts te lezen.
|
||
|
|
|
||
|
|
## 6. Open punten
|
||
|
|
|
||
|
|
1. **Welke TLS-poort wordt de standaard?** - **50022** (19-08-2026, gebruiker).
|
||
|
|
50002 is de conventie voor Electrum over SSL, maar Fulcrum bezet die op de host, dus met Fulcrum erbij
|
||
|
|
zou de app niet starten, en dat is precies het omschakelen dat deze app moet ondersteunen. De poort
|
||
|
|
naar buiten is toch al een andere, want die staat in de router doorgestuurd, dus de conventie weegt
|
||
|
|
hier licht.
|
||
|
|
|
||
|
|
Al doorgevoerd in `docker-compose.yml` en `nginx.conf.template`, vooruitlopend op dit plan, omdat de
|
||
|
|
app op 19-08-2026 toch opnieuw geïnstalleerd werd. **Let op: dit vraagt eenmalig een aanpassing van de
|
||
|
|
doorstuurregel in de router**, anders komt een wallet van buiten niet meer binnen. De wallet zelf
|
||
|
|
merkt er niets van, want die gebruikt het externe poortnummer.
|
||
|
|
|
||
|
|
2. **Wat gebeurt er als het certificaat verdwijnt terwijl de app draait?** Nu wacht het startscript er bij
|
||
|
|
de start op, maar tijdens bedrijf is er geen gedrag afgesproken. Doorgaan met het oude certificaat in
|
||
|
|
het geheugen is waarschijnlijk het beste, maar het moet een besluit zijn en geen toeval. **Moment:**
|
||
|
|
bij fase 3. **Eigenaar:** uitvoerder.
|
||
|
|
|
||
|
|
3. **Blijft `Docs/` in de publieke repo staan?** De repo staat sinds 18-08-2026 publiek, mét het domein
|
||
|
|
en het certificaatpad in de historie. Daarmee is de geheimhoudingsvraag vervallen: `Docs/` alsnog uit
|
||
|
|
de repo halen verbergt niets meer.
|
||
|
|
|
||
|
|
Wat overblijft is een presentatievraag, en die is kleiner: de naslag beschrijft de indeling van één
|
||
|
|
specifieke server, wat voor een lezer van een publieke app store ruis is. Voorstel: laten staan, en de
|
||
|
|
installatiespecifieke voorbeelden in `Referenties/Architectuur-huidig.md` vervangen door de
|
||
|
|
configuratiesleutels zodra fase 2 klaar is. Dan documenteert de naslag het mechanisme in plaats van
|
||
|
|
één installatie. **Moment:** bij fase 4, samen met de README. **Eigenaar:** gebruiker.
|
||
|
|
|
||
|
|
## 7. Verificatie
|
||
|
|
|
||
|
|
- Een verse installatie zonder configuratiebestand start en detecteert het certificaat zelf.
|
||
|
|
- `TLS_DOMAIN` invullen overstemt de detectie.
|
||
|
|
- Twee certificaatparen in de map leveren een foutmelding op die beide namen noemt, en geen willekeurige
|
||
|
|
keuze.
|
||
|
|
- Een app-update overschrijft een bestaand configuratiebestand niet. Dit is de belangrijkste controle,
|
||
|
|
want dit is het soort fout dat pas bij de volgende update zichtbaar wordt.
|
||
|
|
- `grep -ri kamenier` over de repo levert buiten `Docs/` niets op.
|