Routing Problem nginx+fhem in Docker

Begonnen von NehCoy, 01 Januar 2024, 15:00:09

Vorheriges Thema - Nächstes Thema

NehCoy

Hallo zusammen (und erstmal noch alles Gute für 2024)!

Ich versuche mich gerade darin, meine FHEM Installation zu containerisieren und auf einen neuen Homeserver zu verlagern.
Das Webseiten-Routing soll über nginx gelöst werden, da auch weitere Projekte parallel laufen werden.
Die grundlegende Inbetriebnahme hat soweit funktioniert. Mein nginx-Config File sieht aktuell wie folgt aus:
events {
    worker_connections 1024;
}

http {
    server {
        listen 80;
        server_name dev.fritz.box;

        location /fhem {
            proxy_pass http://fhem:8083;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_read_timeout 10;
            proxy_buffering off;
        }
    }
}

Mein Problem ist aber, dass die Webseite nicht automatisch aktualisiert wird. Wenn ich zum Beispiel auf ein Symbol zum einschalten des Lichts klicke, wird das Licht korrekt geschaltet. Das Symbol zeigt aber weiterhin des ausgeschalteten Zustand. Erst wenn ich die Seite manuell neu lade wird das Symbol für den eingeschalteten Zustand korrekt angezeigt und ich kann es auch wieder ausschalten.

Im Trace Output wird mir nach dem konfigurierten Timeout von 10 Sekunden folgender Fehler angezeigt:
nginx_1    | 2024/01/01 13:49:11 [error] 22#22: *54 upstream timed out (110: Connection timed out) while reading upstream, client: 192.168.160.1, server: dev.fritz.box, request: "GET /fhem?XHR=1&inform=type%3Dstatus%3Bfilter%3Droom%3DKeller%3Bsince%3D1704115399.53455%3Bfmt%3DJSON&fw_id=1704115400.53456&timestamp=1704116886119 HTTP/1.1", upstream: "http://192.168.160.2:8083/fhem?XHR=1&inform=type%3Dstatus%3Bfilter%3Droom%3DKeller%3Bsince%3D1704115399.53455%3Bfmt%3DJSON&fw_id=1704115400.53456&timestamp=1704116886119", host: "localhost"
192.168.160.2 ist die IP-Adresse des FHEM Containers, 192.168.160.3 ist die IP-Adresse des nginx Containers im Docker Netzwerk.
Weiß jemand, wie ich dieses Routing-Probleme beheben kann?

Danke für die Hilfe!

Viele Grüße
NehCoy

Edit 01.01.2024-15:19Uhr:
Ich habe festgestellt, dass minütlich der selbe GET-Request abgesetzt wird und zeitgleich im Webbrowser "Connection loss" von FHEM gemeldet wird, der kurz daruf wieder verschwindet.
Zitatnginx_1    | 192.168.10.152 - - [01/Jan/2024:14:18:06 +0000] "GET /fhem?XHR=1&inform=type%3Dstatus%3Bfilter%3Droom%3DKeller%3Bsince%3D1704118605.06678%3Bfmt%3DJSON&fw_id=1704118606.06678&timestamp=1704118631413 HTTP/1.1" 200 6 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0"
nginx_1    | 192.168.10.152 - - [01/Jan/2024:14:19:06 +0000] "GET /fhem?XHR=1&inform=type%3Dstatus%3Bfilter%3Droom%3DKeller%3Bsince%3D1704118605.06678%3Bfmt%3DJSON&fw_id=1704118606.06678&timestamp=1704118692437 HTTP/1.1" 200 6 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0"
nginx_1    | 192.168.10.152 - - [01/Jan/2024:14:20:07 +0000] "GET /fhem?XHR=1&inform=type%3Dstatus%3Bfilter%3Droom%3DKeller%3Bsince%3D1704118605.06678%3Bfmt%3DJSON&fw_id=1704118606.06678&timestamp=1704118752841 HTTP/1.1" 200 6 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0"
nginx_1    | 192.168.10.152 - - [01/Jan/2024:14:21:07 +0000] "GET /fhem?XHR=1&inform=type%3Dstatus%3Bfilter%3Droom%3DKeller%3Bsince%3D1704118605.06678%3Bfmt%3DJSON&fw_id=1704118606.06678&timestamp=1704118813683 HTTP/1.1" 200 6 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0"
nginx_1    | 192.168.10.152 - - [01/Jan/2024:14:22:07 +0000] "GET /fhem?XHR=1&inform=type%3Dstatus%3Bfilter%3Droom%3DKeller%3Bsince%3D1704118605.06678%3Bfmt%3DJSON&fw_id=1704118606.06678&timestamp=1704118873697 HTTP/1.1" 200 6 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0"
nginx_1    | 192.168.10.152 - - [01/Jan/2024:14:23:08 +0000] "GET /fhem?XHR=1&inform=type%3Dstatus%3Bfilter%3Droom%3DKeller%3Bsince%3D1704118605.06678%3Bfmt%3DJSON&fw_id=1704118606.06678&timestamp=1704118933061 HTTP/1.1" 200 6 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0"

In der Netzwerkanalyse von Firefox sieht man, dass die Anfrage zyklisch aus dem JavaScript kommt.
Komischerweise wird der Status-Code mit 200 angegeben, obwohl als Fehler "NS_ERROR_WEBSOCKET_CONNECTION_REFUSED" angegeben wird.

