server-up/CHANGELOG.md
Ramon 8b29553a71
Some checks failed
Deploy server-up (dev) / deploy (push) Failing after 3s
v0.5.00-beta - containerbeheer, eigen IP-adressen, veiliger installeren
- Beheer per container: de stackkaart klapt uit naar de losse containers, met
  start/stop/herstart, logs en live CPU-/geheugengebruik per container. De
  containernaam wordt getoetst aan compose_ps van díé stack, zodat de route
  geen willekeurige container op de host kan raken.
- Stacks met een eigen IP-adres (macvlan/ipvlan): netwerkbeheer onder
  Instellingen → Netwerken, netwerkkeuze in de installatiemodal met voorstel
  voor het eerstvolgende vrije adres, en automatische omzetting van het
  gerenderde compose-bestand (poortmappings eruit, ipv4_address erin). De
  templates in apps/ blijven ongewijzigd.
- Toegekende IP's worden vastgehouden in .serverup.json en getoond op de
  stackkaart, zodat een volgende installatie ze niet opnieuw uitdeelt.
- Vrije poort voorstellen bij installeren: next_free_port() bestond al maar
  werd nergens gebruikt. Bezette poorten worden in de UI gemeld.
- Genereerknop voor velden die op een geheim wijzen (token/password/secret),
  lokaal gegenereerd via crypto.getRandomValues.
- Compose valideren met `docker compose config` vóór het wegschrijven, zowel
  bij de editor als na het renderen bij installatie. Ontbreekt de compose-CLI,
  dan blokkeert dat een installatie niet.
- Uitloggen in de zijbalk; gebruikersbeheer en wachtwoord wijzigen onder
  Instellingen → Beveiliging.
- docs/netwerken.md (incl. de shim-interface die de host nodig heeft om zijn
  eigen macvlan-containers te bereiken) en docs/beveiliging.md toegevoegd.
- CHANGELOG bijgewerkt; testsuite uitgebreid naar 112 tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C7oLCRYzY5ixJ5Sv8Y8EFb
2026-07-26 14:51:32 +02:00

15 KiB

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.40.4.4 (productie, toont v0.4.4)
  • push naar main0.4.4-rc.<sha>
  • push naar dev0.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

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.