11 KiB
Executable File
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:
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
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:
- kümmert sich um HTTP(S), TLS, statische Dateien, Load Balancing
- schickt Anfragen an den Application-Server weiter
- 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:
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:
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:
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.confundsites-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:
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 -tulpenodernetstat -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
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):
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:
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:
sudo ln -s /etc/nginx/sites-available/myflaskapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Ablauf:
- Browser ruft
http://example.com/auf - nginx nimmt Anfrage auf Port 80 entgegen
- nginx leitet an
http://127.0.0.1:8000weiter (Gunicorn/Flask) - Flask antwortet mit „Hallo, Welt“
- nginx sendet diese Antwort an den Browser zurück
6.2 Beispiel: Django mit statischen Dateien
1. Django-Setup (stark vereinfacht)
In settings.py:
STATIC_URL = "/static/"
STATIC_ROOT = "/var/www/mydjangoproject/static/"
Danach statische Dateien sammeln:
python manage.py collectstatic
2. nginx-Konfiguration (Ausschnitt)
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:
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.:
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