Edit 2 01.01.2024-15:49Uhr:
Ich habe diesen Artikel gefunden und mein nginx.config file angepasst.
Damit ist nun das Verbindungsproblem angeblich gelöst. Statuscode ist nun 101. Aber das Icon wird noch immer nicht automatisch aktualisiert.  :(

passibe

#1
Servus,

das sieht nach einem Websocket-Problem aus. Dein Fix aus dem Artikel dürfte für reguläre Anwendungen, die Websockets verwenden, passen, bei FHEM muss das aber irgendwie (frag mich nicht wieso) noch ein klein bisschen anders sein (siehe unten). Deshalb Folgendes:

1. Falls noch nicht geschehen Websocket aktivieren ("WEB" durch dein FHEMWEB-Device ersetzen):
attr WEB longpoll websocket
2. NGINX-Config anpassen (habe den relevanten Teil damals von hier unter "Inhalt der Datei reverse-proxy" übernommen):
location /fhem {
        set $my_http_upgrade "";
        set $my_connection "Connection";
        if ($http_upgrade = "websocket") {
          set $my_http_upgrade $http_upgrade;
          set $my_connection "upgrade";
        }
        proxy_set_header Upgrade $my_http_upgrade;
        proxy_set_header Connection $my_connection;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Host $host:$server_port;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_read_timeout 10;
        proxy_buffering off;

        set $upstream fhem:8083;
        proxy_pass http://$upstream;
    }

Übrigens: proxy_pass mittels der Variable $upstream zu füttern hat – soweit ich mich erinnere – den Vorteil, dass nginx auch dann startet, wenn FHEM in dem Zeitpunkt, wo nginx startet, nicht erreichbar ist. Müsstest du aber nochmal googeln, falls dich das interessiert, ist etwas länger her bei mir.
Was ich noch hinzufüge ist ein proxy_intercept_errors on; das hat den Vorteil, dass man dann Error-Seiten von nginx ausgeben kann und die dann für alle Services die man proxied einheitlich sind.

Ansonsten bietet es sich zur Verschlankung der nginx-Config auch an, die Direktiven
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_intercept_errors on;
in einer Datei z.B. "proxy-default" zusammenzufassen und dann z.B. immer mittelsinclude conf.d/proxy-default; im jeweiligen Location-Block einzufügen.

Hoffe das hilft!

NehCoy

Hallo passibe!

Danke für deine Antwort und deine Tipps!
Das mit den Variablen will bei mir irgendwie nicht klappen! Wenn ich
proxy_pass http://fhem:8083; durch
set $upstream fhem:8083;
 proxy_pass http://$upstream;
ersetze, erhalte ich beim Aufruf der Webseite einen Fehlercode 502 (Bad Gateway). Ich starte die Container über ein Docker Compose File. Der nginx-Container ist dabei vom FHEM Container abhängig.

Viele Grüße
NehCoy

passibe

Ah, vermutlich musst du dann den Docker-DNS-Server setzen. Komisch aber, dass es bei dir oben direkt mit proxy_pass http://fhem:8083; funktioniert hat.

Versuch mal nach server_name ein
resolver 127.0.0.11 valid=30s ipv6=off;einzufügen.

Ansonsten kannst du – falls es nicht stört und damit funktioniert – das mit der Variable auch einfach weglassen.

Wernieman

Wobei .... warum so kompliziert?
        location /fhem {
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-Server $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_pass http://<IP-VON-FHEM-CONTAINER>:80;
                client_max_body_size 128M;
                proxy_read_timeout 90;
                proxy_buffering off;
        }
<IP-VON-FHEM-CONTAINER> lasse ich automatisch ermitteln ... und ja, FHEM-Web hört bei mir im Container auf Port 80. Da bei mir nginx auf dem Host läuft, kann nginx direkt auf fhem per Container-IP zugreifen. Funzt jedenfalls bei mir seit Jahren ...
- Bitte um Input für Output
- When there is a Shell, there is a Way
- Wann war Dein letztes Backup?

Wie man Fragen stellt: https://tty1.net/smart-questions_de.html

passibe

Hm, fair enough, deine Konfiguration funktioniert auch (dann natürlich mit attr WEB longpoll 1). Keine Ahnung wieso ich das damals mit Websocket gemacht habe – läuft bei mir jedenfalls auch schon seit Ewigkeiten problemlos so.

Nur:
Zitat von: Wernieman am 05 Januar 2024, 14:49:11<IP-VON-FHEM-CONTAINER> lasse ich automatisch ermitteln
Das ist ja gerade das Elegante daran, nginx auch in Docker laufen zu lassen, dann kann man einfach den Docker-DNS-Server benutzen und alle Container direkt mit ihren jeweiligen Hostnamen (bzw. dem container_name aus dem Compose-File) ansprechen und muss nichts (vermutlich über irgendeinen weiteren Service?) "automatisch ermitteln lassen".

Aber wie immer führen natürlich mehrere Wege zum Ziel.

Wernieman

Da ich so einige Container-Systeme verwende, habe ich eben einen "globalen" nginx Proxy davor, weil ich die Container eben NICHT im gleichen Netzwerk laufen lassen möchte, was sonst nötig wäre.

Hatte ich mal für einen Arbeitgeber "entwickelt" ..... hat dann sogar den Vorteil, das bei abgeschalteten Container eine passende "Fehlerseite" ausgegeben werden kann ;o)

Und p.s. longpoll habe ich bei mir nicht gesetzt.
- Bitte um Input für Output
- When there is a Shell, there is a Way
- Wann war Dein letztes Backup?

Wie man Fragen stellt: https://tty1.net/smart-questions_de.html