431 lines
11 KiB
Markdown
Executable File
431 lines
11 KiB
Markdown
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:
|
||
|
||
```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
|
||
|