Files
work/notes/nextcloud/Notes/IT-Know-How/web und cloud gedoens/Nginx.md
T
2026-03-17 19:04:55 +01:00

431 lines
11 KiB
Markdown
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## 1. Grundidee: Was ist nginx gerade im PythonKontext?
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 PythonApp) an einen **Anwendungsserver** weiterleitet (z.B. Gunicorn, uWSGI, [[uvicorn]])
Im PythonKontext wird nginx fast immer als **„Vorderseite“ (Frontend) vor einer PythonWebanwendung** 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. Lets 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 Lets 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