From 8e53b90615afff00b76817ebf669a2345d6f2613 Mon Sep 17 00:00:00 2001 From: Ramon Date: Mon, 27 Jul 2026 21:13:06 +0200 Subject: [PATCH] v0.7.40-beta - beheerdersaccount en bind meteen klaarzetten Het installatiescript kan nu allebei zelf regelen, zodat je na afloop niet meer naar de webinterface hoeft om een account te claimen en niet meer in .env hoeft te duiken om erbij te kunnen. Beheerdersaccount: - Op een terminal wordt gevraagd of je er meteen een wil, met naam en wachtwoord (twee keer, echo uit). - Automatisch via --admin NAAM plus --admin-password-file of SU_ADMIN_PASSWORD; zonder bron en zonder terminal maakt het script er zelf een van 24 tekens en toont die. - --admin-password weigert bewust: argumenten zijn zichtbaar in 'ps'. Het wachtwoord gaat via stdin naar curl, niet als argument. - Nieuw --create-admin voor een installatie die al draait. Bereikbaarheid: - Keuzemenu voor BIND (deze server / hele netwerk / eigen adres), met het gedetecteerde serveradres erbij. - Bij opnieuw installeren is de bestaande instelling het uitgangspunt, zodat enter je server niet ongemerkt terugzet op loopback. Opgeloste fouten: - Een bestaande .env bleef altijd ongemoeid, ook met --bind: de installatie leek te lukken terwijl de server op het oude adres bleef luisteren. - --update rekende met de standaardpoort in plaats van met wat er in .env staat, waardoor de wachtlus en het slotadres niet klopten. - --dry-run riep 'sudo docker' aan en vroeg dus om een wachtwoord terwijl het net beloofd had niets te doen; zonder terminal liep het daarop vast. - Ongeldig bind-adres en poort buiten 1-65535 worden nu meteen geweigerd. Getest met een pseudo-terminal voor de vragen en tegen een echt draaiende server voor het aanmaken van het account, inclusief een wachtwoord vol aanhalingstekens en backslashes, een geweigerd tweede account en een server die niet reageert. De e2e-tests slaan zichzelf over waar curl ontbreekt, zoals in het CI-image. 992 tests groen. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01C7oLCRYzY5ixJ5Sv8Y8EFb --- CHANGELOG.md | 49 +++++ README.md | 32 ++- docs/installeren.md | 71 ++++++- install.sh | 360 ++++++++++++++++++++++++++++++++- tests/test_install_script.py | 379 ++++++++++++++++++++++++++++++++++- 5 files changed, 865 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d38ac92..c68eaf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,52 @@ +# v0.7.40-beta — Account en bereikbaarheid meteen goed + +Na het installeren was je nog niet klaar: je moest zelf naar de webinterface om +een beheerdersaccount te claimen, en stond `BIND` op `127.0.0.1`, dan kón je daar +niet eens bij zonder eerst `.env` aan te passen. Het script regelt nu allebei. + +**Beheerdersaccount.** Op een terminal vraagt het script of je er meteen één wil, +en zo ja om een naam en wachtwoord (twee keer, met de echo uit). Automatisch gaat +het met `--admin NAAM` plus `--admin-password-file PAD` of `SU_ADMIN_PASSWORD`. +Is er geen wachtwoordbron én geen terminal, dan maakt het script er zelf een van +24 tekens en zet die op het scherm. + +Het wachtwoord kan bewust *niet* als optie mee: `--admin-password` weigert met +uitleg. Opdrachtregelargumenten zijn voor elke gebruiker op de server zichtbaar +met `ps` en blijven in je shell-geschiedenis staan. Onderweg naar de server gaat +het via stdin naar `curl`, niet als argument. + +Nieuw is ook **`--create-admin`**: alleen het account aanmaken, bij een +installatie die al draait. Voor als het de eerste keer is misgegaan of je het +hebt overgeslagen. De poort komt daarbij uit `.env`. + +**Bereikbaarheid.** Het script vraagt nu waarop de interface moet luisteren: +alleen deze server, het hele netwerk (met het gedetecteerde adres erbij), of een +adres dat je zelf opgeeft. Installeer je opnieuw over een bestaande map, dan is +je huidige instelling het uitgangspunt en houdt enter die vast. + +Daarbij zat een fout die je zelf tegenkwam: een bestaande `.env` bleef *altijd* +ongemoeid, ook als je `--bind` meegaf. De installatie leek dan te lukken terwijl +de server op het oude adres bleef luisteren. Nu wordt doorgevoerd wat je +expliciet meegeeft, en blijft de rest staan. Andersom rekent het script bij +`--update` voortaan met wat er écht in `.env` staat: draaide je op poort 8080, +dan wachtte het daarvoor op poort 5000 en meldde het het verkeerde adres. + +Verder: `--dry-run` riep `sudo docker` aan en vroeg dus om een wachtwoord, +terwijl het net beloofd had niets te doen — zonder terminal liep het daar vast. +Een proefdraai spreekt de Docker-daemon nu niet meer aan. En een ongeldig +bind-adres of een poort buiten 1–65535 wordt meteen geweigerd in plaats van als +een onbegrijpelijke fout uit `docker compose` terug te komen. + +De vragen worden allemaal vooraf gesteld, zodat je kunt weglopen terwijl het +image gebouwd wordt. + +Getest met een echte pseudo-terminal voor de vragen, en tegen een echt +draaiende server voor het aanmaken van het account — inclusief een wachtwoord +vol aanhalingstekens en backslashes, een tweede account dat geweigerd hoort te +worden, en een server die niet reageert. + +--- + # v0.7.30 — Installeren met één regel ```bash diff --git a/README.md b/README.md index 4d1c47a..1f8fd45 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,9 @@ curl -fsSL https://git.ramonbesselink.nl/bes-r/server-up/raw/branch/main/install ``` Dat controleert je systeem, installeert Docker als het ontbreekt, zet Server Up -in `/opt/server-up` en start het op `http://localhost:5000`. +in `/opt/server-up` en start het. Onderweg vraagt het waarop de interface moet +luisteren en of het meteen een beheerdersaccount voor je aanmaakt — die twee +vragen komen vooraf, zodat je kunt weglopen terwijl het image gebouwd wordt. Liever eerst lezen wat je uitvoert — verstandig, want het script gebruikt root-rechten: @@ -58,12 +60,25 @@ cp .env.example .env docker compose up -d --build ``` -Alle opties staan in [docs/installeren.md](docs/installeren.md): -`--dir`, `--port`, `--bind`, `--branch`, `--token`, `--update`, `--uninstall`. +Alle opties staan in [docs/installeren.md](docs/installeren.md): `--dir`, +`--port`, `--bind`, `--branch`, `--token`, `--admin`, `--create-admin`, +`--update`, `--uninstall`. -Open daarna de interface en **maak meteen een beheerdersaccount aan.** -Zolang dat niet gebeurd is, kan iedereen die de pagina bereikt het account -claimen — de container waarschuwt daar bij het opstarten ook voor. +### Het beheerdersaccount + +Zolang er nog geen account is, kan iedereen die de pagina bereikt het claimen — +de container waarschuwt daar bij het opstarten ook voor. Laat het script het +daarom meteen aanmaken: + +```bash +sh install.sh --admin ramon # vraagt om een wachtwoord +SU_ADMIN_PASSWORD='...' sh install.sh --admin ramon --yes # zonder vragen +``` + +Zonder wachtwoordbron en zonder terminal maakt het script er zelf een en toont +die. Overgeslagen of misgegaan? `sh /opt/server-up/install.sh --create-admin +--admin ramon` doet het achteraf. Een wachtwoord als opdrachtregeloptie wordt +geweigerd: dat is zichtbaar in `ps`. ### Instellingen @@ -76,7 +91,10 @@ PORT=5000 ``` De poort bindt standaard op `127.0.0.1`. Zet hem pas open als er een reverse -proxy met TLS voor staat. +proxy met TLS voor staat. Achteraf wijzigen kan met +`sh /opt/server-up/install.sh --update --bind 0.0.0.0`; pas het anders aan in +`.env` en **niet** in `docker-compose.yml`, want dat bestand komt uit de repo en +wordt bij elke update overschreven. ## Documentatie diff --git a/docs/installeren.md b/docs/installeren.md index a75e0d6..b841e68 100644 --- a/docs/installeren.md +++ b/docs/installeren.md @@ -50,6 +50,10 @@ schrijven én `docker` aanroepen, dan blijft alles onder je eigen account. --bind ADRES Waarop de poort luistert (standaard: 127.0.0.1) --branch NAAM Branch om te installeren (standaard: main) --token TOKEN Toegangstoken, als je repo niet openbaar is +--admin NAAM Maak meteen een beheerdersaccount met deze naam +--admin-password-file PAD + Lees het wachtwoord uit een bestand +--create-admin Alleen het account aanmaken, bij een draaiende installatie --update Bijwerken naar de nieuwste versie --uninstall Stoppen en verwijderen (gegevens blijven staan) --yes Niets vragen @@ -59,12 +63,15 @@ schrijven én `docker` aanroepen, dan blijft alles onder je eigen account. ### Voorbeelden ```bash -# Standaard, alleen bereikbaar vanaf de server zelf +# Standaard: vraagt waarop het moet luisteren en of je een account wil sh install.sh # Bereikbaar op je netwerk, andere poort sh install.sh --bind 0.0.0.0 --port 8080 +# Volledig automatisch, met account +SU_ADMIN_PASSWORD='een-lang-wachtwoord' sh install.sh --admin ramon --yes + # Ergens anders neerzetten sh install.sh --dir /srv/server-up @@ -77,21 +84,65 @@ sh install.sh --token jouw-forgejo-token --- -## Meteen na het installeren +## Het beheerdersaccount -**Maak een beheerdersaccount aan.** Server Up beheert de Docker-daemon, en wie -containers kan starten kan willekeurige mappen van de host mounten. Zolang er -nog geen account is, kan iedereen die de pagina bereikt het claimen. +Server Up beheert de Docker-daemon, en wie containers kan starten kan +willekeurige mappen van de host mounten. Zolang er nog geen account is, kan +iedereen die de pagina bereikt het claimen — dus hoe korter dat venster, hoe +beter. Het script kan het account daarom meteen aanmaken. -De poort staat standaard op `127.0.0.1`, dus alleen bereikbaar vanaf de server -zelf. Wil je er van buitenaf bij, zet dan eerst een reverse proxy met TLS ervoor -en pas daarna `BIND` aan: +Op een terminal vraagt het script erom. Automatisch kan het ook: ```bash -sed -i 's/^BIND=.*/BIND=0.0.0.0/' /opt/server-up/.env -docker compose -f /opt/server-up/docker-compose.yml up -d +# Wachtwoord uit een bestand +sh install.sh --admin ramon --admin-password-file /root/su-ww --yes + +# Of uit een omgevingsvariabele +SU_ADMIN_PASSWORD='een-lang-wachtwoord' sh install.sh --admin ramon --yes ``` +Geef je geen wachtwoord en is er geen terminal, dan maakt het script er zelf een +van 24 tekens en zet die op het scherm. Schrijf die meteen over — hij staat +nergens anders. + +> Het wachtwoord kan **niet** als optie mee. Opdrachtregelargumenten zijn voor +> elke gebruiker op de server zichtbaar met `ps` en blijven in je +> shell-geschiedenis staan. `--admin-password` weigert daarom met een verwijzing +> naar de twee manieren hierboven. + +Ging het aanmaken mis, of heb je het overgeslagen? Dan kan het achteraf, zolang +er nog geen account bestaat: + +```bash +sh /opt/server-up/install.sh --create-admin --admin ramon +``` + +Eist minstens 10 tekens, net als de webinterface. + +--- + +## Bereikbaarheid + +Het script vraagt waarop de webinterface moet luisteren: + +| Keuze | `BIND` | Wanneer | +|---|---|---| +| Alleen deze server | `127.0.0.1` | Standaard en veiligst. Erbij via een SSH-tunnel of een reverse proxy op dezelfde machine. | +| Het hele netwerk | `0.0.0.0` | Direct bereikbaar op het adres van je server. Zet er een reverse proxy met TLS voor. | +| Een specifiek adres | zelf opgeven | Bijvoorbeeld alleen je beheernetwerk. | + +Achteraf wijzigen kan met dezelfde optie; die wordt ook doorgevoerd in een +`.env` die er al staat: + +```bash +sh /opt/server-up/install.sh --update --bind 0.0.0.0 +``` + +Wat je *niet* expliciet meegeeft blijft staan zoals het was, zodat een `--update` +je instellingen niet terugzet. Pas `BIND` daarom aan in `.env` of via deze optie +— **niet** in `docker-compose.yml`, want dat bestand komt uit de repo en wordt +bij elke update overschreven. + Zie [beveiliging.md](beveiliging.md) voor de reverse proxy, rollen en SSO. --- diff --git a/install.sh b/install.sh index 28678d7..4cc169d 100755 --- a/install.sh +++ b/install.sh @@ -13,7 +13,7 @@ set -eu -SCRIPT_VERSIE="1.0" +SCRIPT_VERSIE="1.1" GIT_HOST="git.ramonbesselink.nl" GIT_PAD="bes-r/server-up" BRANCH="main" @@ -24,6 +24,13 @@ TOKEN="" JA=0 DROOG=0 ACTIE="install" +BEHEERDER="" +BEHEERDER_WW="" +BEHEERDER_WW_BESTAND="" +# Expliciet meegegeven waarden overschrijven wél een bestaande .env; de rest +# blijft staan, zodat een --update je instellingen niet terugzet. +BIND_EXPLICIET=0 +POORT_EXPLICIET=0 # ── Uitvoer ────────────────────────────────────────────────────────────────── # Kleuren alleen als we naar een terminal schrijven; in een pipe of logbestand @@ -79,15 +86,28 @@ Gebruik: install.sh [opties] maar zet er dan wel een reverse proxy met TLS voor. --branch NAAM Branch om te installeren (standaard: ${BRANCH}) --token TOKEN Toegangstoken, als je git-repo niet openbaar is + --admin NAAM Maak meteen een beheerdersaccount met deze naam + --admin-password-file PAD + Lees het wachtwoord uit een bestand. Kan ook via de + omgevingsvariabele SU_ADMIN_PASSWORD. Geef je geen van + beide, dan wordt ernaar gevraagd; kan dat niet (geen + terminal), dan wordt er één aangemaakt en getoond. + --create-admin Alleen het beheerdersaccount aanmaken, bij een installatie + die al draait. Werkt zolang er nog geen account bestaat. --update Bijwerken naar de nieuwste versie --uninstall Stoppen en verwijderen (je gegevens blijven staan) --yes Niets vragen, overal ja op antwoorden --dry-run Alleen tonen wat er zou gebeuren --help Deze uitleg +Het wachtwoord staat bewust niet als optie op de opdrachtregel: die is voor +iedereen op de server te zien met 'ps' en blijft in je shell-geschiedenis staan. + Voorbeelden: sh install.sh sh install.sh --bind 0.0.0.0 --port 8080 + sh install.sh --admin ramon + SU_ADMIN_PASSWORD=... sh install.sh --admin ramon --yes sh install.sh --update UITLEG } @@ -96,12 +116,18 @@ UITLEG while [ $# -gt 0 ]; do case "$1" in --dir) DOEL="${2:?--dir vereist een pad}"; shift 2 ;; - --port) POORT="${2:?--port vereist een nummer}"; shift 2 ;; - --bind) BIND="${2:?--bind vereist een adres}"; shift 2 ;; + --port) POORT="${2:?--port vereist een nummer}"; POORT_EXPLICIET=1; shift 2 ;; + --bind) BIND="${2:?--bind vereist een adres}"; BIND_EXPLICIET=1; shift 2 ;; --branch) BRANCH="${2:?--branch vereist een naam}"; shift 2 ;; --token) TOKEN="${2:?--token vereist een waarde}"; shift 2 ;; + --admin) BEHEERDER="${2:?--admin vereist een gebruikersnaam}"; shift 2 ;; + --admin-password-file) + BEHEERDER_WW_BESTAND="${2:?--admin-password-file vereist een pad}"; shift 2 ;; + --admin-password) + fout "Gebruik --admin-password-file of SU_ADMIN_PASSWORD; een wachtwoord op de opdrachtregel is voor iedereen zichtbaar met 'ps'." ;; --update) ACTIE="update"; shift ;; --uninstall) ACTIE="uninstall"; shift ;; + --create-admin) ACTIE="create-admin"; shift ;; --yes|-y) JA=1; shift ;; --dry-run) DROOG=1; shift ;; --help|-h) gebruik; exit 0 ;; @@ -110,6 +136,18 @@ while [ $# -gt 0 ]; do done case "$POORT" in ''|*[!0-9]*) fout "Ongeldige poort: $POORT" ;; esac +[ "$POORT" -ge 1 ] && [ "$POORT" -le 65535 ] || fout "Poort buiten bereik: $POORT" + +# Docker publiceert op een adres, niet op een hostnaam. Alleen cijfers, punten +# en dubbele punten (IPv6) toestaan, zodat een typefout hier opvalt en niet pas +# als 'docker compose up' er een onbegrijpelijke fout over geeft. +geldig_bind() { + case "$1" in + ''|*[!0-9.:a-fA-F]*) return 1 ;; + *) return 0 ;; + esac +} +geldig_bind "$BIND" || fout "Ongeldig bind-adres: $BIND (verwacht een IP-adres, bijvoorbeeld 127.0.0.1 of 0.0.0.0)" # ── Rechten ────────────────────────────────────────────────────────────────── # Alleen sudo gebruiken waar het echt nodig is: kan de gebruiker zelf al in de @@ -146,6 +184,18 @@ controleer_systeem() { } controleer_docker() { + # Bij een proefdraai niets aanroepen wat via sudo loopt: dan staat er + # ineens een wachtwoordvraag op het scherm terwijl we net beloofd hebben + # dat er niets gebeurt — en zonder terminal blijft hij daarop hangen. + if [ "$DROOG" -eq 1 ]; then + if heeft docker; then + goed "Docker aanwezig (de daemon wordt bij een proefdraai niet aangesproken)" + else + waarschuw "Docker is niet geïnstalleerd; het script zou aanbieden dat te doen." + fi + return 0 + fi + if heeft docker; then if $SUDO docker info >/dev/null 2>&1; then goed "Docker draait ($($SUDO docker version --format '{{.Server.Version}}' 2>/dev/null || echo '?'))" @@ -216,18 +266,127 @@ haal_broncode() { } # ── Instellingen ───────────────────────────────────────────────────────────── +server_ip() { hostname -I 2>/dev/null | awk '{print $1}'; } + +kies_bind() { + # Alleen vragen als er nog iets te kiezen valt: met --bind, met --yes of + # zonder terminal is de keuze al gemaakt. + [ "$BIND_EXPLICIET" -eq 1 ] && return 0 + [ "$JA" -eq 1 ] && return 0 + [ "$DROOG" -eq 1 ] && return 0 + [ -e /dev/tty ] || return 0 + + # Installeer je opnieuw over een bestaande map, dan is je huidige keuze het + # uitgangspunt — anders zet enter je server ongemerkt terug op loopback. + huidig="" + if [ -f "$DOEL/.env" ]; then + lees_env_terug "$DOEL/.env" + huidig="$BIND" + fi + + ip="$(server_ip)" + stap "Bereikbaarheid" + printf ' Waarop moet de webinterface luisteren?\n\n' + printf ' 1) Alleen deze server (127.0.0.1) — veiligst\n' + printf ' Erbij via een SSH-tunnel of een reverse proxy op deze machine.\n' + printf ' 2) Het hele netwerk (0.0.0.0)\n' + printf ' Direct bereikbaar op http://%s:%s — zet er wel TLS voor.\n' "${ip:-}" "$POORT" + printf ' 3) Een specifiek adres\n\n' + if [ -n "$huidig" ]; then + printf ' Nu ingesteld: %s\n' "$huidig" + printf ' Keuze [enter = zo laten]: ' + else + printf ' Keuze [1]: ' + fi + read -r keuze > '$1'" +} + +lees_env_terug() { + # Wat er in .env staat is de waarheid, niet wat dit script als standaard + # heeft. Zonder dit klopt bij --update de wachtlus en het slotadres niet + # meer zodra je ooit een andere poort hebt gekozen. + [ -f "$1" ] || return 0 + # Lezen kan meestal zonder sudo; alleen als het bestand van root is en + # afgeschermd, is de omweg nodig. + if [ -r "$1" ]; then + _lees="cat" + elif [ -n "$SUDO" ]; then + _lees="$SUDO cat" + elif heeft sudo; then + _lees="sudo cat" + else + _lees="cat" + fi + _inhoud="$($_lees "$1" 2>/dev/null || true)" + _poort="$(printf '%s\n' "$_inhoud" | sed -n 's/^PORT=//p' | tail -1)" + _bind="$(printf '%s\n' "$_inhoud" | sed -n 's/^BIND=//p' | tail -1)" + if [ "$POORT_EXPLICIET" -eq 0 ]; then + case "$_poort" in ''|*[!0-9]*) ;; *) POORT="$_poort" ;; esac + fi + if [ "$BIND_EXPLICIET" -eq 0 ] && [ -n "$_bind" ] && geldig_bind "$_bind"; then + BIND="$_bind" + fi + return 0 +} + schrijf_env() { stap "Instellingen" env_bestand="$DOEL/.env" + if [ -f "$env_bestand" ]; then - goed "Bestaande .env blijft ongemoeid" - # BIND en PORT wel bijwerken als ze expliciet zijn meegegeven. + # Een bestaande .env bevat jouw instellingen; die blijven staan. Alleen + # wat je nu expliciet meegeeft wordt doorgevoerd — dat is precies het + # verschil dat eerder ontbrak, waardoor --bind niets deed zodra er al + # een .env stond. + gewijzigd=0 + if [ "$BIND_EXPLICIET" -eq 1 ]; then + if [ "$DROOG" -eq 1 ]; then + printf ' [droog] BIND=%s in bestaande .env zetten\n' "$BIND" + else + zet_env_regel "$env_bestand" BIND "$BIND" + fi + gewijzigd=1 + fi + if [ "$POORT_EXPLICIET" -eq 1 ]; then + if [ "$DROOG" -eq 1 ]; then + printf ' [droog] PORT=%s in bestaande .env zetten\n' "$POORT" + else + zet_env_regel "$env_bestand" PORT "$POORT" + fi + gewijzigd=1 + fi + if [ "$gewijzigd" -eq 1 ]; then + goed "Bestaande .env bijgewerkt (BIND=$BIND, PORT=$POORT)" + else + lees_env_terug "$env_bestand" + goed "Bestaande .env blijft ongemoeid (BIND=$BIND, PORT=$POORT)" + fi return 0 fi + if [ "$DROOG" -eq 1 ]; then printf ' [droog] .env aanmaken met BIND=%s PORT=%s\n' "$BIND" "$POORT" return 0 fi + if [ -f "$DOEL/.env.example" ]; then $SUDO cp "$DOEL/.env.example" "$env_bestand" else @@ -276,6 +435,148 @@ wacht_op_gereed() { return 1 } +# ── Beheerdersaccount ──────────────────────────────────────────────────────── +# Tussen "container draait" en "eerste account" ligt een venster waarin iedereen +# die de pagina bereikt zichzelf beheerder kan maken. Dat venster hoort zo kort +# mogelijk te zijn, dus kan het script het account meteen aanmaken. +WW_GEGENEREERD=0 +BEHEERDER_WW_TOON="" + +json_tekst() { + # Escapet een waarde voor gebruik tussen JSON-aanhalingstekens. + printf '%s' "$1" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' +} + +genereer_wachtwoord() { + LC_ALL=C tr -dc 'A-Za-z0-9' < /dev/urandom 2>/dev/null | head -c 24 +} + +vraag_wachtwoord() { + # Twee keer intypen, met de echo uit. Mislukt dat, dan valt hij terug op + # een gegenereerd wachtwoord in plaats van er een half account van te maken. + oude_stty="" + if stty -g /dev/null 2>&1; then oude_stty="$(stty -g /dev/null || true)" + # Bij een mislukte verbinding schrijft curl zelf al "000"; kan curl helemaal + # niet draaien, dan blijft het leeg. Beide gevallen zijn hetzelfde verhaal. + case "$code" in ''|*[!0-9]*) code="000" ;; esac + + case "$code" in + 200) goed "Beheerder '$BEHEERDER' aangemaakt" + # Alleen een zelf aangemaakt wachtwoord moet nog getoond worden; + # een ingetypt of meegegeven wachtwoord kent de gebruiker al. + if [ "$WW_GEGENEREERD" -eq 1 ]; then + BEHEERDER_WW_TOON="$BEHEERDER_WW" + fi ;; + 409) waarschuw "Er bestond al een account; er is niets gewijzigd." + BEHEERDER=""; WW_GEGENEREERD=0 ;; + 000) waarschuw "Server Up was niet bereikbaar; account niet aangemaakt." + BEHEERDER=""; WW_GEGENEREERD=0 ;; + *) melding="$(sed -n 's/.*"msg" *: *"\([^"]*\)".*/\1/p' "$antwoord" 2>/dev/null)" + waarschuw "Aanmaken mislukt (HTTP $code)${melding:+: }${melding:-}" + BEHEERDER=""; WW_GEGENEREERD=0 ;; + esac + rm -f "$antwoord" + BEHEERDER_WW="" +} + afsluiting() { if [ "$BIND" = "0.0.0.0" ]; then ip="$(hostname -I 2>/dev/null | awk '{print $1}')" @@ -288,9 +589,18 @@ afsluiting() { printf '%s Server Up draait op %s%s\n' "$C_OK" "$adres" "$C_UIT" printf '%s────────────────────────────────────────────────────────%s\n\n' "$C_KOP" "$C_UIT" - printf ' %sMaak nu meteen een beheerdersaccount aan.%s\n' "$C_WAARSCHUW" "$C_UIT" - printf ' Zolang dat niet gebeurd is, kan iedereen die deze pagina\n' - printf ' bereikt het account claimen.\n\n' + if [ -n "$BEHEERDER" ]; then + printf ' %s✔%s Inloggen als: %s%s%s\n' "$C_OK" "$C_UIT" "$C_KOP" "$BEHEERDER" "$C_UIT" + if [ "$WW_GEGENEREERD" -eq 1 ]; then + printf ' Wachtwoord: %s%s%s\n' "$C_KOP" "$BEHEERDER_WW_TOON" "$C_UIT" + printf ' %sSchrijf dit nu over — het staat nergens anders.%s\n' "$C_WAARSCHUW" "$C_UIT" + fi + printf '\n' + else + printf ' %sMaak nu meteen een beheerdersaccount aan.%s\n' "$C_WAARSCHUW" "$C_UIT" + printf ' Zolang dat niet gebeurd is, kan iedereen die deze pagina\n' + printf ' bereikt het account claimen.\n\n' + fi if [ "$BIND" = "127.0.0.1" ]; then printf ' Alleen bereikbaar vanaf deze server zelf. Van buitenaf erbij?\n' @@ -326,6 +636,13 @@ verwijderen() { } # ── Hoofdprogramma ─────────────────────────────────────────────────────────── +# De testsuite laadt dit bestand om losse functies te kunnen aanroepen — vooral +# de vragen die bepalen waarop de server straks luistert. Zonder deze uitgang +# zou het script bij het inladen meteen een hele installatie beginnen. +if [ -n "${SU_INSTALL_ALLEEN_FUNCTIES:-}" ]; then + return 0 2>/dev/null || exit 0 +fi + printf '\n%sServer Up — installatiescript %s%s\n' "$C_KOP" "$SCRIPT_VERSIE" "$C_UIT" [ "$DROOG" -eq 1 ] && waarschuw "Proefdraai: er wordt niets gewijzigd." @@ -339,18 +656,45 @@ case "$ACTIE" in controleer_systeem controleer_docker haal_broncode + # Ook bij bijwerken: expliciete --bind/--port doorvoeren, en anders + # overnemen wat er al staat. + schrijf_env start wacht_op_gereed || true printf '\n' goed "Bijgewerkt." ;; + create-admin) + # Losse actie voor een installatie die al draait: handig als het + # aanmaken tijdens de installatie is misgegaan, of overgeslagen. + # Docker en schrijfrechten zijn hier niet nodig — alleen .env lezen + # en één verzoek naar de draaiende server — dus geen bepaal_rechten. + lees_env_terug "$DOEL/.env" + if [ -z "$BEHEERDER" ]; then + if [ -e /dev/tty ] && [ "$JA" -eq 0 ]; then + printf '\n Gebruikersnaam: ' + read -r naam