Grafana als weiterer Pfad - und "proxy check", damit 502 nicht raten heisst

Ob ein Dienst unter einem Pfad liegen kann, entscheidet der Dienst, nicht
der Proxy: er muss den Praefix kennen und in jede erzeugte Adresse
einsetzen. Checkmk kann das von Haus aus, die Oberflaeche des Proxy
Managers gar nicht - Grafana kann es, wenn man es ihm sagt:

  GF_SERVER_ROOT_URL=https://<ip>/grafana/
  GF_SERVER_SERVE_FROM_SUB_PATH=true

Damit setzt Grafana <base href="/grafana/"> in seine Seiten. An Grafana
13.0.2 hinter dem Proxy Manager gemessen, ueber die IP ohne SNI:
/grafana/ liefert 302 auf /grafana/login, die Anmeldeseite 200, die
Dateien unter /grafana/public/... ebenfalls 200, und POST
/grafana/login meldet 200. Ohne die beiden Zeilen leitet Grafana auf
/login um - also auf die Wurzel, wo etwas anderes liegt.

Neu ist ausserdem "proxy check". Es fragt jedes Ziel eines Proxy-Hosts
AUS DEM PROXY-CONTAINER HERAUS ab, denn von dort baut nginx die
Verbindung auf:

  PFAD      ZIEL                               ANTWORT
  /         http://127.0.0.1:81                HTTP 200
  /grafana  http://127.0.0.1:3000              HTTP 302
  /cmk      http://127.0.0.1:9999              nicht erreichbar

Damit faellt ein Tippfehler in der Zieladresse auf, bevor der Browser
502 zeigt - der Anlass war genau so einer. In der Oberflaeche liegt das
unter Proxy-Hosts > "Ziele pruefen".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-20 21:57:53 +02:00
co-authored by Claude Opus 5
parent f02692e8be
commit 81ff194bd1
3 changed files with 223 additions and 1 deletions
+85 -1
View File
@@ -3940,6 +3940,23 @@ npm_reload_hint() { # restart-flag
fi
}
# Ein Ziel aus Sicht des Proxy-Containers pruefen - von dort aus baut
# nginx die Verbindung auf, nicht von diesem Rechner.
proxy_check_one() { # pfad schema host port
local path="$1" sch="$2" host="$3" port="$4" code
code="$($RUNTIME exec "$NPM_CONTAINER_NAME" \
curl -s -o /dev/null -k --max-time 5 -w '%{http_code}' \
"$sch://$host:$port/" 2>/dev/null)" || code=000
case "${code:-000}" in
000) printf ' %-9s %-34s %b\n' "$path" "$sch://$host:$port" \
"${C_RED}nicht erreichbar${C_RST}"
return 1 ;;
*) printf ' %-9s %-34s %b\n' "$path" "$sch://$host:$port" \
"${C_GRN}HTTP $code${C_RST}"
return 0 ;;
esac
}
cmd_proxy() {
local sub="${1:-list}"; [ $# -gt 0 ] && shift || true
@@ -4025,6 +4042,69 @@ cmd_proxy() {
echo
return 0 ;;
check|test)
local pid="" dom=""
while [ $# -gt 0 ]; do
case "$1" in
--id) pid="$2"; shift 2 ;;
--domain) dom="$2"; shift 2 ;;
*) die "Unbekannte Option fuer 'proxy check': $1" ;;
esac
done
npm_require_running || return 1
NPM_TOKEN="$(npm_api_token)" || return 1
local all i
all="$(npm_api GET /api/nginx/proxy-hosts)"
local -a ids=()
if [ -n "$pid" ]; then
ids=("$pid")
elif [ -n "$dom" ]; then
for i in $(json_ids "$all"); do
if ( set +o pipefail; npm_api GET "/api/nginx/proxy-hosts/$i" | grep -qF "\"$dom\"" ); then
ids=("$i"); break
fi
done
[ "${#ids[@]}" -gt 0 ] || die "Kein Proxy-Host fuer '$dom' gefunden."
else
mapfile -t ids < <(json_ids "$all")
fi
if [ "${#ids[@]}" -eq 0 ]; then
warn "Es gibt keine Proxy-Hosts."; return 0
fi
local fehler=0 o d sch host port el
for i in "${ids[@]}"; do
o="$(npm_api GET "/api/nginx/proxy-hosts/$i")"
[ -n "$(json_num "$o" id)" ] || { warn "Proxy-Host $i gibt es nicht."; continue; }
d="$(printf '%s' "$o" | sed -n 's/.*"domain_names"[[:space:]]*:[[:space:]]*\[[[:space:]]*"\([^"]*\)".*/\1/p')"
printf '\n%sProxy-Host %s %s%s\n' "$C_BLD" "$i" "${d:-?}" "$C_RST"
printf ' %-9s %-34s %s\n' "PFAD" "ZIEL" "ANTWORT"
sch="$(json_str "$o" forward_scheme)"; [ -n "$sch" ] || sch=http
host="$(json_str "$o" forward_host)"; port="$(json_num "$o" forward_port)"
proxy_check_one "/" "$sch" "$host" "$port" || fehler=$((fehler+1))
while IFS= read -r el; do
[ -n "$el" ] || continue
sch="$(json_str "$el" forward_scheme)"; [ -n "$sch" ] || sch=http
host="$(json_str "$el" forward_host)"; port="$(json_num "$el" forward_port)"
proxy_check_one "$(json_str "$el" path)" "$sch" "$host" "$port" || fehler=$((fehler+1))
done < <(json_split_array "$(json_raw "$o" locations)")
done
echo
if [ "$fehler" -eq 0 ]; then
ok "Alle Ziele antworten."
echo; return 0
fi
err "$fehler Ziel(e) antworten nicht - dort meldet nginx 502 Bad Gateway."
printf ' Haeufigste Ursachen: Tippfehler in der Adresse (127.0.0.1 statt
172.0.0.1), der Dienst laeuft nicht, oder er lauscht nur auf einer
anderen Schnittstelle.
Aendern mit: %s proxy edit --id N --location /pfad=host:port\n\n' "$SELF"
return 1 ;;
admin|adminui)
local dom="" root="" off="" pid="" host="" path="" cert=self
while [ $# -gt 0 ]; do
@@ -4744,7 +4824,7 @@ EOF
*) die "Unbekanntes Unterkommando 'proxy $sub'.
Moeglich: status | list | show | certs | add | edit | del | default
| admin | reload | restart" ;;
| admin | check | reload | restart" ;;
esac
}
@@ -5976,6 +6056,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" \
pruefen "Ziele pruefen - antwortet hinter jedem Pfad etwas?" \
adminui "Adminoberflaeche erreichbar machen (Name oder Wurzel)" \
neustart "Proxy Manager neu starten / nginx neu laden" \
del "Proxy-Host loeschen" \
@@ -5995,6 +6076,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 ;;
pruefen) local fp; fp="$(mktemp)"
( NO_COLOR=1 cmd_proxy check ) >"$fp" 2>&1 || true
ui_text "Ziele der Proxy-Hosts" "$fp"; rm -f "$fp" ;;
adminui) gui_proxy_admin || true ;;
neustart) gui_proxy_restart || true ;;
del) gui_proxy_del || true ;;