add_shared_network hing elke service van een stack aan het gedeelde netwerk.
Eén druk op 'koppelen' maakte daarmee de database van die app bereikbaar voor
elke andere gekoppelde app — en niet elk sjabloon zet daar een wachtwoord op.
- Standaard gaan alleen services mee die geen database, cache of zoekindex
zijn; brokers als mosquitto en rabbitmq blijven wel deelbaar.
- Per onderdeel te kiezen in de stap 'Verbinden'; de keuze staat in
.serverup.json en geldt ook bij een volgende wijziging.
- mongodump/mongorestore sturen geen inloggegevens meer mee bij een database
zonder authenticatie; die dump mislukte altijd.
- Joblogs worden bewaard in SU_JOBS (standaard /data/jobs) en teruggelezen na
een herstart; een afgekapte taak meldt dat in plaats van 'unknown'.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H9Vcwu7owJZ3nj5dCf4VFT
- bij de installatie wordt gevraagd onder welk account Server Up draait: een
nieuw systeemaccount 'serverup', het account waarmee je werkt, een bestaand
account, of root zoals voorheen (--user NAAM slaat de vraag over)
- nieuw docker-entrypoint.sh: start als root, zet /data, stacks en backups
klaar, en zakt met setpriv af naar SU_UID:SU_GID met de capabilities die
nodig blijven (chown, dac_override, fowner - alle drie al in Docker's
standaardset)
- appdata blijft daarbij bewust ongemoeid; die mappen zijn van de apps zelf
- de gid van de docker-socket wordt uit de socket zelf gelezen, zodat het
account niet in de docker-groep hoeft (dat zou root op de host geven)
- installatieformulier vult PUID/PGID met de ids waaronder Server Up draait in
plaats van de 1000 die 44 sjablonen blind noemen
- een onleesbaar bestand laat de rest van de backup niet meer sneuvelen; wat
ontbreekt komt in het log en in de metadata (skipped)
- terugzetten herstelt het eigenaarschap van appdata, dat tarfile met
filter="data" laat vallen
- CI controleert in een echte container dat setpriv bestaat, dat er wordt
afgezakt, dat de socket-gid meekomt, dat /data schrijfbaar is en dat SU_UID=0
root laat blijven
- SU_UID=0 in .env is de ontsnappingsklep naar het oude gedrag
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q9eqpADJSRs49SoGGr4NAy
- LIBRARY_DIR, DATA_DIR en BACKUP_DIR worden afgeleid van BASE_DIR in plaats
van hard op /opt/serverup te staan
- docker-compose geeft BASE_DIR nu ook aan de container door; die stond alleen
in de mount, dus de app bleef /opt/serverup voorstellen bij een /srv-mount
- het installatieformulier vult appdata_dir met de ingestelde DATA_DIR, zodat
alle 286 sjablonen de juiste map voorstellen
- Instellingen → Paden heeft een hoofdmap met afgeleide submappen, een
kopieerknop per pad en "Alles overnemen"
- nieuw GET /api/paths/check: is het pad schrijfbaar en binnen de gemounte
BASE_DIR, met de .env-regel als dat niet zo is
- nieuw POST /api/paths/move: stacks stoppen, kopiëren, controleren, paden in
compose/.env/metadata omschrijven, stacks starten en pas dán het oude
opruimen
- jobs.voortgang() plus een voortgangsbalk boven het terminallog
- core/paden.py met meten, bereikbaarheid, verhuizen en omschrijven
- docs/installeren.md en .env.example beschrijven BASE_DIR als de manier om
alles te verplaatsen
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q9eqpADJSRs49SoGGr4NAy
BIND bleef niet staan. Oorzaak: docker-compose.yml staat in Git, dus rsync zet
dat bestand bij elke deploy terug; een wijziging daarin op de server houdt het
nooit. De juiste plek is .env ernaast, maar dat bestand bevatte na een deploy
alleen een kale SU_TAG-regel en was daarmee niet vindbaar.
- Bestaat er nog geen .env, dan zet de deploy hem op vanuit .env.example, met
alle instellingen erin en uitleg per sleutel. Een bestaande .env blijft
ongemoeid (rsync slaat hem al over sinds 6d5453e).
- De deploy logt nu welke instellingen actief zijn, zodat je in de run-log ziet
wat er staat.
- Waarschuwing in docker-compose.yml zelf dat je BIND daar niet moet aanpassen
maar in .env. Dat bestand wordt toch elke deploy teruggezet, dus de tip staat
er altijd.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C7oLCRYzY5ixJ5Sv8Y8EFb
- 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
Server Up beheerde de Docker-daemon als root zonder enige vorm van
authenticatie: elke /api/*-route was gelijk aan root-toegang op de host.
- Authenticatie toegevoegd (core/auth.py): lokale accounts met scrypt-hash,
sessiecookie (HttpOnly, SameSite=Strict) en optionele trusted-proxy-header
SSO die alleen vanaf geconfigureerde proxy-IP's wordt vertrouwd.
- before_request-guard schermt alle API-routes af; loginscherm en
eerste-account-setup in de UI.
- CSRF-token verplicht op elke mutatie; GET-varianten van state-wijzigende
routes verwijderd (o.a. /api/docker/restart was via <img> te triggeren).
- Path traversal in /api/store/install gedicht; gedeelde safe_name()-validatie
voor stack-, instantie- en repo-namen.
- Git-tokens worden niet meer teruggegeven via /api/repos en /api/settings
(has_token-vlag); settings-PUT wist een bestaand token niet meer en kan AUTH
niet overschrijven.
- Git-URL's beperkt tot http(s)/ssh/scp-syntax; ext::-transport (voert een
shell-commando uit) en file:// worden geweigerd.
- Boilerplate-templates renderen in een SandboxedEnvironment (SSTI).
- Automatisch syncen van repo's bij boot standaard uit (AUTO_SYNC_ON_BOOT),
optionele commit-pinning per repo.
- Waitress in plaats van de Flask-ontwikkelserver, MAX_CONTENT_LENGTH,
ProxyFix, en CSP/X-Frame-Options/nosniff/Referrer-Policy headers.
- Front-end libraries (Tailwind, Alpine, htmx) lokaal meegeleverd i.p.v. CDN;
Google Fonts verwijderd. Werkt nu ook offline.
- SSH host-key-verificatie aan (accept-new + /data/known_hosts).
- Lichte /healthz voor de healthcheck i.p.v. `docker info`.
- config.json en secret.key met 0600-rechten.
- Poort standaard op 127.0.0.1 gebonden.
- Audit-log gebruikt één gedeelde SQLite-verbinding (fd-lek per job verholpen);
joblogs afgekapt op 2000 regels.
- VERSION-bestand is de enige bron voor het versienummer.
- pytest-suite toegevoegd (74 tests) en als stap in beide deploy-workflows.
- fix-config.sh verwijderd (hardgecodeerd intern IP, overschreef config).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C7oLCRYzY5ixJ5Sv8Y8EFb