add synced notes on IT know how
This commit is contained in:
@@ -0,0 +1,430 @@
|
||||
## 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
|
||||
|
||||
Reference in New Issue
Block a user