server { # Nginx lauscht auf Port 80 (Standard HTTP-Port). # Der Browser spricht Nginx an — Nginx entscheidet dann wohin die Anfrage geht (Reverse Proxy). listen 80; # Statische React-Dateien ausliefern (HTML, CSS, JS). # Vite baut die App in einen dist-Ordner — dieser wird beim Docker-Build nach /usr/share/nginx/html kopiert. location / { root /usr/share/nginx/html; index index.html; # try_files: Nginx sucht zuerst nach einer echten Datei ($uri), # dann nach einem Ordner ($uri/), und fällt schliesslich auf index.html zurück. # Warum nötig: React ist eine Single Page Application (SPA) — alle Routen # existieren nur im Browser, nicht als echte Dateien auf dem Server. # Ohne diesen Fallback würde ein direkter Aufruf von z.B. /chat einen 404 liefern. try_files $uri $uri/ /index.html; } # Reverse Proxy: Alle Anfragen an /rooms werden an das Backend weitergeleitet. # Warum Reverse Proxy statt direkter Backend-URL: Der Browser kennt nur Nginx auf Port 80. # Das Backend ist im Docker-Netzwerk unter dem Hostnamen "backend" erreichbar — nicht von aussen. # Vorteil: Backend muss keinen öffentlichen Port exponieren, alles läuft über Nginx. location /rooms { proxy_pass http://backend:4000; proxy_http_version 1.1; # Host-Header weiterleiten damit das Backend weiss von welcher Domain die Anfrage kommt. proxy_set_header Host $host; # X-Real-IP: Echte IP-Adresse des Clients weitergeben — sonst sieht das Backend nur Nginx als Absender. proxy_set_header X-Real-IP $remote_addr; # X-Forwarded-For: Liste aller Proxys durch die die Anfrage gelaufen ist (Audit Trail). proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } # Health-Check-Endpoint wird ebenfalls ans Backend weitergeleitet. # Wird von Docker genutzt um zu prüfen ob das Backend läuft (siehe healthcheck in docker-compose.yml). location /health { proxy_pass http://backend:4000; proxy_http_version 1.1; } # WebSocket-Proxy für Socket.IO — braucht spezielle Upgrade-Header. # HTTP und WebSocket sind unterschiedliche Protokolle. Ein WebSocket startet als HTTP-Anfrage # und wird dann per "Upgrade" auf eine dauerhafte bidirektionale Verbindung umgestellt. # Ohne diese Header würde Nginx die Verbindung als normale HTTP-Anfrage behandeln # und der WebSocket-Handshake würde fehlschlagen. location /socket.io/ { proxy_pass http://backend:4000; proxy_http_version 1.1; # Siehe Zeile 72 in App.jsx proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # proxy_cache_bypass: Verhindert dass Nginx WebSocket-Verbindungen cached — # eine dauerhafte Verbindung darf nicht gecacht werden. # da websocket keine fixe Antwort gibt und es ein laufender Kommunikationskanal ist, kann man es nicht sinnvoll cachen proxy_cache_bypass $http_upgrade; } }