- Update-kanalen stable/beta in plaats van het vinkje "pre-releases meenemen".
Stable ziet alleen releases, beta ook pre-releases; een release telt hoger
dan zijn eigen beta (0.5.10-beta1 < 0.5.10). UPDATE_INCLUDE_PRERELEASE
migreert automatisch naar het beta-kanaal.
- Nieuw core/selfupdate.py: image uit de registry ophalen, SU_TAG wegschrijven
en de eigen container laten hercreeren door een korte helper-container die op
het nieuwe image draait (bevat de docker- en compose-CLI al). Een container
kan zichzelf niet hercreeren, vandaar de helper.
- Deploy-map wordt uitgelezen uit de compose-labels van de eigen container.
Ontbreken die, draait de container niet vanaf een registry-image of is de
docker-socket er niet, dan meldt de UI waarom bijwerken niet kan.
- Vorige tag wordt onthouden; terugrolknop in de instellingen.
- Update-check een uur gecached, met geforceerde check via de knop; eerder deed
elke paginalading een netwerkverzoek. Laatst-gecontroleerd zichtbaar.
- Registry-inloggegevens instelbaar; het token komt net als de git-tokens nooit
terug via de API en leeg laten betekent ongewijzigd.
- docker-compose.yml gebruikt ${SU_IMAGE:-server-up}:${SU_TAG:-latest}; zonder
SU_IMAGE blijft lokaal bouwen werken zoals voorheen.
- deploy-prod.yml bouwt en pusht het image in dezelfde job wanneer SU_IMAGE
ingesteld is; build.yml is nu alleen handmatig. Bewust geen aparte
build-workflow op dezelfde tag: bij een runner met een job tegelijk zou de
deploy wachten op een build die zelf nog in de wachtrij staat.
- docs/updates.md: werking, complete Forgejo-instelling (registry, tokens,
variables, secrets, runners), release-procedure voor stable en beta,
terugrollen en probleemoplossing.
- Tests uitgebreid naar 148 (kanaallogica, cache, image-afleiding incl.
registry-poortnummers, tag-validatie, .env-schrijven, tokenlek).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C7oLCRYzY5ixJ5Sv8Y8EFb
18 KiB
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), dierelease.ymlautomatisch 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_TAGwegschrijven) 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 pullloopt via het bestaande job-logvenster; daarna pollt de browser/healthztot 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.ymlgebruikt${SU_IMAGE:-server-up}:${SU_TAG:-latest}, zodat image en tag los instelbaar zijn. ZonderSU_IMAGEblijft alles werken zoals voorheen (lokaal bouwen).deploy-prod.ymlbouwt én pusht het image in dezelfde job wanneerSU_IMAGEingesteld is. Bewust niet als aparte workflow: bij één runner zou de deploy wachten op een build die zelf nog in de wachtrij staat.build.ymlis nu alleen handmatig, voor het herbouwen van een specifieke tag.docs/updates.mdtoegevoegd: 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.1gebonden; zetBIND=0.0.0.0in je.envals je er van buiten de server bij moet (liefst achter een reverse proxy met TLS — ziedocs/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 geenGETmeer —/api/docker/restartwas eerder met een<img>-tag vanaf een willekeurige website te triggeren. - Path traversal:
/api/store/installcontroleerde de instantienaam niet;"instance": "../../…"schreef buiten de library. Alle stack-, instantie- en repo-namen lopen nu door éénsafe_name()-validatie. - Tokenlek: git-tokens werden teruggegeven door
/api/reposen/api/settings. Die zijn vervangen door eenhas_token-vlag; opslaan met een leeg veld wist het bestaande token niet meer. - Git-URL's: alleen
http(s)://,ssh://engit@host:pad. Git'sext::-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 stondStrictHostKeyChecking=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.jsonen 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_addresserin. De templates inapps/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
/healthzvoor de healthcheck in plaats vandocker info. fix-config.shverwijderd: 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, toontv0.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
docker compose build --no-cache
docker compose up -d
v0.3.0 — UI rebuild + Boilerplates support
Hoogtepunten
🎨 Nieuwe UI (Tailwind + Alpine + HTMX)
templates/index.htmlis 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)— detectiemetadata(d)— converteerttemplate.json["metadata"](incl. selfhst-icons) naar Server-Up formaatfields(d)— flattened variable-schema voor de install-modalrender_to_dir(src, dest, values)— rendertfiles/*.yamlmet 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_srcaccepteert ook boilerplate-mappen.POST /api/store/previewretourneert voor boilerplates het variabelen-schema (fields) plus een gerenderde preview met defaults.POST /api/store/installmet 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:
bes-r/server-up— eigen stacks, submapappsChristianLempa/boilerplates-library— community templates, submapcompose
📦 Versie / Dockerfile
SU_VERSION=0.3.0inDockerfileendocker-compose.ymlrequirements.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.