From 48228ba91002e6b7d27dead66c0f71473aba1b1e Mon Sep 17 00:00:00 2001 From: duffyduck Date: Sun, 20 Sep 2026 21:24:46 +0200 Subject: [PATCH] Proxy Manager neu starten - als Menuepunkt und als Parameter Die Zusatzkonfiguration - Standard-Server fuer den IP-Zugang, Adminport - liegt als Datei im Datenverzeichnis und wird erst beim naechsten Einlesen beachtet. Bisher blieb dafuer nur "restart" fuer den ganzen Stack. proxy reload nginx neu einlesen, ohne Unterbrechung proxy restart Container neu starten "reload" prueft vorher mit "nginx -t" und laedt nur bei fehlerfreier Konfiguration neu; sonst stehen Ursache und Zeilennummer da und es passiert nichts. In der Oberflaeche liegt beides unter Proxy-Hosts > "Proxy Manager neu starten / nginx neu laden". Beim Bauen kamen zwei Dinge heraus: - "nginx -t" beantwortet nicht, ob nginx laeuft - es prueft nur die Datei und gelingt auch, bevor der Dienst da ist. Als Bereitschaftspruefung nach dem Neustart taugt es also nicht; es wird jetzt in /proc nach dem Masterprozess gesehen (ohne "ps", das es im Container nicht gibt) und anschliessend geprueft, ob die Adminoberflaeche wieder antwortet. nginx ist nach einer Sekunde zurueck, der Dienst dahinter braucht laenger - ein sofortiges "fertig" waere gelogen. - ENVFILE_OPT wurde nie an Unterprozesse weitergereicht. Wer die Oberflaeche mit --env-file startete, dessen Menuepunkte liefen gegen die Standard-.env, also womoeglich gegen den falschen Stack. Alle 43 Stellen bekommen die Option jetzt mit. Co-Authored-By: Claude Opus 5 (1M context) --- README.md | 33 +++++++ README_en.md | 33 +++++++ scripts/cmk-manage.sh | 216 +++++++++++++++++++++++++++++++++--------- 3 files changed, 235 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index c16f3ae..76b5572 100644 --- a/README.md +++ b/README.md @@ -1227,6 +1227,8 @@ erzwingen, HTTP/2 und Websockets einschalten und den empfohlenen | `proxy edit --id N …` | vorhandenen Proxy-Host ändern – nur die angegebenen Felder | | `proxy default --domain X` | HTTPS über die blanke IP ermöglichen (spiegelt X in einen Standard-Server) | | `proxy default --off` | diese Spiegelung wieder entfernen | +| `proxy reload` | nginx die Konfiguration neu einlesen lassen – ohne Unterbrechung | +| `proxy restart` | den Proxy-Manager-Container neu starten | Optionen von `proxy add`: @@ -1573,6 +1575,37 @@ stehen als Auswahlliste bereit. > vorher. Nach inhaltlichen Änderungen neu schreiben – `proxy edit` erinnert > daran. +### 10.10 Änderungen wirksam machen + +Was über die API läuft – Proxy-Hosts anlegen, ändern, löschen –, schreibt der +Proxy Manager selbst und lädt nginx dabei neu. Die **Zusatzkonfiguration** +dagegen (der Standard-Server aus [Kapitel 10.8](#108-https-über-die-blanke-ip), +der Adminport aus [Kapitel 12](#12-adminoberfläche-auf-einen-anderen-port-legen)) +liegt als Datei im Datenverzeichnis und wird erst beim nächsten Einlesen +beachtet: + +```bash +./scripts/cmk-manage.sh proxy reload # nginx neu einlesen, ohne Unterbrechung +./scripts/cmk-manage.sh proxy restart # Container neu starten +``` + +`reload` prüft die Konfiguration **vorher** mit `nginx -t` und lädt nur dann +neu. Ist etwas kaputt, steht die Ursache samt Zeilennummer da, und es passiert +nichts: + +``` +[FEHLER] Die nginx-Konfiguration ist fehlerhaft - es wird nichts neu geladen. + nginx: [emerg] invalid parameter "kaputt" in /data/nginx/custom/http.conf:1 +``` + +`restart` ist nur nötig, wenn sich Umgebungsvariablen geändert haben oder nginx +gar nicht mehr antwortet. Er wartet danach, bis nginx wieder läuft **und** die +Adminoberfläche antwortet – nginx ist nach einer Sekunde zurück, der Dienst +dahinter braucht länger, und ein „fertig" wäre sonst gelogen. + +In der Oberfläche liegt beides unter **Proxy-Hosts → Proxy Manager neu starten +/ nginx neu laden**. + --- ## 11. Proxy Manager lokal einrichten (Terminal-Browser) diff --git a/README_en.md b/README_en.md index e1d79fb..bc43ae1 100644 --- a/README_en.md +++ b/README_en.md @@ -1226,6 +1226,8 @@ HTTPS, enables HTTP/2 and websockets, and sets the recommended | `proxy edit --id N …` | change an existing proxy host – only the fields you name | | `proxy default --domain X` | enable HTTPS on the bare IP (mirrors X into a default server) | | `proxy default --off` | remove that mirror again | +| `proxy reload` | make nginx re-read its configuration – without interruption | +| `proxy restart` | restart the Proxy Manager container | Options for `proxy add`: @@ -1568,6 +1570,37 @@ checklist. > ([chapter 10.8](#108-https-on-the-bare-ip)), it mirrors an earlier state. > Rewrite it after content changes – `proxy edit` reminds you. +### 10.10 Applying changes + +Whatever goes through the API – creating, changing, deleting proxy hosts – is +written by the Proxy Manager itself, which reloads nginx along the way. The +**custom configuration** however (the default server from +[chapter 10.8](#108-https-on-the-bare-ip), the admin port from +[chapter 12](#12-moving-the-admin-interface-to-a-different-port)) is a file in the +data directory and only takes effect on the next read: + +```bash +./scripts/cmk-manage.sh proxy reload # re-read nginx config, no interruption +./scripts/cmk-manage.sh proxy restart # restart the container +``` + +`reload` checks the configuration **first** with `nginx -t` and only reloads if +it passes. If something is broken, the cause including the line number is right +there and nothing happens: + +``` +[FEHLER] Die nginx-Konfiguration ist fehlerhaft - es wird nichts neu geladen. + nginx: [emerg] invalid parameter "kaputt" in /data/nginx/custom/http.conf:1 +``` + +`restart` is only needed when environment variables changed or nginx stopped +answering altogether. It then waits until nginx runs again **and** the admin +interface answers – nginx is back within a second, the service behind it takes +longer, and a "done" would otherwise be a lie. + +The GUI has both under **Proxy-Hosts → Proxy Manager neu starten / nginx neu +laden**. + --- ## 11. Configuring the Proxy Manager locally (terminal browser) diff --git a/scripts/cmk-manage.sh b/scripts/cmk-manage.sh index fd8e130..803580a 100755 --- a/scripts/cmk-manage.sh +++ b/scripts/cmk-manage.sh @@ -23,6 +23,11 @@ ASSUME_YES="" VERBOSE="" NPM_TOKEN="" ENVFILE_OPT="" +# Ein aus der Oberflaeche gestarteter Unterprozess muss dieselbe +# Konfiguration lesen wie wir. Ohne das greift er zur Standard-.env, +# und die Aktion liefe gegen den falschen Stack. +SELF_ENV="" # fuer "bash -c"-Zeichenketten +SELF_ENV_ARR=() # fuer direkte Aufrufe # ===================================================================== # Hilfe @@ -3905,6 +3910,21 @@ EOF sed -i '/./,$!d' "$f" } +# Laeuft nginx im Container wirklich? "nginx -t" beantwortet das NICHT - +# es prueft nur die Datei und gelingt auch, bevor der Dienst da ist. +# Der Pfad der pid-Datei ist vom Abbild abhaengig (bei NPM +# /run/nginx/nginx.pid), deshalb wird schlicht in /proc nachgesehen - +# das kommt ohne "ps" aus, das es im Container nicht gibt. +npm_nginx_up() { + $RUNTIME exec "$NPM_CONTAINER_NAME" sh -c ' + for d in /proc/[0-9]*; do + case "$(tr "\0" " " < "$d/cmdline" 2>/dev/null)" in + *"nginx: master"*) exit 0 ;; + esac + done + exit 1' >/dev/null 2>&1 +} + npm_reload_hint() { # restart-flag if [ -n "${1:-}" ] && container_running "$NPM_CONTAINER_NAME"; then log "Starte '$NPM_CONTAINER_NAME' neu, damit nginx die Konfiguration liest ..." @@ -3914,7 +3934,8 @@ npm_reload_hint() { # restart-flag warn "Neustart fehlgeschlagen - bitte manuell: $SELF restart" fi else - log "Wirksam nach: $SELF restart (bzw. Neustart des Proxy Managers)" + log "Wirksam nach: $SELF proxy restart + (oder ohne Unterbrechung: $SELF proxy reload)" fi } @@ -4003,6 +4024,83 @@ cmd_proxy() { echo return 0 ;; + reload|restart) + npm_enabled || die "Der NGINX Proxy Manager ist abgeschaltet (NPM_ENABLED=off). + Einschalten: $SELF npm-enable on" + container_running "$NPM_CONTAINER_NAME" \ + || die "Der Container '$NPM_CONTAINER_NAME' laeuft nicht. + Starten: $SELF up" + + if [ "$sub" = reload ] && ! npm_nginx_up; then + err "Im Container laeuft kein nginx - es gibt nichts neu zu laden." + log "Dann hilft ein Neustart: $SELF proxy restart" + return 1 + fi + + if [ "$sub" = reload ]; then + # Erst die Konfiguration pruefen. nginx wuerde ein fehlerhaftes + # Reload zwar ablehnen und weiterlaufen, aber dann steht die + # Ursache nur im Containerprotokoll. + local out + if ! out="$($RUNTIME exec "$NPM_CONTAINER_NAME" nginx -t 2>&1)"; then + err "Die nginx-Konfiguration ist fehlerhaft - es wird nichts neu geladen." + printf '%s\n' "$out" | sed 's/^/ /' >&2 + return 1 + fi + log "Konfiguration in Ordnung, lade nginx neu ..." + if $RUNTIME exec "$NPM_CONTAINER_NAME" nginx -s reload >/dev/null 2>&1; then + ok "nginx hat die Konfiguration neu eingelesen (ohne Unterbrechung)." + else + err "Neuladen fehlgeschlagen." + log "Dann hilft ein Neustart: $SELF proxy restart" + return 1 + fi + else + log "Starte '$NPM_CONTAINER_NAME' neu ..." + if ! $RUNTIME restart "$NPM_CONTAINER_NAME" >/dev/null; then + err "Neustart fehlgeschlagen." + log "Protokoll ansehen: $RUNTIME logs --tail 50 $NPM_CONTAINER_NAME" + return 1 + fi + # Warten, bis nginx wieder lauscht - und ehrlich melden, + # wenn es das nicht tut + local i=0 up="" + while [ "$i" -lt 60 ]; do + if npm_nginx_up; then up=1; break; fi + i=$((i+1)); sleep 1 + done + if [ -z "$up" ]; then + warn "Der Container laeuft, nginx ist aber nach 60s nicht da." + log "Protokoll ansehen: $RUNTIME logs --tail 50 $NPM_CONTAINER_NAME" + return 1 + fi + ok "Proxy Manager neu gestartet." + + # nginx ist schnell wieder da, die Oberflaeche dahinter braucht + # laenger. Ohne diese zweite Pruefung meldet der Befehl Erfolg, + # waehrend der Browser noch ins Leere laeuft. + local url code + url="${NPM_ADMIN_URL:-http://127.0.0.1:${NPM_ADMIN_PORT:-81}}" + i=0 + while [ "$i" -lt 45 ]; do + code="$(http_code "$url")" || code=000 + case "$code" in 2??|3??) break ;; esac + i=$((i+1)); sleep 1 + done + case "$code" in + 2??|3??) log "Adminoberflaeche antwortet wieder (nach ${i}s)." ;; + *) warn "Die Adminoberflaeche antwortet noch nicht ($url, HTTP $code). + Kurz warten - der Dienst dahinter braucht laenger als nginx." ;; + esac + fi + + printf ' Adminoberflaeche : %s\n' "${NPM_ADMIN_URL:-http://127.0.0.1:${NPM_ADMIN_PORT:-81}}" + local conf; conf="$(npm_custom_conf_path)" + if grep -qsF "$NPM_DEF_START" "$conf"; then + printf ' HTTPS ueber die blanke IP: eingerichtet\n' + fi + return 0 ;; + default|ip) local dom="" off="" restart="" conf while [ $# -gt 0 ]; do @@ -4447,7 +4545,8 @@ EOF return 0 ;; *) die "Unbekanntes Unterkommando 'proxy $sub'. - Moeglich: status | list | show | certs | add | edit | del | default" ;; + Moeglich: status | list | show | certs | add | edit | del | default + | reload | restart" ;; esac } @@ -4614,11 +4713,11 @@ gui_stack_menu() { logs "Letzte 200 Logzeilen ansehen" \ back "zurueck")" || return 0 case "$sel" in - up) ui_run "Stack starten" bash -c "cd '$PROJECT_DIR' && '$SELF' up" ;; - restart) ui_run "Neu starten" bash -c "cd '$PROJECT_DIR' && '$SELF' restart" ;; + up) ui_run "Stack starten" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV up" ;; + restart) ui_run "Neu starten" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV restart" ;; down) ui_yesno "Stack stoppen" "Container wirklich stoppen und entfernen?\n(Die Daten unter ./data bleiben erhalten.)" \ - && ui_run "Stack stoppen" bash -c "cd '$PROJECT_DIR' && '$SELF' down" ;; - pull) ui_run "Images laden" bash -c "cd '$PROJECT_DIR' && '$SELF' pull" ;; + && ui_run "Stack stoppen" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV down" ;; + pull) ui_run "Images laden" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV pull" ;; logs) local lf; lf="$(mktemp)"; compose logs --tail=200 >"$lf" 2>&1 || true ui_text "Logs (letzte 200 Zeilen)" "$lf"; rm -f "$lf" ;; back) return 0 ;; @@ -4659,7 +4758,7 @@ gui_backup() { args+=(--site "$sitename") done - ui_run "Backup laeuft" bash -c "cd '$PROJECT_DIR' && '$SELF' -y ${args[*]}" + ui_run "Backup laeuft" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y ${args[*]}" } # --------------------------------------------------------------------- @@ -4700,7 +4799,7 @@ gui_backup_auto() { Abschalten? Die Jobs bleiben erhalten, es wird nur nichts mehr automatisch ausgefuehrt." || return 0 - ui_run "Automatik abschalten" bash -c "cd '$PROJECT_DIR' && '$SELF' -y job auto off" + ui_run "Automatik abschalten" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y job auto off" else local n; n="$(jobs_read | awk -F'|' '$7=="on"' | wc -l)" if [ "$n" -eq 0 ]; then @@ -4716,7 +4815,7 @@ dort wird auch der Zeitplan festgelegt." ($CRON_FILE). Dafuer werden root-Rechte benoetigt. Einschalten?" || return 0 - ui_run "Automatik einschalten" bash -c "cd '$PROJECT_DIR' && '$SELF' -y job auto on" + ui_run "Automatik einschalten" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y job auto on" fi load_env "${ENV_FILE:-$PROJECT_DIR/.env}" } @@ -4740,7 +4839,7 @@ gui_job_run_now() { local j; j="$(gui_pick_job)" || return 0 [ -n "$j" ] || return 0 ui_yesno "Job ausfuehren" "Job '$j' jetzt ausfuehren?" || return 0 - ui_run "Job '$j'" bash -c "cd '$PROJECT_DIR' && '$SELF' -y job run '$j'" + ui_run "Job '$j'" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y job run '$j'" } gui_jobs_menu() { @@ -4766,10 +4865,10 @@ Jobdatei: $(jobs_file)" \ j2="$(gui_pick_job)" || continue; [ -n "$j2" ] || continue l="$(job_line "$j2")"; st=disable if [ "$(job_f "$l" 7)" = off ]; then st=enable; fi - ui_run "Job $st" bash -c "cd '$PROJECT_DIR' && '$SELF' -y job $st '$j2'" ;; + ui_run "Job $st" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y job $st '$j2'" ;; del) local j3; j3="$(gui_pick_job)" || continue; [ -n "$j3" ] || continue ui_yesno "Loeschen" "Job '$j3' wirklich loeschen?\n\n(Bereits erstellte Backups bleiben erhalten.)" \ - && ui_run "Job loeschen" bash -c "cd '$PROJECT_DIR' && '$SELF' -y job del '$j3'" ;; + && ui_run "Job loeschen" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y job del '$j3'" ;; back) return 0 ;; esac done @@ -4865,7 +4964,7 @@ gui_job_edit() { # name (leer = neu) local action=add; job_exists "$name" && action=set ui_run "Job speichern" bash -c \ - "cd '$PROJECT_DIR' && '$SELF' -y job $action --name '$name' --sites '$sites' \ + "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y job $action --name '$name' --sites '$sites' \ --cron '$cron' --dir '$dir' --keep '$keep' $opts" } @@ -4885,7 +4984,7 @@ gui_restore() { reuse="--reuse --kill" fi ui_yesno "Restore starten" "Site '$B_SITE' aus\n$(basename "$file")\nwiederherstellen?" || return 0 - ui_run "Restore laeuft" bash -c "cd '$PROJECT_DIR' && '$SELF' -y restore --file '$file' $reuse" + ui_run "Restore laeuft" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y restore --file '$file' $reuse" } gui_import() { @@ -4919,7 +5018,7 @@ Dann muessen die Agents NICHT neu eingerichtet werden." ui_yesno "Standard-Site" "Soll CMK_SITE_ID in der .env auf '$B_SITE' gesetzt werden?\n\n(Empfohlen - sonst startet der Container nach einem Reboot\ndie importierte Site nicht automatisch.)" \ && setdef="--set-default-site" - ui_run "Import laeuft" bash -c "cd '$PROJECT_DIR' && '$SELF' -y import --file '$file' $reuse $setdef" + ui_run "Import laeuft" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y import --file '$file' $reuse $setdef" } gui_backups_menu() { @@ -4938,7 +5037,7 @@ gui_backups_menu() { local f2; f2="$(mktemp)"; bundle_show "$b" >"$f2" 2>&1 || true ui_text "Details" "$f2"; rm -f "$f2" ;; verify) local b2; b2="$(gui_pick_backup)" || continue; [ -n "$b2" ] || continue - ui_run "Pruefe Bundle" bash -c "cd '$PROJECT_DIR' && '$SELF' verify --file '$b2'" ;; + ui_run "Pruefe Bundle" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV verify --file '$b2'" ;; del) local b3; b3="$(gui_pick_backup)" || continue; [ -n "$b3" ] || continue ui_yesno "Loeschen" "Datei wirklich loeschen?\n\n$b3" && rm -f "$b3" \ && ui_msg "Geloescht" "Die Datei wurde entfernt." ;; @@ -4960,10 +5059,10 @@ gui_sites_menu() { case "$sel" in list) local f; f="$(mktemp)"; cmd_sites >"$f" 2>&1 || true; ui_text "Sites" "$f"; rm -f "$f" ;; start) local s; s="$(gui_pick_site)" || continue; [ -n "$s" ] || continue - ui_run "Site starten" bash -c "cd '$PROJECT_DIR' && '$SELF' site-start '$s'" ;; + ui_run "Site starten" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV site-start '$s'" ;; stop) local s2; s2="$(gui_pick_site)" || continue; [ -n "$s2" ] || continue - ui_run "Site stoppen" bash -c "cd '$PROJECT_DIR' && '$SELF' site-stop '$s2'" ;; - all) ui_run "Alle Sites starten" bash -c "cd '$PROJECT_DIR' && '$SELF' start-all-sites" ;; + ui_run "Site stoppen" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV site-stop '$s2'" ;; + all) ui_run "Alle Sites starten" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV start-all-sites" ;; back) return 0 ;; esac done @@ -5128,7 +5227,7 @@ Benutzer:" "")" || return 0 case "$src" in registry) ui_run "Image holen: $ed $ver" bash -c \ - "cd '$PROJECT_DIR' && '$SELF' -y image pull --edition '$ed' --version '$ver' --remember ${extra[*]+${extra[*]}}" || rc=1 ;; + "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y image pull --edition '$ed' --version '$ver' --remember ${extra[*]+${extra[*]}}" || rc=1 ;; download) case "$ver" in *-latest|latest|*-daily) @@ -5138,20 +5237,20 @@ z.B. 2.3.0p23 - '$ver' gibt es dort nicht." return 0 ;; esac ui_run "Tarball holen: $ed $ver" bash -c \ - "cd '$PROJECT_DIR' && '$SELF' -y image download --edition '$ed' --version '$ver' --remember ${extra[*]+${extra[*]}}" || rc=1 ;; + "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y image download --edition '$ed' --version '$ver' --remember ${extra[*]+${extra[*]}}" || rc=1 ;; file) local lf lf="$(ui_pick_file "${IMAGE_DIR:-$PROJECT_DIR/images}" '*.tar.gz')" || return 0 [ -n "$lf" ] || return 0 ui_run "Image einspielen" bash -c \ - "cd '$PROJECT_DIR' && '$SELF' -y image load --file '$lf'" || rc=1 + "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y image load --file '$lf'" || rc=1 [ "$rc" = 0 ] && ui_run "Edition/Version eintragen" bash -c \ - "cd '$PROJECT_DIR' && '$SELF' -y config set CMK_EDITION '$ed' && '$SELF' -y config set CMK_VERSION '$ver'" ;; + "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y config set CMK_EDITION '$ed' && '$SELF' $SELF_ENV -y config set CMK_VERSION '$ver'" ;; setonly) # Setzt Edition, Version UND das daraus gebildete Image. # Heruntergeladen wird nichts - das erledigt "up" bei Bedarf. ui_run "Eintragen" bash -c \ - "cd '$PROJECT_DIR' && '$SELF' -y image use --edition '$ed' --version '$ver'" || rc=1 ;; + "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y image use --edition '$ed' --version '$ver'" || rc=1 ;; esac load_env "${ENV_FILE:-$PROJECT_DIR/.env}" @@ -5247,13 +5346,13 @@ Woher soll das Image geholt werden?" \ lf="$(ui_pick_file "${IMAGE_DIR:-$PROJECT_DIR/images}" '*.tar.gz')" || return 0 [ -n "$lf" ] || return 0 ui_run "Image einspielen" bash -c \ - "cd '$PROJECT_DIR' && NO_COLOR=1 '$SELF' -y image load --file '$lf'" + "cd '$PROJECT_DIR' && NO_COLOR=1 '$SELF' $SELF_ENV -y image load --file '$lf'" load_env "${ENV_FILE:-$PROJECT_DIR/.env}" return 0 ;; esac ui_run "Image holen ($sel)" bash -c \ - "cd '$PROJECT_DIR' && NO_COLOR=1 '$SELF' -y image get --source '$sel'" + "cd '$PROJECT_DIR' && NO_COLOR=1 '$SELF' $SELF_ENV -y image get --source '$sel'" load_env "${ENV_FILE:-$PROJECT_DIR/.env}" local f; f="$(mktemp)" @@ -5284,7 +5383,7 @@ gui_image_test() { [ -n "$user" ] && extra+=(--user "$user" --password "$pass") fi ui_run "Zugangsdaten pruefen" bash -c \ - "cd '$PROJECT_DIR' && NO_COLOR=1 '$SELF' image test --edition '$ed' --version '$ver' ${extra[*]+${extra[*]}}" + "cd '$PROJECT_DIR' && NO_COLOR=1 '$SELF' $SELF_ENV image test --edition '$ed' --version '$ver' ${extra[*]+${extra[*]}}" } gui_image_pull() { @@ -5298,7 +5397,7 @@ gui_image_pull() { pass="$(ui_password "Registry-Anmeldung" "Kennwort:")" || return 0 [ -n "$user" ] && extra+=(--user "$user" --password "$pass") fi - ui_run "Image holen" bash -c "cd '$PROJECT_DIR' && '$SELF' -y image pull --edition '$ed' --version '$ver' ${extra[*]+${extra[*]}}" + ui_run "Image holen" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y image pull --edition '$ed' --version '$ver' ${extra[*]+${extra[*]}}" load_env "${ENV_FILE:-$PROJECT_DIR/.env}" } @@ -5314,7 +5413,7 @@ gui_image_download() { esac user="$(ui_input "Downloadportal" "Benutzer:" "${CMK_DOWNLOAD_USER:-}")" || return 0 pass="$(ui_password "Downloadportal" "Kennwort:")" || return 0 - ui_run "Image herunterladen" bash -c "cd '$PROJECT_DIR' && '$SELF' -y image download --edition '$ed' --version '$ver' --user '$user' --password '$pass'" + ui_run "Image herunterladen" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y image download --edition '$ed' --version '$ver' --user '$user' --password '$pass'" load_env "${ENV_FILE:-$PROJECT_DIR/.env}" } @@ -5327,7 +5426,7 @@ gui_image_use() { [ ${#items[@]} -gt 0 ] || { ui_msg "Images" "Es ist kein Checkmk-Image lokal vorhanden.\n\nZuerst 'pull', 'download' oder 'load' verwenden."; return; } local sel sel="$(ui_menu "Image auswaehlen" "Lokal vorhandene Checkmk-Images:" "${items[@]}")" || return 0 - ui_run "Image setzen" bash -c "cd '$PROJECT_DIR' && '$SELF' -y image use '$sel'" + ui_run "Image setzen" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y image use '$sel'" load_env "${ENV_FILE:-$PROJECT_DIR/.env}" } @@ -5399,14 +5498,14 @@ naechsten Start selbst nach. Uebernehmen?"; then ui_run "Image setzen" bash -c \ - "cd '$PROJECT_DIR' && '$SELF' -y image use --edition '$CMK_EDITION' --version '$CMK_VERSION'" + "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y image use --edition '$CMK_EDITION' --version '$CMK_VERSION'" fi ;; angleichen) if [ -z "${CMK_IMAGE:-}" ]; then ui_msg "Nicht moeglich" "CMK_IMAGE ist nicht gesetzt." else ui_run "Vorgaben angleichen" bash -c \ - "cd '$PROJECT_DIR' && '$SELF' -y image use '$CMK_IMAGE' --remember" + "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y image use '$CMK_IMAGE' --remember" fi ;; esac load_env "${ENV_FILE:-$PROJECT_DIR/.env}" @@ -5447,9 +5546,9 @@ Uebernehmen?"; then done if [ "$key" = NPM_ADMIN_PORT ]; then - ui_run "Admin-Port setzen" bash -c "cd '$PROJECT_DIR' && '$SELF' -y npm-port '$new'" + ui_run "Admin-Port setzen" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y npm-port '$new'" elif [ "$key" = NPM_ENABLED ]; then - ui_run "Proxy Manager ${new}schalten" bash -c "cd '$PROJECT_DIR' && '$SELF' -y npm-enable '$new'" + ui_run "Proxy Manager ${new}schalten" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y npm-enable '$new'" else env_set "$key" "$new" "$opt" local hint="" @@ -5465,7 +5564,7 @@ Uebernehmen?"; then Getestet wird die Anmeldung an Registry und Downloadportal - es wird nichts heruntergeladen."; then ui_run "Zugangsdaten pruefen" bash -c \ - "cd '$PROJECT_DIR' && NO_COLOR=1 '$SELF' image test" + "cd '$PROJECT_DIR' && NO_COLOR=1 '$SELF' $SELF_ENV image test" fi ;; esac fi @@ -5569,7 +5668,7 @@ Oberflaeche des Proxy Managers darstellen." \ url) local u u="$(ui_input "Startseite" "URL:" "${NPM_ADMIN_URL:-http://127.0.0.1:81}")" || continue if [ -n "$u" ]; then NPM_ADMIN_URL="$u"; fi ;; - build) ui_run "Werkzeug-Image bauen" bash -c "cd '$PROJECT_DIR' && '$SELF' browser --build-only" || true ;; + build) ui_run "Werkzeug-Image bauen" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV browser --build-only" || true ;; back) return 0 ;; *) local burl="${NPM_ADMIN_URL:-http://127.0.0.1:81}" if ! browser_url_reachable "$burl"; then @@ -5653,13 +5752,13 @@ in einem Durchgang neu anlegen. Fortfahren?" || return 0 ui_run "Datenbank zuruecksetzen" bash -c \ - "cd '$PROJECT_DIR' && NO_COLOR=1 '$SELF' -y npm-reset" + "cd '$PROJECT_DIR' && NO_COLOR=1 '$SELF' $SELF_ENV -y npm-reset" if ui_yesno "Jetzt starten?" \ "Damit das Konto entsteht, muss der Proxy Manager neu starten. Stack jetzt starten?"; then - ui_run "Stack starten" bash -c "cd '$PROJECT_DIR' && NO_COLOR=1 '$SELF' -y up" + ui_run "Stack starten" bash -c "cd '$PROJECT_DIR' && NO_COLOR=1 '$SELF' $SELF_ENV -y up" fi load_env "${ENV_FILE:-$PROJECT_DIR/.env}" } @@ -5679,6 +5778,7 @@ Ziel : ${PROXY_FORWARD_HOST:-127.0.0.1}:${PROXY_FORWARD_PORT:-5000}" \ show "Einzelheiten eines Proxy-Hosts (mit Pfaden)" \ certs "Vorhandene Zertifikate anzeigen" \ ipzugang "HTTPS ueber die blanke IP (ohne Namen) ermoeglichen" \ + neustart "Proxy Manager neu starten / nginx neu laden" \ del "Proxy-Host loeschen" \ status "Anmeldung pruefen" \ reset "Datenbank zuruecksetzen (Konto neu anlegen lassen)" \ @@ -5696,8 +5796,9 @@ Ziel : ${PROXY_FORWARD_HOST:-127.0.0.1}:${PROXY_FORWARD_PORT:-5000}" \ certs) local f2; f2="$(mktemp)"; NO_COLOR=1 cmd_proxy certs >"$f2" 2>&1 || true ui_text "Zertifikate" "$f2"; rm -f "$f2" ;; ipzugang) gui_proxy_default || true ;; + neustart) gui_proxy_restart || true ;; del) gui_proxy_del || true ;; - status) ui_run "Anmeldung pruefen" bash -c "cd '$PROJECT_DIR' && NO_COLOR=1 '$SELF' proxy status" ;; + status) ui_run "Anmeldung pruefen" bash -c "cd '$PROJECT_DIR' && NO_COLOR=1 '$SELF' $SELF_ENV proxy status" ;; reset) gui_npm_reset || true ;; back) return 0 ;; esac @@ -5857,6 +5958,23 @@ Mehrere Anweisungen durch \\\\n trennen." "$curadv")" || continue done } +gui_proxy_restart() { + local sel + sel="$(ui_menu "Proxy Manager neu starten" \ +"Nach Aenderungen an der Zusatzkonfiguration - etwa am Standard-Server +fuer den IP-Zugang oder am Adminport - muss nginx sie erst einlesen. + +Neu laden genuegt dafuer und unterbricht keine Verbindung. Ein Neustart +des Containers ist nur noetig, wenn sich Umgebungsvariablen geaendert +haben oder nginx gar nicht mehr antwortet." \ + reload "nginx neu laden (ohne Unterbrechung)" \ + restart "Container neu starten (kurze Unterbrechung)" \ + back "zurueck")" || return 0 + case "$sel" in back) return 0 ;; esac + ui_run "Proxy Manager: $sel" bash -c "cd '$PROJECT_DIR' && NO_COLOR=1 '$SELF' $SELF_ENV proxy $sel" || true + return 0 +} + gui_proxy_default() { local f rc=0 f="$(mktemp)" @@ -5880,7 +5998,7 @@ Aufrufe mit Namen bleiben unberuehrt." \ case "$sel" in back) return 0 ;; aus) ui_run "Standard-Server entfernen" bash -c \ - "cd '$PROJECT_DIR' && NO_COLOR=1 '$SELF' proxy default --off --restart" || true + "cd '$PROJECT_DIR' && NO_COLOR=1 '$SELF' $SELF_ENV proxy default --off --restart" || true return 0 ;; esac @@ -5997,7 +6115,7 @@ Einen bereits vorhandenen Eintrag fuer diesen Namen ersetzen? bricht ab, falls es ihn schon gibt"; then upd=--update; fi ui_run "Proxy-Host anlegen" bash -c \ - "cd '$PROJECT_DIR' && NO_COLOR=1 '$SELF' -y proxy add --domain '$dom' \ + "cd '$PROJECT_DIR' && NO_COLOR=1 '$SELF' $SELF_ENV -y proxy add --domain '$dom' \ --forward-port '$fport' --cert '$cert' $upd ${locopt[*]+${locopt[*]}}" # Die Vorgaben merken, damit der naechste Aufruf sie kennt @@ -6015,7 +6133,7 @@ gui_proxy_del() { [ -n "$id" ] || return 0 case "$id" in ''|*[!0-9]*) ui_msg "Ungueltig" "Bitte eine Zahl angeben."; return 0 ;; esac ui_yesno "Loeschen" "Proxy-Host $id wirklich loeschen?" || return 0 - ui_run "Proxy-Host loeschen" bash -c "cd '$PROJECT_DIR' && '$SELF' -y proxy del --id '$id'" + ui_run "Proxy-Host loeschen" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y proxy del --id '$id'" } gui_cert() { @@ -6026,7 +6144,7 @@ gui_cert() { days="$(ui_input "Zertifikat" "Gueltigkeit in Tagen:" "${CERT_DAYS:-3650}")" || days=3650 local -a a=(); local x for x in $alt; do a+=(--alt "$x"); done - ui_run "Zertifikat erzeugen" bash -c "cd '$PROJECT_DIR' && '$SELF' cert --domain '$domain' --days '$days' ${a[*]+${a[*]}}" + ui_run "Zertifikat erzeugen" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV cert --domain '$domain' --days '$days' ${a[*]+${a[*]}}" } # Bericht anzeigen; fehlt etwas, das Uebernehmen anbieten @@ -6077,9 +6195,9 @@ Nein = Freigabe fuer alle Quellen"; then local -a a=(firewall "${opt[@]}" --apply --yes) if [ "$(id -u)" -eq 0 ]; then - ui_run "Firewall-Regeln uebernehmen" "$SELF" "${a[@]}" || true + ui_run "Firewall-Regeln uebernehmen" "$SELF" ${SELF_ENV_ARR[@]+"${SELF_ENV_ARR[@]}"} "${a[@]}" || true elif command -v sudo >/dev/null 2>&1; then - gui_run_interactive sudo -- "$SELF" "${a[@]}" + gui_run_interactive sudo -- "$SELF" ${SELF_ENV_ARR[@]+"${SELF_ENV_ARR[@]}"} "${a[@]}" else ui_msg "Firewall" "Dafuer werden root-Rechte benoetigt. Bitte als root erneut aufrufen." @@ -6124,9 +6242,9 @@ Nein = nur noch lokal (Terminal-Browser oder SSH-Tunnel)"; then fi fi if [ "$(id -u)" -eq 0 ]; then - ui_run "Ports schliessen" "$SELF" "${a[@]}" || true + ui_run "Ports schliessen" "$SELF" ${SELF_ENV_ARR[@]+"${SELF_ENV_ARR[@]}"} "${a[@]}" || true elif command -v sudo >/dev/null 2>&1; then - gui_run_interactive sudo -- "$SELF" "${a[@]}" + gui_run_interactive sudo -- "$SELF" ${SELF_ENV_ARR[@]+"${SELF_ENV_ARR[@]}"} "${a[@]}" else ui_msg "Firewall" "Dafuer werden root-Rechte benoetigt. Bitte als root erneut aufrufen." @@ -7131,6 +7249,10 @@ main() { esac done + if [ -n "$ENVFILE_OPT" ]; then + SELF_ENV="--env-file '$ENVFILE_OPT'" + SELF_ENV_ARR=(--env-file "$ENVFILE_OPT") + fi load_env "${ENVFILE_OPT:-$PROJECT_DIR/.env}" detect_runtime UI_BACKTITLE="Checkmk Stack Manager - Runtime: $RUNTIME"