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:
@@ -1228,6 +1228,7 @@ erzwingen, HTTP/2 und Websockets einschalten und den empfohlenen
|
||||
| `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 admin --domain X` / `--root` | Adminoberfläche erreichbar machen – per Name oder über die Wurzel |
|
||||
| `proxy check` | antwortet hinter jedem Pfad etwas? (aus dem Proxy-Container geprüft) |
|
||||
| `proxy reload` | nginx die Konfiguration neu einlesen lassen – ohne Unterbrechung |
|
||||
| `proxy restart` | den Proxy-Manager-Container neu starten |
|
||||
|
||||
@@ -1677,6 +1678,75 @@ bei Variante A. Ohne Angabe zeigt `proxy admin` den Stand.
|
||||
In der Oberfläche liegt beides unter **Proxy-Hosts → Adminoberfläche erreichbar
|
||||
machen**.
|
||||
|
||||
### 10.12 Weitere Dienste dazunehmen – Beispiel Grafana
|
||||
|
||||
Mit einem einzigen freien Port lassen sich mehrere Dienste über Pfade
|
||||
auseinanderhalten:
|
||||
|
||||
```
|
||||
https://172.0.250.82/ Adminoberfläche des Proxy Managers
|
||||
https://172.0.250.82/cmk/ Checkmk
|
||||
https://172.0.250.82/grafana/ Grafana
|
||||
```
|
||||
|
||||
Ob ein Dienst das mitmacht, hängt an ihm selbst – nicht am Proxy. Er muss
|
||||
wissen, dass er unter einem Präfix liegt, und ihn in jede Adresse einsetzen,
|
||||
die er erzeugt. Checkmk kann das von Haus aus (der Site-Pfad *ist* der
|
||||
Präfix), die Oberfläche des Proxy Managers kann es gar nicht
|
||||
([Kapitel 10.11](#1011-die-adminoberfläche-des-proxy-managers-erreichbar-machen)),
|
||||
**Grafana kann es, wenn man es ihm sagt**:
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml, Dienst grafana
|
||||
environment:
|
||||
GF_SERVER_ROOT_URL: "https://172.0.250.82/grafana/"
|
||||
GF_SERVER_SERVE_FROM_SUB_PATH: "true"
|
||||
```
|
||||
|
||||
Gleichwertig in der `grafana.ini`:
|
||||
|
||||
```ini
|
||||
[server]
|
||||
root_url = https://172.0.250.82/grafana/
|
||||
serve_from_sub_path = true
|
||||
```
|
||||
|
||||
Damit setzt Grafana ein `<base href="/grafana/" />` in seine Seiten, und alle
|
||||
Dateien werden relativ dazu geladen. Ohne die beiden Zeilen leitet es auf
|
||||
`/login` um – also auf die Wurzel, wo etwas ganz anderes liegt. Gemessen:
|
||||
|
||||
| Grafana-Einstellung | `/grafana/login` | Dateien der Seite |
|
||||
|---|---|---|
|
||||
| ohne `serve_from_sub_path` | 302 auf `/login` | gehen an die Wurzel |
|
||||
| mit `root_url` + `serve_from_sub_path` | 200 | `/grafana/public/…` → 200 |
|
||||
|
||||
Auf der Proxy-Seite ist es dann ein Pfad mehr:
|
||||
|
||||
```bash
|
||||
./scripts/cmk-manage.sh proxy edit --id 1 --location /grafana=127.0.0.1:3000
|
||||
./scripts/cmk-manage.sh proxy default --domain <name> --restart # falls eingerichtet
|
||||
./scripts/cmk-manage.sh proxy check
|
||||
```
|
||||
|
||||
`proxy check` fragt jedes Ziel **aus dem Proxy-Container heraus** ab – von dort
|
||||
baut nginx die Verbindung auf, nicht von deinem Arbeitsplatz:
|
||||
|
||||
```
|
||||
Proxy-Host 1 stack.local
|
||||
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
|
||||
```
|
||||
|
||||
Genau so findet man einen Tippfehler in der Zieladresse, bevor der Browser
|
||||
`502 Bad Gateway` zeigt. In der Oberfläche liegt das unter **Proxy-Hosts →
|
||||
Ziele prüfen**.
|
||||
|
||||
> Port **3000 bleibt in der Firewall zu**. Grafana wird ausschließlich über den
|
||||
> Proxy erreicht, genau wie Checkmk auf 5000. `firewall close` bietet einen
|
||||
> versehentlich geöffneten Port wieder an.
|
||||
|
||||
---
|
||||
|
||||
## 11. Proxy Manager lokal einrichten (Terminal-Browser)
|
||||
|
||||
@@ -1227,6 +1227,7 @@ HTTPS, enables HTTP/2 and websockets, and sets the recommended
|
||||
| `proxy default --domain X` | enable HTTPS on the bare IP (mirrors X into a default server) |
|
||||
| `proxy default --off` | remove that mirror again |
|
||||
| `proxy admin --domain X` / `--root` | make the admin interface reachable – by name or via the root |
|
||||
| `proxy check` | does something answer behind each path? (checked from inside the proxy container) |
|
||||
| `proxy reload` | make nginx re-read its configuration – without interruption |
|
||||
| `proxy restart` | restart the Proxy Manager container |
|
||||
|
||||
@@ -1668,6 +1669,73 @@ option A. Without arguments `proxy admin` shows the current state.
|
||||
|
||||
The GUI has both under **Proxy-Hosts → Adminoberfläche erreichbar machen**.
|
||||
|
||||
### 10.12 Adding more services – Grafana as an example
|
||||
|
||||
A single free port is enough to keep several services apart by path:
|
||||
|
||||
```
|
||||
https://172.0.250.82/ Proxy Manager admin interface
|
||||
https://172.0.250.82/cmk/ Checkmk
|
||||
https://172.0.250.82/grafana/ Grafana
|
||||
```
|
||||
|
||||
Whether a service plays along is up to the service, not the proxy. It has to
|
||||
know that it lives under a prefix and put that prefix into every address it
|
||||
generates. Checkmk does this natively (the site path *is* the prefix), the
|
||||
Proxy Manager's interface cannot do it at all
|
||||
([chapter 10.11](#1011-making-the-proxy-managers-admin-interface-reachable)),
|
||||
and **Grafana can, once you tell it**:
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml, service grafana
|
||||
environment:
|
||||
GF_SERVER_ROOT_URL: "https://172.0.250.82/grafana/"
|
||||
GF_SERVER_SERVE_FROM_SUB_PATH: "true"
|
||||
```
|
||||
|
||||
Equivalent in `grafana.ini`:
|
||||
|
||||
```ini
|
||||
[server]
|
||||
root_url = https://172.0.250.82/grafana/
|
||||
serve_from_sub_path = true
|
||||
```
|
||||
|
||||
With that Grafana puts a `<base href="/grafana/" />` into its pages and loads
|
||||
every file relative to it. Without those two lines it redirects to `/login` –
|
||||
the root, where something else lives entirely. Measured:
|
||||
|
||||
| Grafana setting | `/grafana/login` | page assets |
|
||||
|---|---|---|
|
||||
| without `serve_from_sub_path` | 302 to `/login` | go to the root |
|
||||
| with `root_url` + `serve_from_sub_path` | 200 | `/grafana/public/…` → 200 |
|
||||
|
||||
On the proxy side it is one more path:
|
||||
|
||||
```bash
|
||||
./scripts/cmk-manage.sh proxy edit --id 1 --location /grafana=127.0.0.1:3000
|
||||
./scripts/cmk-manage.sh proxy default --domain <name> --restart # if set up
|
||||
./scripts/cmk-manage.sh proxy check
|
||||
```
|
||||
|
||||
`proxy check` queries every target **from inside the proxy container** – that
|
||||
is where nginx opens the connection from, not your workstation:
|
||||
|
||||
```
|
||||
Proxy-Host 1 stack.local
|
||||
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
|
||||
```
|
||||
|
||||
That is how you find a typo in a target address before the browser shows
|
||||
`502 Bad Gateway`. The GUI has it under **Proxy-Hosts → Ziele prüfen**.
|
||||
|
||||
> Port **3000 stays closed in the firewall**. Grafana is reached exclusively
|
||||
> through the proxy, just like Checkmk on 5000. `firewall close` offers an
|
||||
> accidentally opened port for closing again.
|
||||
|
||||
---
|
||||
|
||||
## 11. Configuring the Proxy Manager locally (terminal browser)
|
||||
|
||||
+85
-1
@@ -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 ;;
|
||||
|
||||
Reference in New Issue
Block a user