1. Objective
The objective of the web server configuration is to
- provide the locally operated AI and RAG services
- in a secure and controlled manner
- via HTTP/HTTPS in the internal network
- with a clear separation between
Der Webserver fungiert als Reverse Proxy, TLS-Termination und Zugriffskontrollschicht.
2. Systemarchitektur und Überlegung
Zielarchitektur soll sein:
|
Komponente
|
Funktion
|
|
Nginx
|
Reverse Proxy + TLS
|
|
Ollama
|
LLM Runtime (GPU-gestützt)
|
|
RAG API (FastAPI)
|
Dokumenten-Retrieval + LLM-Orchestrierung
|
|
Qdrant
|
Vektor-Datenbank
|
|
Open WebUI
|
Chat-Frontend
|
2.1 Warum so?
Das Ziel besteht darin, ein RAG-System zu schaffen, auf das externe Programme über den Ollama-Service zugreifen können.
Das RAG-System soll maßgeblich auf der KI laufen und selbst entwickelte Programme, die beispielsweise auf einem Mac oder einem Windows-Rechner laufen, sollen den Ollama-Dienst nutzen können.
Darüber hinaus soll die Nutzung von OpenWebUI zum Testen und Stellen von Anfragen möglich sein.
Die Aufteilung in verschiedene Module soll eine spätere Verteilung auf verschiedene KI-Systeme ermöglichen, z. B. wenn der Cluster erweitert wird oder verteilte Rechenaufgaben auf verschiedenen Maschinen laufen sollen.
3. Warum Nginx als Reverse Proxy?
Begründung:
-
Trennung von Anwendung und Exposition
→ Die Dienste laufen intern auf 127.0.0.1 (z. B. 8080, 3000, 11434).
-
TLS-Termination zentral
→ Nur Nginx verwaltet Zertifikate (/etc/ssl/localca/homecpt.crt).
-
Pfadbasierte Routing-Logik
→ /rag/ → RAG-API
→ / → Open WebUI
-
Timeouts steuerbar
→ LLM-Generierung kann mehrere Minuten dauern
→ Standard-Timeouts wären zu kurz
-
Erweiterbarkeit
→ Logging, Rate Limiting, Access-Control später möglich
Der Dienst läuft lokal und nicht in einem Dogger.
4. Server-Konfiguration: "homecpt" auf Port 443
Konfigurationsbeispiel NGINX:
Achtung: Fehler: Hier wird NGINX in einem Docker installiert. Kann man machen!
location /rag/ {
rewrite ^/rag/(.*)$ /$1 break;
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 30s;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
send_timeout 3600s;
proxy_buffering off;
proxy_cache off;
}
Und hier direkt auf der Maschine ohne Docker:
Wichtigste Pfade:
-
Hauptconfig: /etc/nginx/nginx.conf
-
vHosts: /etc/nginx/sites-available/
-
aktive vHosts (Symlinks): /etc/nginx/sites-enabled/
-
Logs: /var/log/nginx/access.log, /var/log/nginx/error.log
Best Practice:
Eigene Site anlegen (Beispiel: homecpt)
Datei erstellen :
sudo nano /etc/nginx/sites-available/homecpt
Beispiel (HTTP-only, später HTTPS ergänzen):
server {
listen 80;
server_name homecpt homecpt.local;
location / {
proxy_pass http://127.0.0.1:3000/; # Open WebUI
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto http;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
proxy_cache off;
}
location /rag/ {
rewrite ^/rag/(.*)$ /$1 break;
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto http;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 30s;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
send_timeout 3600s;
proxy_buffering off;
proxy_cache off;
}
}
Aktivieren:
sudo ln -s /etc/nginx/sites-available/homecpt /etc/nginx/sites-enabled/homecpt
Default deaktivieren:
sudo rm -f /etc/nginx/sites-enabled/default
4.1 Warum diese Konfiguration gewählt wurde
4.1.1 rewrite-Regel
rewrite ^/rag/(.*)$ /$1 break;
Begründung:
-
Die RAG-API kennt keine /rag-Prefixe.
-
Intern läuft sie auf /ask, /upload, /evaluate (Selbst definierte Schnittstellen in app.py im Dogger RAG).
-
Der Reverse Proxy entfernt das Präfix.
→ Trennung von externer URL-Struktur und interner API-Logik.
4.1.2 Lange Timeouts (3600s)
Begründung:
→ Stabilität > Standard-Web-Latenz.
4.1.3 proxy_buffering off
Begründung:
Besonders wichtig bei:
-
-
langen Antworten
-
Streaming
-
großen JSON-Responses
→ Direktes Durchreichen der Upstream-Antwort.
4.1.4 X-Forwarded-Proto Header
Begründung:
5. Sicherheitsüberlegungen
5.1 Interne Bindung
-
Ollama läuft auf 0.0.0.0:11434, aber Zugriff erfolgt primär über Proxy.
-
RAG läuft intern auf 127.0.0.1:8080.
→ Minimierung direkter Angriffsfläche.
5.2 Netztrennung
→ Segmentierung zwischen Admin und Gastnutzung.
6. Docker-Konzept
Der Webserver läuft lokal, um möglichst höchste Performance zu haben und bei einem Neustart den Fehler zu verhindern, dass der Dogger nicht startet. Bei den anderen Modulen habe ich mich für Docker entschieden.
6.1 Warum Docker?
Begründung:
6.2 Nachteil:
Zusätzliche Komplexität
-
Docker + Docker Compose + Netzwerke + Volumes
-
Fehlerquellen: falsche Runtime, GPU-Passthrough, Restart-Policy
-
Debugging kann aufwändiger sein (Host vs Container)
- Laut Grok und chatcpt etwas langsamer (chatcpt gibt 5% Performanceverlust an)
Praxisbeispiel:
GPU war da, wurde aber im Container nicht genutzt → Runtime-Problem.
Ich habe mich aber am Ende dennoch für eine Dockerlösung entschieden, da es für mich einfacher war, die verschiedenen Einstellungen in verschiedenen Docker zu testen.
7. Installation unter Ubuntu (Mein Betriebssystem)
Ich installierte alle Service mit SSL
7.1 Paketlisten aktualisieren
sudo apt update
7.2 NGINX installieren
sudo apt install nginx -y
7.3 Dienste starten
sudo systemctl start nginx
7.4 Autostart erzwingen
sudo systemctl enable nginx
7.5 Status prüfen
sudo systemctl status nginx
7.6 Firewall konfigurieren
sudo ufw allow 'Nginx Full'
7.7 Grundstruktur nach Installation
/etc/nginx/nginx.conf
/etc/nginx/sites-available/
/etc/nginx/sites-enabled/
/var/log/nginx/
Konzept:
7.8 Neue Konfiguration erstellen
sudo nano /etc/nginx/sites-available/homecpt
Beispiel:
server {
listen 80;
server_name homecpt;
location / {
return 200 "NGINX läuft korrekt\n";
}
}
7.9 Script aktivieren auf Webserver
sudo ln -s /etc/nginx/sites-available/homecpt /etc/nginx/sites-enabled/
7.10 Alles neu laden
sudo systemctl reload nginx
7.11 HTTPS Zertifikat erstellen
sudo openssl req -x509 -nodes -days 365 \
-newkey rsa:2048 \
-keyout /etc/ssl/localca/homecpt.key \
-out /etc/ssl/localca/homecpt.crt
und im Script (siehe Punkt 7.8) ergänzen:
server {
listen 443 ssl;
server_name homecpt;
ssl_certificate /etc/ssl/localca/homecpt.crt;
ssl_certificate_key /etc/ssl/localca/homecpt.key;
location / {
return 200 "HTTPS funktioniert\n";
}
}
7.12 Reverse Proxy erstellen
location /rag/ {
rewrite ^/rag/(.*)$ /$1 break;
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
7.12.1 Warum Reverse Proxy?
- Der Client sieht nur NGINX.
- Die internen Dienste bleiben verborgen.
- Angriffsfläche im Guestnetzwerk reduziert
8. Lessons Learned (nach etlichen Systemkonfigurationen)
-
Default-Timeouts sind für LLM ungeeignet.
-
Browser-fetch("/ask") funktioniert hinter Reverse Proxy nicht → Base-Path notwendig.
-
GPU-Idle bedeutet nicht zwingend Fehlfunktion.
-
default_num_ctx=262144 ist Heuristik, nicht realer Request.
-
Warum nicht direkt FastAPI öffentlich, sondern Reverse-Proxy?
NGINX ist genau dafür gebaut. Weiterempfehlungen auch im NVIDIA Playbook