diff --git a/README.md b/README.md index e152f0b..6bbbe07 100644 --- a/README.md +++ b/README.md @@ -231,8 +231,20 @@ aus. Ohne das erscheint dort keine Leiste, und in der Konsole steht nur `ERR_BLOCKED_BY_RESPONSE.NotSameOriginAfterDefaultedToSameOriginByCoep`. Das COEP der App bleibt dabei unangetastet — ihre eigenen Fähigkeiten also auch. -**Fertiges Beispiel:** [`beispiele/bentopdf/`](beispiele/bentopdf/) — Compose -und nginx-Konfiguration, so getestet. +**Fertige Beispiele:** + +- [`beispiele/bentopdf/`](beispiele/bentopdf/) — ein Dienst, kürzestmöglich. +- [`beispiele/mehrere-apps/`](beispiele/mehrere-apps/) — **ein** Einsetzer für + alle Dienste. Am Host erkennt nginx, welcher gemeint ist; eine neue App sind + zwei Zeilen in den Tabellen oben in der Datei. Das ist der Aufbau, den man + haben will, sobald es mehr als ein Werkzeug ist — nicht ein Behälter je App. + +Damit ein gemeinsamer Einsetzer die Dienste erreicht, teilen sie sich ein Netz +(`docker network create honeybar`, in jeder App-Compose-Datei als `external` +eintragen). Ein Host, der in der Tabelle fehlt, bekommt **404** statt einer +geratenen Weiterleitung — sonst wird aus einem Tippfehler in Pangolin eine +stille Umleitung irgendwohin. WebSocket-Verbindungen (Uptime Kuma, Dashboards, +alles mit Live-Anzeige) gehen durch, dafür sorgt `upgrade.conf`. **Nur Pangolin davor?** Traefik kann Antwortkörper nicht von sich aus ändern; dafür bräuchte es ein Plugin. Der kürzere Weg ist ein kleiner nginx *zwischen* diff --git a/beispiele/mehrere-apps/docker-compose.yml b/beispiele/mehrere-apps/docker-compose.yml new file mode 100644 index 0000000..3f6391e --- /dev/null +++ b/beispiele/mehrere-apps/docker-compose.yml @@ -0,0 +1,34 @@ +# ───────────────────────────────────────────────────────────── +# Ein Einsetzer für mehrere Dienste. +# +# Pangolin → leiste → (bentopdf | uptime-kuma | …) +# +# Die Dienste selbst liegen in ihren eigenen Compose-Dateien. Damit der +# Einsetzer sie erreicht, teilen sie sich ein Netz: +# +# docker network create honeybar +# +# und in jeder App-Compose-Datei: +# +# networks: [default, honeybar] +# networks: +# honeybar: +# external: true +# +# Danach in Pangolin jede Ressource auf leiste:80 zeigen lassen. +# ───────────────────────────────────────────────────────────── +services: + leiste: + image: nginx:alpine + container_name: honeybar-leiste + restart: unless-stopped + volumes: + - ./upgrade.conf:/etc/nginx/conf.d/00-upgrade.conf:ro + - ./leiste.conf:/etc/nginx/conf.d/default.conf:ro + ports: + - "127.0.0.1:8185:80" + networks: [honeybar] + +networks: + honeybar: + external: true diff --git a/beispiele/mehrere-apps/leiste.conf b/beispiele/mehrere-apps/leiste.conf new file mode 100644 index 0000000..237f6b9 --- /dev/null +++ b/beispiele/mehrere-apps/leiste.conf @@ -0,0 +1,63 @@ +# ───────────────────────────────────────────────────────────────────────────── +# Ein Einsetzer für alle Dienste, die die Leiste tragen sollen. +# +# Pangolin gibt den ursprünglichen Host weiter; daran erkennt nginx, welcher +# Dienst gemeint ist. Eine neue App heisst: zwei Zeilen in den Tabellen unten, +# neu laden, fertig — kein weiterer Behälter. +# ───────────────────────────────────────────────────────────────────────────── + +# Wohin durchgereicht wird. Links der Name, unter dem du die App aufrufst, +# rechts Behältername und Port im Docker-Netz. +map $host $ziel { + default ""; + pdf.honeyos.duckdns.org "bentopdf:8080"; + status.honeyos.duckdns.org "uptime-kuma:3001"; +} + +# Welche App das für HoneyOS ist. Muss der id in der App-Liste entsprechen — +# daran erkennt die Leiste, wo man gerade ist, und hebt sie hervor. +map $host $appid { + default ""; + pdf.honeyos.duckdns.org "bentopdf"; + status.honeyos.duckdns.org "status"; +} + +server { + listen 80; + server_name _; + + # Für ein proxy_pass mit Variable braucht nginx einen Namensauflöser — + # im Docker-Netz ist das der eingebaute unter 127.0.0.11. + resolver 127.0.0.11 valid=30s ipv6=off; + + # Unbekannter Host: nicht raten, sondern ablehnen. Sonst wird aus einem + # Tippfehler in Pangolin eine stille Weiterleitung irgendwohin. + if ($ziel = "") { return 404; } + + location / { + proxy_pass http://$ziel; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Real-IP $remote_addr; + + # WebSockets durchlassen — viele Werkzeuge (Uptime Kuma, Dashboards, + # alles mit Live-Anzeige) brechen sonst ab. + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + + # Unkomprimiert anfordern, sonst ist im Strom nichts zu ersetzen. + proxy_set_header Accept-Encoding ""; + + # Nur HTML anfassen; alles andere geht unberührt durch. + sub_filter_types text/html; + sub_filter_once on; + sub_filter '' + ''; + + # Lange Antworten nicht künstlich aufhalten (Downloads, Fortschritt). + proxy_buffering off; + proxy_read_timeout 300s; + } +} diff --git a/beispiele/mehrere-apps/upgrade.conf b/beispiele/mehrere-apps/upgrade.conf new file mode 100644 index 0000000..f48caf2 --- /dev/null +++ b/beispiele/mehrere-apps/upgrade.conf @@ -0,0 +1,6 @@ +# Gehört nach /etc/nginx/conf.d/, aber ausserhalb eines server-Blocks: +# „Connection: upgrade" nur dann setzen, wenn der Browser das auch will. +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +}