„Wir hosten unsere KI selbst“ klingt gut und endet oft auf einem VPS, der eine Antwort pro Minute ausspuckt. Die Frage ist nicht, ob ein Sprachmodell auf einem Mietserver läuft, das tut es, sondern welches, wie schnell und wofür sich das lohnt. Dieser Beitrag beantwortet das mit Zahlen, die du auf deiner eigenen Maschine nachmessen kannst, statt mit fremden Balkendiagrammen.
Die ehrliche Ausgangslage#
Ein normaler VPS hat keine Grafikkarte. Ein Sprachmodell rechnet dann auf der CPU, und dort ist nicht die Rechenleistung der Engpass, sondern die Speicherbandbreite: Für jedes einzelne erzeugte Wort muss das gesamte Modell einmal durch den Arbeitsspeicher gelesen werden. Ein 5-GB-Modell bedeutet 5 GB Lesevorgänge pro Token. Mehr Kerne helfen deshalb weit weniger, als man erwartet.
Daraus folgt die erste Regel: Das Modell muss klein genug sein, um schnell gelesen zu werden, nicht nur klein genug, um zu passen.
Der Speicherbedarf ergibt sich aus Parameterzahl und Quantisierung. Bei der üblichen 4-Bit-Quantisierung sind das grob:
| Modellgröße | Datei (Q4) | RAM inkl. Kontext | Sinnvoll auf CPU |
|---|---|---|---|
| 1-3 B | ~1-2 GB | 3-4 GB | ja, flott |
| 7-8 B | ~4-5 GB | 8 GB | ja, aber geduldig |
| 13-14 B | ~8-9 GB | 12-16 GB | grenzwertig |
| 30 B+ | ~18 GB+ | 32 GB+ | nein, nicht interaktiv |
Das sind Dateigrößen und Faustwerte, keine Messung. Was deine Maschine daraus macht, misst du selbst, der Befehl steht weiter unten.
Der oben genannte RAM-Bedarf gilt für kurze Eingaben. Der Kontext wird zusätzlich gehalten, und er wächst mit jeder Nachricht im Verlauf. Wer 32k Kontext einstellt, kann bei gleichem Modell das Doppelte an Arbeitsspeicher brauchen und ein Server, der beim Rechnen in den Swap läuft, ist praktisch stehengeblieben.
Wofür sich das ohne GPU lohnt#
Nicht als Chatfenster. Sondern überall dort, wo eine Aufgabe kurz, wiederholt und nicht interaktiv ist:
- Texte einsortieren, Tickets, Mails, Formulareingaben in Kategorien. Ein 3-B-Modell reicht dafür oft.
- Zusammenfassen im Hintergrund, nachts über den Tagesbestand laufen lassen, das Ergebnis ablegen. Niemand wartet.
- Einbettungen für Suche (Embeddings), schnell, klein, und der klassische Grund für einen eigenen Server: die Dokumente bleiben im Haus.
- Spracherkennung mit Whisper, läuft auf CPU brauchbar, weil kurze Audiodateien stückweise verarbeitet werden.
Und der ehrliche Gegenpunkt: Für Chatqualität auf dem Niveau der großen Anbieter ist eine API billiger als jede eigene Hardware. Der Grund, trotzdem selbst zu hosten, ist selten der Preis, es ist die Frage, wessen Server die Daten sehen. Wer einen Auftragsverarbeitungsvertrag vermeiden will oder mit Daten arbeitet, die das Haus nicht verlassen dürfen, hat ein Argument. Wer nur sparen will, rechnet meist falsch.
Aufsetzen: Ollama und Open WebUI im Container#
Zwei Container: Ollama rechnet, Open WebUI ist die Oberfläche. Aufbau und Begründung der Compose-Struktur stehen in Docker Compose produktiv betreiben.
# compose.yaml
services:
ollama:
image: ollama/ollama:latest
restart: unless-stopped
# NUR auf localhost. Siehe Abschnitt "Port 11434".
ports:
- "127.0.0.1:11434:11434"
volumes:
- ollama-models:/root/.ollama
deploy:
resources:
limits:
memory: 12g
webui:
image: ghcr.io/open-webui/open-webui:main
restart: unless-stopped
depends_on: [ollama]
ports:
- "127.0.0.1:8080:8080"
environment:
- OLLAMA_BASE_URL=http://ollama:11434
- WEBUI_AUTH=true
volumes:
- webui-data:/app/backend/data
volumes:
ollama-models:
webui-data:
Modell laden und ausprobieren:
docker compose up -d
docker compose exec ollama ollama pull llama3.2:3b
docker compose exec ollama ollama list
Nach außen kommt das Ganze über einen Reverse-Proxy mit TLS und Anmeldung, nicht über einen offenen Port, siehe Reverse-Proxy mit Caddy oder nginx.
Port 11434 ist kein Detail#
Die Ollama-API hat standardmäßig keine Anmeldung. Wer sie auf 0.0.0.0 bindet, stellt fremden Leuten einen Rechendienst hin: Modelle laden, Modelle löschen, beliebige Anfragen stellen, auf deine Rechnung, mit deiner IP als Absender.
Ein ports:-Eintrag ohne IP-Angabe veröffentlicht auf allen Adressen, und Docker trägt seine Regeln so ein, dass eine Firewall wie ufw daran vorbeigreift. Der Port ist dann offen, obwohl die Firewall ihn als gesperrt anzeigt. Deshalb steht in der Compose-Datei oben überall 127.0.0.1: davor. Das ist die eigentliche Absicherung, nicht die Firewall-Regel.
Nachprüfen, von außen und von innen:
# auf dem Server: worauf lauscht der Port wirklich?
ss -tlnp | grep 11434
# erwartet: 127.0.0.1:11434 — steht dort 0.0.0.0, ist er offen
# von einem anderen Rechner aus, ehrlicher Test:
curl -m 5 http://DEINE-IP:11434/api/tags # muss ins Leere laufen
Passend dazu die Grundlagen in Firewall mit nftables und SSH-Schlüssel und Härtung.
Selbst messen statt schätzen#
Ollama gibt die Zahlen direkt aus:
docker compose exec ollama ollama run llama3.2:3b --verbose "Erkläre in drei Sätzen, was ein Reverse-Proxy tut."
Am Ende der Ausgabe stehen eval count und eval duration, daraus ergibt sich die Tokenrate deiner Maschine. Ein zweiter, ehrlicherer Test läuft über die API und misst inklusive Ladezeit:
time curl -s http://127.0.0.1:11434/api/generate \
-d '{"model":"llama3.2:3b","prompt":"Fasse zusammen: ...","stream":false}' \
| head -c 200
Und daneben mitlaufen lassen, was der Server dabei tut:
htop # ein Kern am Anschlag heißt: falsch parallelisiert
free -m # ist Swap im Spiel? Dann ist das Modell zu groß.
docker stats --no-stream
Die eine Zahl, die zählt: Tokens pro Sekunde bei dem Modell, das du wirklich benutzen willst. Alles andere ist Marketing, auch das aus diesem Beitrag.
Der Betrieb danach#
- Platte im Blick behalten. Modelle sind Gigabyte-Ware, und
ollama pullsammelt still.docker system df -vzeigt, was das Volume wirklich belegt; alte Modelle mitollama rmweg. - Speichergrenze setzen. Ohne
limits.memorynimmt sich der Container, was da ist, und der Kernel beendet im Zweifel den falschen Prozess, nämlich die Datenbank nebenan. - Updates wie bei jedem Container, mit derselben Vorsicht: Container-Updates und Images.
- Ins Monitoring aufnehmen. RAM und Antwortzeit gehören auf denselben Bildschirm wie der Rest (Monitoring aufsetzen).
Häufige Fragen#
Reicht ein VPS mit 4 GB RAM?#
Für ein 1-3-B-Modell ja, für ein 7-8-B-Modell nicht. Der Server muss neben dem Modell noch alles andere tragen, Reverse-Proxy, Datenbank, Betriebssystem. Wer knapp plant, landet im Swap, und dort ist ein Sprachmodell nicht langsam, sondern unbenutzbar.
Lohnt ein VPS mit GPU?#
Wenn die Auslastung hoch und dauerhaft ist, ja. Bei ein paar Anfragen am Tag zahlt man eine Karte, die 23 Stunden wartet. Vorher ausrechnen: Monatspreis geteilt durch erwartete Anfragen, gegen den API-Preis pro Anfrage gestellt.
Kann ich mehrere Modelle gleichzeitig laden?#
Technisch ja, praktisch selten sinnvoll, jedes geladene Modell belegt seinen RAM, bis es aus dem Speicher fällt. Auf kleinen Maschinen ist ein Modell die richtige Antwort.
Ist selbst gehostet automatisch datenschutzkonform?#
Nein, es verschiebt nur die Verantwortung zu dir. Zugriffsrechte, Protokolle, Löschfristen und die Frage, was in den Verläufen von Open WebUI dauerhaft liegen bleibt, musst du dann selbst regeln. Das ist der Preis dafür, keinen Auftragsverarbeitungsvertrag zu brauchen.
Woran merke ich, dass das Modell zu groß ist?#
An drei Anzeichen gleichzeitig: free -m zeigt Swap-Nutzung, die erste Antwort dauert deutlich länger als die folgenden, und die Tokenrate bricht gegenüber einem kleineren Modell überproportional ein.
Kurz gesagt#
- Der Engpass auf CPU ist die Speicherbandbreite, Modellgröße schlägt Kernzahl.
- Realistisch ohne GPU: 1-8 B, für Aufgaben im Hintergrund, nicht für Chat.
127.0.0.1:vor jedem veröffentlichten Port. Docker greift an der Firewall vorbei.- Erst messen (
--verbose,free -m), dann über Hardware reden. - Der gute Grund fürs Selbsthosten heißt Datenhoheit, nicht Ersparnis.
Geschrieben aus dem laufenden Betrieb: MRMedia betreibt eigene Proxmox- Hosts, einen Backup-Server und Kundendienste in der EU. Fehler in einer Anleitung sind Fehler im eigenen Betrieb. Korrekturen bitte über Discord.