## 1. Grundidee: Was ist nginx – gerade im Python‑Kontext? nginx („engine x“) ist ein **Webserver** und **Reverse Proxy**, der: - HTTP(S)-Anfragen aus dem Internet annimmt - statische Dateien (HTML, CSS, Bilder, JS) direkt ausliefert - Anfragen für **dynamische Inhalte** (z.B. deine Python‑App) an einen **Anwendungsserver** weiterleitet (z.B. Gunicorn, uWSGI, [[uvicorn]]) Im Python‑Kontext wird nginx fast immer als **„Vorderseite“ (Frontend) vor einer Python‑Webanwendung** eingesetzt. Typischer Aufbau: ```text Browser des Nutzers -> nginx -> Gunicorn/uWSGI/uvicorn -> Python-App (Django, Flask, FastAPI, ...) (Port 80/443) (lokaler Port, z.B. 8000) ``` --- ## 2. Einordnung in die Webwelt: Grundbegriffe Damit nginx einzuordnen ist, müssen ein paar Begriffe klar sein: ### 2.1 Webserver Ein **Webserver**: - läuft auf einem Rechner (Server) - „lauscht“ auf Port 80 (HTTP) oder 443 (HTTPS) - nimmt HTTP-Anfragen entgegen und schickt HTTP-Antworten zurück Beispiele: - **nginx** - **Apache HTTP Server** - (leichtere) Caddy, lighttpd ### 2.2 Application Server / WSGI-/ASGI-Server Ein **Application Server** führt deine **Web-App** aus, also deinen Python-Code. - Für klassische synchronen Python-Webapps: **WSGI**-Server - z.B. **[[Gunicorn]]**, **uWSGI**, mod_wsgi - Für moderne, asynchrone Apps: **ASGI**-Server - z.B. **[[uvicorn]]**, **[[hypercorn]]**, Daphne Der App-Server: - spricht mit deinem Python-Framework (Django, Flask, [[FastAPI]], etc.) - versteht Anfragen im WSGI/ASGI-Format - erzeugt dynamische Antworten (z.B. JSON, HTML aus Templates) ### 2.3 Python-Webframework (Django, Flask, [[FastAPI]] …) Ein **Framework** ist deine Programmierbibliothek, mit der du die Web-App baust: - Django: „Vollausstattung“ (ORM, Admin, Auth, etc.) - Flask: minimaler Kern, viel per Erweiterung - [[FastAPI]]: modern, async, stark bei APIs **Das Framework ist nicht der Webserver.** Es definiert nur, wie dein Code auf Anfragen reagieren soll. --- ## 3. Abgrenzung: nginx vs. verwandte Begriffe ### 3.1 nginx vs. Apache Beide sind **Webserver**, Unterschiede grob: - **nginx** - schnell bei vielen gleichzeitigen Verbindungen - ressourcensparend (eventbasiert) - sehr gut als Reverse Proxy, Load Balancer, TLS-Terminator - **Apache** - älter, sehr weit verbreitet - modulbasiert, viel Legacy - kann PHP & Co. direkt ausführen (mod_php, etc.) Im modernen Python-Umfeld: **nginx + Gunicorn/[[uvicorn]]** ist ein sehr gängiges Setup. ### 3.2 nginx vs. [[Gunicorn]]/uWSGI/[[uvicorn]] - **nginx**: Webserver / Reverse Proxy - **[[Gunicorn]]/uWSGI/[[uvicorn]]**: Python-Application-Server nginx: - kümmert sich um HTTP(S), TLS, statische Dateien, Load Balancing - schickt Anfragen an den Application-Server weiter [[Gunicorn]]/[[uvicorn]]: - startet deine Python-App - verarbeitet die Anfragen logikseitig - rendert Templates, greift auf Datenbanken zu, etc. ### 3.3 nginx vs. Django/Flask/[[FastAPI]] - nginx: Infrastruktur-Komponente (Server) - Django/Flask/[[FastAPI]]: Bibliotheken, mit denen du deinen Code schreibst Eine typische Kombi: ```text nginx + Gunicorn + Django nginx + uvicorn + FastAPI nginx + uWSGI + Flask ``` Jede Komponente hat ihren klaren Aufgabenbereich. --- ## 4. Welche Probleme löst nginx im Python-Setup? ### 4.1 Sichere und stabile Auslieferung deiner Python-Webapp Problem: Die eingebaute Entwicklungsserver in Django/Flask sind nur für **lokale Entwicklung** gedacht: - wenig performant - kaum Sicherheitsfeatures - nicht für viele gleichzeitige Nutzer ausgelegt Lösung: nginx + App-Server (Gunicorn/uvicorn): - nginx nimmt alle Anfragen entgegen - Python-App läuft hinter nginx auf einem internen Port - Anwendung ist stabiler, sicherer, skalierbarer ### 4.2 Auslieferung statischer Dateien Problem: Python-Frameworks sind nicht optimiert, um Millionen von statischen Dateien schnell auszuliefern. Lösung: - nginx kann statische Dateien extrem effizient ausliefern - Python-App wird entlastet **Beispiel:** Django-Setup: ```text Browser -> nginx -> (statische Dateien: /static/) direkt von nginx -> (dynamische URLs: /api/, /admin/) an Gunicorn/Django ``` ### 4.3 HTTPS / TLS-Termination Problem: Du willst deine Seite unter **https://deinedomain.de** mit Zertifikat ausliefern. Python-Application-Server kümmern sich eher nicht um Zertifikate. Lösung: - nginx bietet HTTPS/TLS an (inkl. Let’s Encrypt-Integration) - entschlüsselt eingehende Anfragen - leitet sie dann intern als HTTP an Gunicorn/uvicorn weiter So muss sich deine Python-App nicht um Zertifikate kümmern. ### 4.4 Load Balancing (Lastverteilung) Problem: Eine einzelne Instanz deiner Python-App reicht nicht bei hoher Last. Lösung: - nginx kann Anfragen auf mehrere App-Server verteilen: ```text Browser -> nginx -> Gunicorn Instanz 1 -> Gunicorn Instanz 2 -> Gunicorn Instanz 3 ``` Damit erreichst du höhere Verfügbarkeit und Kapazität. ### 4.5 Reverse Proxy / Schutz der App Problem: Du willst deine App nicht direkt ins Internet hängen (Sicherheitsrisiko, private Ports). Lösung: - nginx steht „davor“ und leitet nur definierte Anfragen durch - interne Ports (z.B. 8000) sind von außen nicht erreichbar - nginx kann zusätzliche Security-Header, Ratelimits, IP-Filter etc. einsetzen --- ## 5. Herausforderungen bei der Arbeit mit nginx ### 5.1 Konfigurationssyntax & -struktur - nginx wird über Textdateien konfiguriert (z.B. `/etc/nginx/nginx.conf` und `sites-available/...`) - die Syntax ist am Anfang ungewohnt: - `http`, `server`, `location`, `upstream`, `listen`, etc. - Fehler in der Konfiguration führen dazu, dass nginx nicht startet oder falsch weiterleitet Praxis-Hinweise: ```bash sudo nginx -t # Konfiguration testen sudo systemctl reload nginx # Konfiguration neu laden ``` ### 5.2 Rechte & Pfade (Linux-Dateisystem) Probleme: - nginx läuft als bestimmter Benutzer (z.B. `www-data`) - Python-App läuft evtl. als anderer Benutzer (z.B. `myapp`) - Zugriffsrechte auf Dateien/Ordner (Logs, statische Dateien) müssen passen Beispiel: Wenn statische Dateien unter `/var/www/myapp/static/` liegen, muss der nginx-User Lesezugriff haben. ### 5.3 Fehlersuche (Debugging) - Fehler können an mehreren Stellen auftreten: - DNS / Domain falsch - nginx-Konfiguration fehlerhaft - App-Server (Gunicorn/uvicorn) läuft nicht - Python-App wirft Fehler Praxis-Tipp: - in nginx-Logs schauen: - `/var/log/nginx/access.log` - `/var/log/nginx/error.log` - in App-Logs schauen - Ports prüfen: `ss -tulpen` oder `netstat -tulpen` ### 5.4 Performance-Tuning Fortgeschrittener, aber wichtig bei größerem Traffic: - wie viele Worker-Prozesse nginx nutzt - Keep-Alive-Einstellungen - Buffergrößen - Cache-Konfiguration für statische Inhalte Am Anfang reicht meist die Standardkonfiguration, später optimiert man bei Bedarf. --- ## 6. Praxisnahe Beispiele ### 6.1 Minimalbeispiel: Flask-App hinter nginx + Gunicorn **1. Eine einfache Flask-App (Python)** Datei: `app.py` ```python from flask import Flask app = Flask(__name__) @app.route("/") def index(): return "Hallo, Welt! Das kommt aus Flask hinter nginx." ``` Start des App-Servers (Gunicorn): ```bash pip install flask gunicorn gunicorn -w 3 -b 127.0.0.1:8000 app:app # -w 3: 3 Worker # -b 127.0.0.1:8000: lauscht auf Port 8000 nur lokal ``` **2. nginx-Konfiguration (vereinfacht)** Datei: z.B. `/etc/nginx/sites-available/myflaskapp`: ```nginx server { listen 80; server_name example.com; # deine Domain oder IP # Statische Dateien (wenn du welche hast) # root /var/www/myflaskapp; # falls du HTML/Assets direkt ablegen willst location / { proxy_pass http://127.0.0.1:8000; # Gunicorn 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; } } ``` Dann: ```bash sudo ln -s /etc/nginx/sites-available/myflaskapp /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx ``` Ablauf: 1. Browser ruft `http://example.com/` auf 2. nginx nimmt Anfrage auf Port 80 entgegen 3. nginx leitet an `http://127.0.0.1:8000` weiter (Gunicorn/Flask) 4. Flask antwortet mit „Hallo, Welt“ 5. nginx sendet diese Antwort an den Browser zurück ### 6.2 Beispiel: Django mit statischen Dateien **1. Django-Setup (stark vereinfacht)** In `settings.py`: ```python STATIC_URL = "/static/" STATIC_ROOT = "/var/www/mydjangoproject/static/" ``` Danach statische Dateien sammeln: ```bash python manage.py collectstatic ``` **2. nginx-Konfiguration (Ausschnitt)** ```nginx server { listen 80; server_name example.com; # Statische Dateien direkt von nginx location /static/ { alias /var/www/mydjangoproject/static/; access_log off; expires 30d; } # Alles andere an Django via Gunicorn location / { proxy_pass http://127.0.0.1:8001; # hier läuft Gunicorn 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; } } ``` Vorteil: - statische Inhalte kommen extrem schnell von nginx - Django/Gunicorn verarbeitet nur „echte“ App-Logik ### 6.3 Beispiel: HTTPS mit Let’s Encrypt (Konzept) Mit Tools wie **certbot** kannst du für nginx kostenlos TLS-Zertifikate holen. Grobe Schritte: ```bash sudo apt install certbot python3-certbot-nginx sudo certbot --nginx -d example.com ``` certbot: - holt Zertifikat - passt nginx-Konfiguration an (Port 443, SSL-Parameter) - richtet automatische Erneuerung ein nginx-Konfiguration enthält danach z.B.: ```nginx server { listen 443 ssl; server_name example.com; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; location / { proxy_pass http://127.0.0.1:8000; ... } } ``` Damit ist deine Python-App per HTTPS erreichbar. --- ## 7. Zusammenfassung - **nginx** ist ein leistungsfähiger Webserver und Reverse Proxy, der im Python-Kontext typischerweise: - vor deiner Python-Webanwendung sitzt - HTTP(S) abwickelt - statische Dateien effizient ausliefert - Anfragen an einen Python-Application-Server (Gunicorn, uWSGI, uvicorn) weiterleitet - TLS/HTTPS, Load Balancing, Security-Features bereitstellt - **Abgrenzung**: - nginx ≠ Python-Framework (Django/Flask/[[FastAPI]]) - nginx ≠ Application-Server (Gunicorn/uvicorn) - nginx = Webserver/Reverse Proxy - **Gelöste Probleme**: - sichere Produktion anstelle von Entwicklungsservern - Performance für statische Inhalte - TLS/HTTPS, Lastverteilung, Schutz der App - **Herausforderungen**: - Konfigurationsdateien verstehen - Rechte & Pfade korrekt setzen - Fehler systematisch debuggen - bei hoher Last Performance tunen