All checks were successful
Deploy server-up (dev) / deploy (push) Successful in 1m3s
Gemeld met twee screenshots: een foutmelding dat de IP-range buiten het subnet
lag terwijl 10.0.20.240/28 gewoon binnen 10.0.20.0/24 valt, en een geval zonder
melding waarbij aanmaken toch niet lukte. Twee losse oorzaken.
1. Verouderd beoordelingsantwoord
De live beoordeling gaat af bij elke toetsaanslag. Tijdens het typen van
/28 kom je langs /2, en 10.0.20.240/2 normaliseert naar 0.0.0.0/2 - buiten
het subnet. Kwam dat antwoord na het goede binnen, dan bleef die fout staan
en bleef de knop uit.
- Volgnummer op de verzoeken; alleen het antwoord bij de laatste vraag telt.
- Knop niet meer uitgeschakeld op clientstatus; de server beslist bij het
opslaan, zodat een verouderde beoordeling nooit blokkeert.
2. CIDR met hostbits
10.0.20.200/28 leest Python met strict=False als 10.0.20.192/28, maar Docker
weigert het met "has host bits set". We valideerden soepel en stuurden de
ruwe tekst door, dus de interface keurde iets goed dat bij het aanmaken
alsnog strandde.
- normalize() zet subnet en ip_range om naar canonieke vorm voor ze naar
Docker gaan en voor ze worden opgeslagen.
- Waarschuwing die toont wat er van de invoer gemaakt is.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C7oLCRYzY5ixJ5Sv8Y8EFb
600 lines
27 KiB
Markdown
600 lines
27 KiB
Markdown
# v0.5.42-beta — Netwerk toevoegen: twee blokkades weg
|
|
|
|
Een netwerk aanmaken lukte niet, met wisselend gedrag: soms een foutmelding dat
|
|
de IP-range buiten het subnet lag terwijl dat aantoonbaar niet zo was, soms geen
|
|
melding maar toch geen resultaat. Het bleken twee losse oorzaken.
|
|
|
|
## De foutmelding die niet klopte
|
|
|
|
De beoordeling gaat af bij elke toetsaanslag. Tijdens het intypen van `/28` ga
|
|
je langs `/2`, en `10.0.20.240/2` normaliseert naar `0.0.0.0/2` — inderdaad
|
|
buiten je subnet. Kwam dat antwoord ná het antwoord voor de volledige waarde
|
|
binnen, dan bleef die foutmelding staan en bleef de knop uitgeschakeld.
|
|
|
|
Er zit nu een volgnummer op: alleen het antwoord bij de laatste vraag telt. En
|
|
de knop wordt niet meer uitgeschakeld op de clientstatus — bij het opslaan
|
|
beslist de server, zodat een verouderde beoordeling je nooit kan blokkeren.
|
|
|
|
## De range die Docker weigerde
|
|
|
|
`10.0.20.200/28` heeft hostbits gezet. Python leest dat soepel als
|
|
`10.0.20.192/28`, maar Docker is streng en antwoordt *"has host bits set"*. Wij
|
|
valideerden soepel en stuurden vervolgens de ruwe tekst door, dus de interface
|
|
keurde iets goed dat bij het aanmaken alsnog strandde.
|
|
|
|
Subnet en IP-range worden nu omgezet naar hun canonieke vorm voordat ze naar
|
|
Docker gaan én voordat ze worden opgeslagen, met een waarschuwing die laat zien
|
|
wat er van je invoer gemaakt is. `.200/28` is trouwens een logische invoer — je
|
|
bedoelt "vanaf .200" — maar een /28 begint nu eenmaal op een veelvoud van 16.
|
|
|
|
---
|
|
|
|
# v0.5.41-beta — Netwerk toevoegen liep vast tijdens het typen
|
|
|
|
Een netwerk toevoegen gaf een JSON-parsefout in de browser.
|
|
|
|
Oorzaak: de live beoordeling die bij elke toetsaanslag afgaat, bouwde een lijst
|
|
van alle bruikbare adressen in het bereik. Tijdens het intypen van
|
|
`192.168.1.0/24` is de tussenstand `192.168.1.0/2` een volkomen geldig
|
|
netwerk — met 1.073.741.824 adressen. Het verzoek liep daarop vast en de browser
|
|
kreeg geen JSON meer terug.
|
|
|
|
- `review()` rekent eerste adres, laatste adres en aantal nu uit in plaats van
|
|
ze op te sommen. Antwoord binnen 0,05 seconde bij elk prefix.
|
|
- `suggest_range()` had hetzelfde probleem: die somde alle /28-blokken op, wat
|
|
bij een `/8` ruim een miljoen blokken zijn. Rekent nu van achteren naar voren.
|
|
- Waarschuwing bij een bereik van meer dan 4096 adressen, want dat is vrijwel
|
|
altijd een typefout in het prefix.
|
|
- Ook `.env` van de deploy-map werd bij elke deploy gewist door `rsync --delete`,
|
|
omdat het bestand in `.gitignore` staat en dus niet in de checkout zit. Daardoor
|
|
raakte je `BIND` telkens kwijt. `--exclude='.env'` toegevoegd.
|
|
- Nieuw `.env.example` met alle instellingen bij elkaar en uitleg per sleutel.
|
|
|
|
---
|
|
|
|
# v0.5.40-beta — Netwerken instellen zonder uitzoekwerk
|
|
|
|
## 🔍 Automatische detectie
|
|
|
|
Bij **Instellingen → Netwerken → Netwerk** toont Server Up nu bovenaan het
|
|
netwerk dat je server zelf gebruikt: interface, subnet, gateway en een
|
|
voorgestelde vrije IP-range. Eén klik vult het hele formulier.
|
|
|
|
De detectie start heel kort een container die de netwerknamespace van de host
|
|
deelt en leest daar de routetabel. Dat is nodig omdat Server Up in een eigen
|
|
namespace zit: de vorige versie las `/sys/class/net` binnen de container en
|
|
toonde daardoor de bridge-interface van de container zelf in plaats van de
|
|
netwerkkaart van de host — een lijstje dat er goed uitzag maar niet klopte.
|
|
|
|
Lukt detecteren niet (geen docker-socket, ouder image), dan staat er een nette
|
|
melding en vul je het als vanouds handmatig in.
|
|
|
|
## 💡 Live meedenken bij het invullen
|
|
|
|
Terwijl je typt controleert Server Up de combinatie en toont wat het oplevert:
|
|
*"14 adressen beschikbaar: 192.168.1.241 tot en met 192.168.1.254"*. Klopt er
|
|
iets niet, dan staat er in gewone taal bij waarom — een range buiten het subnet,
|
|
een gateway die je beter buiten het bereik kunt houden, of een range zo klein
|
|
dat er maar een paar stacks in passen.
|
|
|
|
Een knop stelt een vrij blok voor op basis van het subnet, met de gateway
|
|
ontweken.
|
|
|
|
## 📖 Uitleg waar je hem nodig hebt
|
|
|
|
In het formulier zit een uitklapbaar blok dat uitlegt hoe subnet, gateway,
|
|
IP-range en host-interface zich tot elkaar verhouden, met een concreet voorbeeld.
|
|
`docs/netwerken.md` heeft dezelfde uitleg met een schema van de adresverdeling,
|
|
een tabel met veelgebruikte ranges, en één punt dat er echt uit moet springen:
|
|
**het instellen van de IP-range in Server Up doet niets aan je router** — je moet
|
|
daar zelf het DHCP-bereik verkleinen, anders blijven dubbele adressen mogelijk.
|
|
|
|
---
|
|
|
|
# v0.5.30-beta — Rollen, app-store-filter en twee planningsfouten
|
|
|
|
## 👥 Rollen per gebruiker
|
|
|
|
Tot nu toe had elk account volledige toegang. Nu drie rollen:
|
|
|
|
| Rol | Mag |
|
|
|---|---|
|
|
| **Beheerder** | alles |
|
|
| **Operator** | stacks, containers en backups beheren — niet de instellingen, gebruikers, repo's, netwerken of modules |
|
|
| **Alleen lezen** | alleen bekijken |
|
|
|
|
- Afgedwongen in de `before_request`-guard, niet alleen in de interface.
|
|
- Je eigen wachtwoord wijzigen mag iedereen, ongeacht rol.
|
|
- De laatste beheerder kan niet gedegradeerd of verwijderd worden.
|
|
- Wie via de reverse proxy binnenkomt zonder eigen account krijgt de rol uit
|
|
`AUTH.proxy_role`; bestaat er wél een lokaal account met die naam, dan wint
|
|
dat account.
|
|
- Accounts van vóór deze versie hebben geen rol en gelden als beheerder.
|
|
|
|
## 🔒 Rechtenescalatie verholpen
|
|
|
|
Bij het wijzigen van een wachtwoord werd het hele gebruikersrecord vervangen,
|
|
waardoor het `role`-veld wegviel. Omdat een ontbrekende rol als beheerder geldt
|
|
(nodig voor bestaande accounts), kon **elke operator of viewer zichzelf tot
|
|
beheerder promoveren door zijn eigen wachtwoord te wijzigen.** Gevonden bij het
|
|
naspelen van de rollenflow; de rol blijft nu behouden en een test dekt het af.
|
|
|
|
## ⏰ Geplande backups draaiden nooit
|
|
|
|
De scheduler stempelde ook taken af die zichzelf hadden overgeslagen. De
|
|
backup-taak bewaakt zelf of het het ingestelde uur is, dus die werd afgestempeld
|
|
op het moment van de eerste tick — waarna het volgende moment 24 uur later op
|
|
precies dat verkeerde tijdstip viel. Resultaat: de geplande backup kwam nooit
|
|
aan de beurt.
|
|
|
|
Een taak stempelt nu alleen af als hij `True` teruggeeft. De backup-taak draait
|
|
daardoor op een kort interval en bepaalt zelf wanneer het zover is, zodat een
|
|
gewijzigde planning ook meteen werkt zonder herstart. Voor wekelijkse backups is
|
|
`BACKUP_SCHEDULE_DAY` toegevoegd.
|
|
|
|
## 🔎 Zoeken en filteren in de app store
|
|
|
|
Zoekveld over naam, omschrijving en tags, plus klikbare tagfilters (de veertien
|
|
meestgebruikte, op frequentie gesorteerd). Repo's zonder treffers vallen weg.
|
|
|
|
## 🔧 Overig
|
|
|
|
- Opstartcontrole op de meegeleverde front-end-bestanden. Mislukt het downloaden
|
|
tijdens de image-build, dan laadde de interface zonder opmaak terwijl de
|
|
server prima leek te draaien; nu staat er een duidelijke melding in het log.
|
|
- 227 tests.
|
|
|
|
---
|
|
|
|
# v0.5.20-beta — Vertalingen, SSO-scherm, complete backups en app-updates
|
|
|
|
## 🌍 Vertalingen en SSO
|
|
|
|
- De schermen uit v0.5.x (login, Beveiliging, Netwerken, Updates,
|
|
containerpaneel) gebruikten harde Nederlandse teksten terwijl de rest van de
|
|
interface via `t()` loopt. Op Engels gaf dat een mengelmoes. Nu volledig
|
|
vertaald: 208 sleutels in `nl` en `en`.
|
|
- `t()` ondersteunt plaatshouders: `t('port_taken', {port: 8080})`. Zo blijven
|
|
zinnen heel in plaats van in losse stukjes geknipt.
|
|
- Nieuw instelscherm voor **reverse-proxy-SSO** onder Instellingen →
|
|
Beveiliging: modus lokaal/proxy/beide, identiteitsheader en de vertrouwde
|
|
proxy-adressen. De backend bestond al maar was alleen met `curl` te bereiken.
|
|
- Nieuwe test bewaakt dat `nl` en `en` dezelfde sleutels houden, dat de
|
|
plaatshouders in beide talen gelijk zijn, en dat de interface geen sleutels
|
|
gebruikt die nergens gedefinieerd staan.
|
|
|
|
## 💾 Backups compleet
|
|
|
|
Backup was één `tar`-commando waarvan de returncode genegeerd werd — een
|
|
mislukte backup gold als succes, en terugzetten kon alleen met de hand.
|
|
|
|
- **Terugzetten** met één klik: stack stoppen, huidige map opzij, uitpakken,
|
|
starten. Mislukt het uitpakken, dan komt de oude situatie terug.
|
|
- **Bewaarbeleid**: aantal per stack en/of maximale leeftijd. De nieuwste
|
|
backup van een stack blijft altijd staan.
|
|
- **Geplande backups**, dagelijks of wekelijks, via een eigen planner in de
|
|
applicatie (geen cron). Een gemiste ronde loopt bij de eerstvolgende
|
|
gelegenheid alsnog.
|
|
- **Automatisch een backup vóór het bijwerken of verwijderen** van een stack.
|
|
Mislukt die, dan gaat de actie door — anders kun je een kapotte stack niet
|
|
meer opruimen.
|
|
- Uitpakken gebeurt met `tarfile` en `filter="data"`: absolute paden en
|
|
`..`-ingangen worden geweigerd. Met een kaal `tar xzf` kon een geprepareerd
|
|
archief buiten de stackmap schrijven.
|
|
- Backups binnen dezelfde seconde overschreven elkaar; namen krijgen nu een
|
|
teller.
|
|
- `docs/backups.md` legt uit wat er wél en niet in zit — de compose- en
|
|
`.env`-bestanden, **niet** de Docker-volumes met de eigenlijke appdata.
|
|
|
|
## 📦 Updates per app
|
|
|
|
- Server Up controleert nu ook of er nieuwere images zijn voor de
|
|
geïnstalleerde stacks, met een badge op de stackkaart en een knop om te
|
|
controleren. Bijwerken doet de bestaande update-knop.
|
|
- De vergelijking loopt via de Registry API v2 (`Docker-Content-Digest`), niet
|
|
via `docker manifest inspect`: dat laatste geeft per platform een aparte
|
|
digest terug terwijl `RepoDigests` de digest van de manifest-list bevat, wat
|
|
bij elk multi-arch image permanent "update beschikbaar" zou opleveren.
|
|
- Drie statussen per service — `update`, `current` en `unknown`. Een lokaal
|
|
gebouwd image, een nog niet gepulld image of een onbereikbare registry levert
|
|
`unknown` op en dus géén badge, zodat er nooit ten onrechte een update wordt
|
|
gemeld.
|
|
- Dagelijkse achtergrondcheck via dezelfde planner; resultaten 6 uur gecached.
|
|
|
|
---
|
|
|
|
# v0.5.10-beta — Update-systeem met kanalen en één-klik bijwerken
|
|
|
|
## 🔄 Kanalen
|
|
|
|
Server Up kent nu twee update-kanalen in plaats van een vinkje "pre-releases
|
|
meenemen":
|
|
|
|
- **stable** — alleen echte releases (`v0.5.10`)
|
|
- **beta** — ook pre-releases (`v0.5.10-beta1`), die `release.yml` automatisch
|
|
als zodanig markeert bij een tag met een streepje
|
|
|
|
Een release telt hoger dan zijn eigen beta (`0.5.10-beta1` < `0.5.10`), dus wie
|
|
op beta zit krijgt de definitieve versie alsnog aangeboden. De oude instelling
|
|
`UPDATE_INCLUDE_PRERELEASE` migreert automatisch naar het beta-kanaal.
|
|
|
|
## ⬇️ Bijwerken vanuit de interface
|
|
|
|
Nieuw: **Nu bijwerken** haalt het image uit je Forgejo container-registry en
|
|
vervangt de eigen container.
|
|
|
|
- Omdat een container zichzelf niet kan hercreëren, doet Server Up alleen het
|
|
voorwerk (image ophalen, `SU_TAG` wegschrijven) en laat het de hercreatie over
|
|
aan een korte helper-container die op het nieuwe image draait — dat bevat de
|
|
docker- en compose-CLI al.
|
|
- De deploy-map wordt uitgelezen uit de compose-labels van de eigen container,
|
|
niet geraden. Ontbreken die labels, draait de container niet vanaf een
|
|
registry-image, of is de docker-socket er niet, dan meldt de interface
|
|
precies waaróm bijwerken niet kan in plaats van iets te proberen.
|
|
- De vorige tag wordt onthouden, met een **terugrolknop** in de instellingen.
|
|
- Voortgang van de `docker pull` loopt via het bestaande job-logvenster; daarna
|
|
pollt de browser `/healthz` tot de nieuwe versie leeft.
|
|
|
|
## 🔧 Overig
|
|
|
|
- Update-check wordt een uur gecached; **Controleren** forceert een verse check.
|
|
Eerder deed elke paginalading een netwerkverzoek.
|
|
- Laatst-gecontroleerd-tijdstip zichtbaar in de interface.
|
|
- Registry-inloggegevens instelbaar voor een privé registry. Het token wordt net
|
|
als de git-tokens nooit teruggegeven door de API (alleen een `has_`-vlag) en
|
|
leeg laten betekent "ongewijzigd".
|
|
- `docker-compose.yml` gebruikt `${SU_IMAGE:-server-up}:${SU_TAG:-latest}`, zodat
|
|
image en tag los instelbaar zijn. Zonder `SU_IMAGE` blijft alles werken zoals
|
|
voorheen (lokaal bouwen).
|
|
- `deploy-prod.yml` bouwt én pusht het image in dezelfde job wanneer `SU_IMAGE`
|
|
ingesteld is. Bewust niet als aparte workflow: bij één runner zou de deploy
|
|
wachten op een build die zelf nog in de wachtrij staat.
|
|
- `build.yml` is nu alleen handmatig, voor het herbouwen van een specifieke tag.
|
|
- `docs/updates.md` toegevoegd: hoe het werkt, de complete Forgejo-instelling
|
|
(registry, tokens, variables, secrets, runners), de release-procedure voor
|
|
zowel stable als beta, terugrollen en een probleemoplostabel.
|
|
|
|
---
|
|
|
|
# v0.5.00-beta — Authenticatie, beveiliging en eigen IP-adressen
|
|
|
|
> **Let op bij het bijwerken.** Server Up heeft nu een login. Open na het
|
|
> bijwerken meteen de webinterface en maak een beheerdersaccount aan — zolang
|
|
> dat niet gebeurd is, kan iedereen die de pagina bereikt het account claimen.
|
|
> De poort wordt voortaan standaard op `127.0.0.1` gebonden; zet `BIND=0.0.0.0`
|
|
> in je `.env` als je er van buiten de server bij moet (liefst achter een
|
|
> reverse proxy met TLS — zie `docs/beveiliging.md`).
|
|
|
|
## 🔐 Authenticatie
|
|
|
|
Tot nu toe was elke `/api/*`-route open. Omdat Server Up de docker-socket als
|
|
root gebruikt, betekende dat: wie de poort kon bereiken, had root op de host.
|
|
|
|
- Lokale accounts met scrypt-gehashte wachtwoorden, sessiecookie
|
|
(`HttpOnly`, `SameSite=Strict`) en lockout na vijf mislukte pogingen.
|
|
- Optionele SSO via een reverse-proxy-header (Authelia/Authentik/Cloudflare
|
|
Access). De header wordt alleen vertrouwd vanaf een geconfigureerd proxy-IP.
|
|
- Loginscherm en eerste-account-setup in de interface; gebruikersbeheer en
|
|
wachtwoord wijzigen onder Instellingen → Beveiliging.
|
|
|
|
## 🛡️ Beveiligingsfixes
|
|
|
|
- **CSRF**: elke mutatie vereist een `X-CSRF-Token`-header. Routes die de
|
|
toestand wijzigen accepteren geen `GET` meer — `/api/docker/restart` was
|
|
eerder met een `<img>`-tag vanaf een willekeurige website te triggeren.
|
|
- **Path traversal**: `/api/store/install` controleerde de instantienaam niet;
|
|
`"instance": "../../…"` schreef buiten de library. Alle stack-, instantie- en
|
|
repo-namen lopen nu door één `safe_name()`-validatie.
|
|
- **Tokenlek**: git-tokens werden teruggegeven door `/api/repos` en
|
|
`/api/settings`. Die zijn vervangen door een `has_token`-vlag; opslaan met een
|
|
leeg veld wist het bestaande token niet meer.
|
|
- **Git-URL's**: alleen `http(s)://`, `ssh://` en `git@host:pad`. Git's
|
|
`ext::`-transport voert een shell-commando uit en wordt nu geweigerd.
|
|
- **Templates** renderen in een Jinja2-sandbox (server-side template injection).
|
|
- **SSH**: host-keys worden geverifieerd (`accept-new` + `/data/known_hosts`);
|
|
eerder stond `StrictHostKeyChecking=no`, waarmee elke MITM onzichtbaar was.
|
|
- **Modules**: repo's worden niet meer automatisch bij elke start gepulld
|
|
(`AUTO_SYNC_ON_BOOT`, standaard uit) en kunnen per repo op een commit worden
|
|
vastgezet.
|
|
- Productie-WSGI-server (waitress) i.p.v. de Flask-ontwikkelserver, limiet op
|
|
request-grootte, `ProxyFix`, en CSP/`X-Frame-Options`/`nosniff`/
|
|
`Referrer-Policy`-headers.
|
|
- Tailwind, Alpine en htmx worden meegeleverd in plaats van vanaf een CDN
|
|
geladen; Google Fonts is eruit. De interface werkt nu ook offline.
|
|
- `config.json` en de sleutel staan op 0600.
|
|
|
|
## 🌐 Stacks met een eigen IP-adres
|
|
|
|
Nieuw: geef een stack een eigen adres in je LAN in plaats van poorten op de host
|
|
(macvlan/ipvlan). Geen poortconflicten meer, apps op hun eigen standaardpoort, en
|
|
je kunt per app firewallen.
|
|
|
|
- Netwerkbeheer onder Instellingen → Netwerken (driver, host-interface, subnet,
|
|
gateway, optionele IP-range).
|
|
- Bij het installeren kies je "Poorten op de host" of een netwerk; Server Up
|
|
stelt het eerstvolgende vrije adres voor en houdt toegekende adressen vast.
|
|
- Het gerenderde compose-bestand wordt automatisch omgezet: poortmappings eruit,
|
|
netwerk met `ipv4_address` erin. De templates in `apps/` blijven ongewijzigd.
|
|
- Uitleg en valkuilen (waaronder de shim-interface die de host nodig heeft om
|
|
zijn eigen macvlan-containers te bereiken) staan in `docs/netwerken.md`.
|
|
|
|
## 🧩 Beheer per container
|
|
|
|
De stackkaart klapt uit naar de losse containers: per container starten, stoppen,
|
|
herstarten, logs bekijken en live CPU-/geheugengebruik.
|
|
|
|
## 📦 Veiliger installeren
|
|
|
|
- Poortvelden krijgen een vrij poortnummer voorgesteld — `next_free_port()`
|
|
bestond al maar werd nergens gebruikt. Bezette poorten worden gemeld.
|
|
- Velden voor tokens en wachtwoorden krijgen een genereerknop.
|
|
- Compose wordt gevalideerd (`docker compose config`) vóór het wegschrijven, dus
|
|
een typefout in de editor maakt een draaiende stack niet meer onstartbaar.
|
|
|
|
## 🔧 Overig
|
|
|
|
- Testsuite met pytest (112 tests), ook als stap in beide deploy-workflows.
|
|
- Audit-log gebruikt één gedeelde SQLite-verbinding — elke job lekte eerder een
|
|
file descriptor. Joblogs worden afgekapt op 2000 regels.
|
|
- Het `VERSION`-bestand is de enige bron voor het versienummer.
|
|
- Lichte `/healthz` voor de healthcheck in plaats van `docker info`.
|
|
- `fix-config.sh` verwijderd: bevatte een hardgecodeerd intern IP en
|
|
overschreef de configuratie van de gebruiker.
|
|
|
|
---
|
|
|
|
# v0.4.60 — Tweecijferig patch-nummer
|
|
|
|
## Versiebeleid vanaf v0.4.60
|
|
|
|
Het patch-deel (laatste cijfer) gebruikt nu twee cijfers en loopt in tientallen:
|
|
`0.4.60`, `0.4.61`, … `0.4.69`, `0.4.70`. Blijft semver-compatibel (het deel
|
|
wordt als geheel getal vergeleken, dus `0.4.60` > `0.4.6`).
|
|
|
|
---
|
|
|
|
# v0.4.6 — Kaal versienummer op alle builds
|
|
|
|
## Wijziging in v0.4.6
|
|
|
|
De deploy-workflows tonen nu overal het kale versienummer uit het `VERSION`-
|
|
bestand (of de tagnaam), zonder `-dev`/`-rc.<sha>`-suffix. Eenvoudiger te lezen;
|
|
bump bij elke wijziging gewoon `VERSION`.
|
|
|
|
---
|
|
|
|
# v0.4.5 — Releases & in-app update-check
|
|
|
|
## Nieuw in v0.4.5
|
|
|
|
### 🏷️ Automatische releases bij een tag
|
|
Push je een `v*`-tag, dan maakt de nieuwe `release.yml`-workflow automatisch een
|
|
Forgejo-**Release** aan met notes uit de bijbehorende `CHANGELOG.md`-sectie plus
|
|
een commit-overzicht sinds de vorige tag. Pre-release tags (bv. `v0.8.4-beta1`)
|
|
worden als pre-release gemarkeerd. Zo krijg je een Releases-pagina met duidelijke
|
|
changelog per versie, vergelijkbaar met GitHub Releases.
|
|
|
|
### 🔔 In-app "update beschikbaar"
|
|
Server Up vergelijkt de draaiende versie met de laatste release via de Forgejo/
|
|
GitHub Releases-API (semver-vergelijking, pre-releases optioneel). Is er een
|
|
nieuwere versie, dan verschijnt een melding in de topbar en een blok in
|
|
Instellingen → Updates met versie, release-notes en een link. Instelbaar via
|
|
`UPDATE_API_URL` (of env `SU_UPDATE_API`) en de optie "pre-releases meenemen".
|
|
|
|
### 🔖 Versiebeleid
|
|
Bump bij elke wijziging het centrale `VERSION`-bestand; tags zijn de bron voor
|
|
release-versies (`vX.Y.Z`, of `-beta`/`-rc` voor pre-releases).
|
|
|
|
---
|
|
|
|
# v0.4.4 — Nette versienummers op alle builds
|
|
|
|
## Nieuw in v0.4.4
|
|
|
|
Centraal `VERSION`-bestand (semver) is nu de bron voor het versienummer. De
|
|
deploy-workflows lezen het en bouwen:
|
|
|
|
- tag `v0.4.4` → `0.4.4` (productie, toont `v0.4.4`)
|
|
- push naar `main` → `0.4.4-rc.<sha>`
|
|
- push naar `dev` → `0.4.4-dev.<sha>`
|
|
|
|
Zo zie je voortaan het échte versienummer in de topbar i.p.v. alleen de
|
|
git-SHA (`vdev-1eab7c07`). Bump bij elke wijziging alleen nog `VERSION` (en voor
|
|
de zekerheid de fallback in `app.py`/`index.html` voor lokale runs).
|
|
|
|
---
|
|
|
|
# v0.4.3 — Auto-logo's legacy-apps + fix lege Docker Images
|
|
|
|
## Nieuw / fixes in v0.4.3
|
|
|
|
### 🖼️ Automatische logo's voor legacy-apps
|
|
Legacy-apps (eigen `app.json`/`stack.json`-stacks) krijgen nu automatisch een
|
|
logo via de dashboard-icons CDN, afgeleid uit de app-naam (bv. "Nextcloud" →
|
|
`nextcloud.png`). Een expliciete logo-URL in de metadata wint; bestaat het
|
|
geraden icoon niet, dan valt de UI terug op het emoji-icoon. Geldt voor zowel
|
|
de App Store als geïnstalleerde stacks.
|
|
|
|
### 🐛 Fix: Docker Images-pagina was leeg
|
|
De afbeeldingenlijst gebruikte `:key="img.id"`, maar meerdere tags kunnen
|
|
dezelfde image-ID delen → dubbele Alpine-keys waardoor de tabel niet rendert
|
|
(en de "geen images"-melding ook niet, want er waren wél images). De `x-for`
|
|
gebruikt nu de index als key.
|
|
|
|
---
|
|
|
|
# v0.4.2 — App-logo's bij stacks
|
|
|
|
## Nieuw in v0.4.2
|
|
|
|
Geïnstalleerde stacks tonen nu het app-logo (of een emoji-icoon als fallback),
|
|
zowel op het dashboard als op de Stacks-pagina. Bij installatie wordt het
|
|
logo/icoon van de bron-app opgeslagen in `.serverup.json` in de stack-map.
|
|
Bestaande installaties krijgen hun logo via een naam-match met de App Store,
|
|
dus ze hoeven niet opnieuw geïnstalleerd te worden. De store toonde al logo's
|
|
voor boilerplate-apps (via de selfhst/dashboard-icons CDN).
|
|
|
|
---
|
|
|
|
# v0.4.1 — Fix: styling werd niet toegepast
|
|
|
|
## Fix bovenop v0.4.0
|
|
|
|
De volledige Tailwind-stylesheet faalde stil omdat `.modal` via `@apply` de
|
|
eigen CSS-animatieklasse `anim` toepaste. Tailwind's `@apply` accepteert alleen
|
|
Tailwind-utilities, geen losse CSS-klassen, waardoor de hele Play-CDN-compilatie
|
|
afbrak en de pagina ongestyled (kaal HTML) werd geladen. De animatie staat nu
|
|
als gewone CSS-regel (`.anim, .modal { animation: … }`) los van `@apply`.
|
|
|
|
---
|
|
|
|
# v0.4.0 — Volledig nieuw UI-ontwerp (Modern SaaS)
|
|
|
|
## Nieuw in v0.4.0
|
|
|
|
### 🎨 Compleet herontworpen interface
|
|
Volledig nieuw, licht en ruim "Modern SaaS"-ontwerp (Inter-font, indigo accent,
|
|
zachte schaduwen, ronde 2xl-kaarten). Nieuwe app-shell: verticale sidebar met
|
|
merk-header, gegroepeerde navigatie met actieve indicator en live status-footer;
|
|
slanke sticky topbar met dynamische paginatitel en status-chips. Dashboard,
|
|
stacks, app store, images-/audittabellen, instellingen, modals, wizard, toasts
|
|
en het log-paneel zijn allemaal opnieuw vormgegeven. Inklapbaar menu en grote
|
|
touch-targets blijven behouden; volledig mobielvriendelijk.
|
|
|
|
### 🌗 Thema volgt systeemvoorkeur
|
|
Standaard volgt het thema de OS-voorkeur (licht/donker) en reageert live op
|
|
wijzigingen. Handmatige override via Auto / Light / Dark in Instellingen.
|
|
|
|
---
|
|
|
|
# v0.3.1 — UI-restyle + taalmodule (add-on)
|
|
|
|
## Nieuw in v0.3.1
|
|
|
|
### 🎨 Grondige UI-restyle
|
|
Grotere, touch-vriendelijke knoppen (min. 44px), ruimere spacing, grotere
|
|
typografie en kaarten. Layout gecentreerd met max-breedte voor meer lucht op
|
|
grote schermen. Volledig mobielvriendelijk.
|
|
|
|
### 📐 Inklapbaar menu (ook op desktop)
|
|
De hamburger klapt de sidebar nu ook op desktop in/uit; voorkeur wordt onthouden
|
|
(`localStorage`), hoofdinhoud en log-paneel schuiven mee. Op mobiel een
|
|
tap-to-close overlay.
|
|
|
|
### 🌐 Taalmodule als add-on
|
|
Nieuwe sectie in Instellingen → "Taalmodule": talen toevoegen, bewerken,
|
|
verwijderen en ingebouwde talen (NL/EN) dupliceren als startpunt. Editor toont
|
|
per sleutel de Engelse referentie met zoekfilter. Backend-endpoints:
|
|
`POST/DELETE /api/i18n`, `GET /api/i18n/keys`, `GET /api/i18n/<code>/raw`.
|
|
Toegevoegde talen komen als JSON in `translations/` en zijn direct beschikbaar.
|
|
|
|
---
|
|
|
|
# v0.3.01 — Boilerplates fixes + git-driven versioning
|
|
|
|
## Fixes bovenop v0.3.0
|
|
|
|
### 🔁 Auto-migratie van default-repos voor upgraders
|
|
Bestaande installaties (vanaf v0.2.x) hadden de Boilerplates-repo niet zichtbaar
|
|
in de App Store omdat hun `config.json` in de `su-data` volume al bestond en de
|
|
nieuwe `DEFAULTS["APP_REPOS"]` daardoor werd overschreven.
|
|
|
|
`core/__init__.py` `load()` doet nu een eenmalige migratie: ontbrekende
|
|
default-repos worden bij opstart aangevuld op basis van id, en gemarkeerd in
|
|
`MIGRATIONS_DONE: ["v0.3.0_default_repos"]`. Wordt direct gepersisteerd.
|
|
Verwijdert een gebruiker de Boilerplates-repo expliciet, dan komt-ie niet
|
|
automatisch terug.
|
|
|
|
### 🧹 YAML-poetsstap na boilerplate-render
|
|
Bij stacks waar de meeste optionele groepen uit staan (Authentik, Nextcloud,
|
|
etc.) liet de Jinja-render verlaten mapping-sleutels achter (`volumes:`,
|
|
`networks:`, etc. zonder kinderen). Docker-compose faalt daarop met *"block
|
|
sequence entries are not allowed in this context"*.
|
|
|
|
`core/boilerplates.py` `_tidy()` heeft nu een `_drop_empty_mappings()` substep
|
|
die in meerdere passes mapping-sleutels verwijdert die alleen worden gevolgd
|
|
door whitespace/commentaar of een sibling op gelijke/lagere indent. Werkt in
|
|
cascade.
|
|
|
|
### 🏷️ Versie komt nu uit git
|
|
`Dockerfile` accepteert `ARG SU_VERSION=dev` en bakt die in `ENV SU_VERSION` +
|
|
OCI image-label. Met `docker build --build-arg SU_VERSION=$(git describe ...)`
|
|
weet het image zijn eigen versie. De Server Up UI toont automatisch de juiste
|
|
waarde, ongeacht wat de productie-compose meegeeft.
|
|
|
|
Forgejo Actions kan een tag-push automatisch verwerken — zie
|
|
`server-up-deploy/README.md`.
|
|
|
|
## Migratie vanaf v0.3.0
|
|
```bash
|
|
docker compose build --no-cache
|
|
docker compose up -d
|
|
```
|
|
|
|
---
|
|
|
|
# v0.3.0 — UI rebuild + Boilerplates support
|
|
|
|
## Hoogtepunten
|
|
|
|
### 🎨 Nieuwe UI (Tailwind + Alpine + HTMX)
|
|
- `templates/index.html` is volledig herschreven. De handgeschreven CSS
|
|
(`--bg/--s1/...` variabelen, ad-hoc grid-classes) is vervangen door
|
|
Tailwind utility-classes met een gematchte donker/licht-palette.
|
|
- Statebeheer via Alpine.js: één `app()` component bovenop het hele document,
|
|
geen `$=document.getElementById`-spaghetti meer.
|
|
- HTMX is geladen voor toekomstige server-rendered partials. Het bestaande
|
|
fetch-RPC patroon blijft werken; HTMX kan progressief worden ingezet.
|
|
- Modals, toasts, terminal-overlay en first-run wizard zitten allemaal in
|
|
één Alpine-state — geen losse globale variabelen meer.
|
|
- Mobiele sidebar gedraagt zich nu correct (slide-in i.p.v. layout-flip).
|
|
|
|
### 🧩 ChristianLempa Boilerplates ondersteund
|
|
Server Up herkent nu twee stack-formaten naast elkaar:
|
|
|
|
| Formaat | Detectie | Bron |
|
|
|---|---|---|
|
|
| **Compose** (origineel) | `compose.yml` / `docker-compose.yml` (+ optioneel `stack.json`) | bes-r/server-up |
|
|
| **Boilerplate** (nieuw) | `template.json` + `files/` | ChristianLempa/boilerplates-library |
|
|
|
|
Nieuw bestand `app/core/boilerplates.py`:
|
|
- `is_boilerplate(d)` — detectie
|
|
- `metadata(d)` — converteert `template.json["metadata"]` (incl. selfhst-icons) naar Server-Up formaat
|
|
- `fields(d)` — flattened variable-schema voor de install-modal
|
|
- `render_to_dir(src, dest, values)` — rendert `files/*.yaml` met de Jinja-achtige
|
|
`<< var >>` + `<%- if expr %>` syntax die de boilerplates gebruiken (Jinja2 met
|
|
custom delimiters). Niet-tekst bestanden worden verbatim gekopieerd.
|
|
|
|
`app/core/git.py` → `_scan_compose_dirs` herkent beide formaten en zet
|
|
`format: "boilerplate"` in de stack-entry zodat de UI er een badge bij kan tonen.
|
|
|
|
`app/app.py`:
|
|
- `_find_stack_src` accepteert ook boilerplate-mappen.
|
|
- `POST /api/store/preview` retourneert voor boilerplates het variabelen-schema
|
|
(`fields`) plus een gerenderde preview met defaults.
|
|
- `POST /api/store/install` met body `{values: {...}}` rendert de templates
|
|
voor je voordat de stack gestart wordt.
|
|
|
|
### ⚙️ Default-repos
|
|
Een nieuwe Server Up komt nu uit de doos met twee app-repositories:
|
|
1. `bes-r/server-up` — eigen stacks, submap `apps`
|
|
2. `ChristianLempa/boilerplates-library` — community templates, submap `compose`
|
|
|
|
### 📦 Versie / Dockerfile
|
|
- `SU_VERSION` = `0.3.0` in `Dockerfile` en `docker-compose.yml`
|
|
- `requirements.txt`: Jinja2 expliciet toegevoegd (was al een Flask-dep)
|
|
|
|
## Migratie vanaf v0.2.29
|
|
- Build opnieuw: `docker compose up -d --build --no-cache`
|
|
- Bestaande stacks blijven werken (legacy formaat is intact).
|
|
- De Boilerplates-repo wordt automatisch toegevoegd voor verse installs.
|
|
Bestaande gebruikers kunnen de repo handmatig toevoegen via
|
|
Instellingen → Git Repositories met submap `compose`.
|
|
|
|
## Bekende beperkingen
|
|
- Boilerplate-templates met onbekende custom-filters of complexe Ansible-style
|
|
conditionals kunnen falen — de fout verschijnt in het terminal-paneel.
|
|
- `volumes:` blokken die conditioneel zijn (`<%- if volume_mode == 'local' %>`)
|
|
werken; complexere render-logica (loops over services) is nog niet getest.
|
|
- HTMX is geladen maar de meeste interacties draaien nog op fetch-RPC. Verdere
|
|
migratie naar server-rendered partials kan stapsgewijs in volgende releases.
|