# 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 ``-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.`-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.` - push naar `dev` → `0.4.4-dev.` 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//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.