Ollama hosten op een VPS: veilig een LLM draaien
Leer hoe u Ollama veilig op een VPS installeert. Een 7B model vereist 8 GB RAM en haalt 4 tot 10 tokens per seconde. Beveilig uw API op 127.0.0.1:11434 door poort 11434 te sluiten.
Wat u bouwt
Een enkel open-weight taalmodel dat draait op een server in uw eigen beheer, benaderbaar via een HTTP API en, indien gewenst, een chatpagina in uw browser. Ollama is de component die het model downloadt, in het geheugen laadt en verzoeken afhandelt op http://127.0.0.1:11434. De installatie vereist slechts één commando. De complexe aspecten bevinden zich elders: het selecteren van een model dat uw VPS daadwerkelijk in het RAM kan vasthouden, en het voorkomen dat u per ongeluk een niet-geauthenticeerde inference-server publiceert naar het gehele internet.
Eerst twee belangrijke waarschuwingen. Een VPS die alleen op CPU draait, voert kleine modellen traag uit, en er is geen ingebouwde authenticatie voor de API aanwezig. Beide punten worden hieronder in detail behandeld, aangezien dit de gebieden zijn waar gebruikers vaak tegen problemen aanlopen.
De realiteit van de systeemvereisten in cijfers
Het geheugengebruik van een model is ongeveer gelijk aan de bestandsgrootte, plus ongeveer een gigabyte aan runtime-overhead, aangevuld met extra geheugen voor het contextvenster. De standaardmodellen van Ollama zijn 4-bit gekwantiseerd (aangeduid als Q4), wat ongeveer een halve gigabyte aan RAM kost per miljard parameters. De berekening is dus eenvoudig en bepalend voor alles.
Een 3B-model zoals llama3.2:3b is een download van ~2 GB en vereist ongeveer 4 GB vrij RAM om te draaien. Een 7B- of 8B-model zoals mistral:7b of llama3.1:8b is ~5 GB op schijf en vereist ongeveer 8 GB RAM, waarbij 16 GB aanbevolen is voor een soepele werking. Een 13B- of 14B-model vereist grofweg 16 GB. Alles in het bereik van 30B tot 70B heeft een server met veel RAM nodig of, realistischerwijs, een GPU; op een CPU VPS zal het model ofwel niet passen, ofwel zo traag reageren dat het onbruikbaar is.
Dan de snelheid, want dit is het aspect dat vaak wordt onderschat. CPU-inferentie wordt beperkt door de geheugenbandbreedte, niet door de kloksnelheid, en een gedeelde vCPU VPS heeft een bescheiden bandbreedte. Houd rekening met een snelheid van enkele tot lage dubbele cijfers aan tokens per seconde: een 7-8B Q4-model haalt wellicht 4 tot 10 tokens per seconde, een 3B-model 10 tot 25. Een GPU is ongeveer een factor tien sneller. Dit zijn bewust ruwe schattingen; de eerlijkste methode is om uw eigen server te meten, zoals in de onderstaande run-stap wordt getoond. Vertrouw op uw eval rate, niet op een getal in een artikel, inclusief dit artikel.
De praktische conclusie: kleine gekwantiseerde modellen op een CPU zijn oprecht nuttig voor het opstellen van concepten, samenvatten en classificatie, mits u het tempo accepteert. Voor alles wat groter of sneller moet zijn, dient u budget vrij te maken voor een GPU-instantie.
Om een specifiek model af te wegen tegen een specifieke server, kunt u hier het geheugengebruik inschatten:
Ollama installeren
Er zijn twee schone methoden. Het officiële script is het eenvoudigst op een kale VPS:
curl -fsSL https://ollama.com/install.sh | shDit maakt een systeemgebruiker genaamd ollama aan, installeert het binaire bestand naar /usr/local/bin/ollama en registreert een systemd-service genaamd ollama.service die bij het opstarten wordt geactiveerd en bindt aan 127.0.0.1:11434. Controleer of deze actief is:
systemctl status ollama
ollama --versionAls u al met Docker werkt, gebruik dan de container:
docker run -d --name ollama \
-p 127.0.0.1:11434:11434 \
-v ollama:/root/.ollama \
--restart always \
ollama/ollamaLet op het 127.0.0.1:-voorvoegsel bij de poorttoewijzing. Dit bindt de poort uitsluitend aan localhost. Het gebruik van -p 11434:11434 in plaats daarvan publiceert de poort op alle interfaces; dit is de fout waarvoor in de beveiligingssectie wordt gewaarschuwd. Kies één installatiemethode; voer het script en de container niet tegelijkertijd uit, anders strijden twee processen om dezelfde poort.
Uw eerste model ophalen en uitvoeren
ollama pull llama3.2:3b
ollama run llama3.2:3bpull downloadt de modellagen naar de schijf (ongeveer 2 GB voor dit model). run laadt deze in het geheugen en opent een >>>-prompt. Stel een vraag. Het genereren van het eerste token kan enkele seconden duren terwijl de gewichten van de schijf naar het RAM worden geladen; daarna wordt het antwoord gestreamd. Typ /bye om de chat te verlaten; Ollama blijft op de achtergrond actief.
Bekijk wat er geladen is en hoe het in het geheugen past:
ollama psDe kolom PROCESSOR geeft de feitelijke status weer. 100% CPU betekent dat er geen GPU wordt gebruikt, wat de oorzaak is van de traagheid. Meet de werkelijke snelheid met de verbose-vlag:
ollama run --verbose llama3.2:3b "Write two sentences about Linux."De regel eval rate die aan het einde wordt afgedrukt, toont het aantal tokens per seconde op deze hardware. Dit is het getal waarop u uw planning moet baseren.
Waar modellen worden opgeslagen en hoeveel schijfruimte u moet aanschaffen
Modellen die door het script zijn geïnstalleerd en als service worden uitgevoerd, bevinden zich in de home-directory van de gebruiker ollama:
sudo du -sh /usr/share/ollama/.ollama/modelsWanneer u ze interactief als uw eigen gebruiker uitvoert, staan ze in ~/.ollama/models. In de container bevinden ze zich in het named volume ollama. Dit is van belang omdat gekwantiseerde gewichten snel oplopen: een 3B-model is ~2 GB, een 7-8B-model is ~5 GB en een 14B-model is ~9 GB. Als u vier modellen downloadt om ze te vergelijken, heeft u ongemerkt 20 GB verbruikt. Bepaal de schijfgrootte op basis van de modellen die u wilt bewaren en verwijder de rest met ollama rm <model>. Als op dezelfde VPS al een applicatie draait die veel ruimte in beslag neemt, zoals PhotoPrism of Immich met een fotobibliotheek, trek dit dan eerst af van de vrije ruimte en beschouw het restant als uw werkelijke budget voor modellen.
Uitvoeren als een service die u beheert
Het installatiescript heeft ollama.service al geregistreerd, waardoor deze na het opstarten automatisch wordt hervat zonder verdere actie. De instelling die het overwegen waard is, is hoe lang een model in het geheugen blijft, en bij sommige configuraties het bind-adres. Beide plaatst u in een systemd drop-in, zodat een upgrade van Ollama deze niet overschrijft:
sudo systemctl edit ollama.serviceVoeg dit toe onder de [Service]-header die de editor toont:
[Service]
Environment="OLLAMA_KEEP_ALIVE=30m"OLLAMA_KEEP_ALIVE bepaalt hoe lang een model in het geheugen blijft na het laatste verzoek (standaard 5 minuten). Verhoog deze waarde op een systeem dat u de hele dag bevraagt om te voorkomen dat de gewichten telkens opnieuw worden geladen; stel deze in op 0 op een systeem met beperkt geheugen om RAM direct vrij te maken zodra een verzoek is voltooid. systemctl edit herlaadt de unit-bestanden voor u; start de service vervolgens opnieuw om de wijziging toe te passen:
sudo systemctl restart ollamaHet belangrijkste beveiligingspunt
Standaard bindt Ollama aan 127.0.0.1:11434, waardoor alleen processen op de VPS zelf de service kunnen bereiken. Deze standaardinstelling is correct. Behoud deze.
De API heeft geen authenticatie. Geen enkele. Er is geen API-sleutel, geen login, geen rate limit en geen allow-list. Iedereen die poort 11434 kan bereiken, kan elk model uitvoeren dat u heeft binnengehaald, nieuwe modellen downloaden, ze verwijderen en uw CPU of GPU voor onbepaalde tijd volledig belasten. Scanners zoals Shodan indexeren duizenden open Ollama-instanties, en een blootgestelde instantie wordt binnen enkele uren gevonden en misbruikt.
De enige fout die u dus nooit mag maken: stel OLLAMA_HOST=0.0.0.0 niet in en open poort 11434 niet in uw firewall. Daarmee stelt u een niet-geauthenticeerde inference-server bloot aan het volledige internet. Geen enkele configuratie maakt rechtstreeks verkeer naar 11434 op 0.0.0.0 veilig, omdat Ollama geen authenticatie biedt en er niets valt te configureren. Dit is een regel voor deze specifieke service, geen verbod om ooit een poort te openen: een zelfgehoste RustDesk-relay voor externe desktops moet openbaar verkeer accepteren om zijn functie te kunnen uitvoeren. Die service rechtvaardigt dat doordat zij eigen authenticatie op basis van cryptografische sleutels en een korte, gedocumenteerde lijst met poorten gebruikt. Ollama biedt geen van beide.
Er zijn drie veilige manieren om het model vanaf een andere locatie dan de server zelf te bereiken:
- Houd het lokaal. Als de enige aanroeper een ander programma op dezelfde VPS is, een cron-script, een bot of een MCP-server die uw tools met het model verbindt, laat de bind dan op
127.0.0.1staan en laat dat programmahttp://127.0.0.1:11434aanroepen. Niets is blootgesteld en er is verder niets nodig. - Bereik het via een privétunnel. Plaats de VPS op een WireGuard VPN die u zelf beheert, stel
OLLAMA_HOSTin op het tunneladres (bijvoorbeeld10.8.0.1, niet0.0.0.0), en alleen VPN-peers kunnen verbinding maken. Het publieke internet ziet nog steeds niets op poort 11434. - Plaats een authenticerende reverse proxy ervoor. Beëindig TLS en vereis een wachtwoord of token bij nginx, Traefik of Caddy, en proxy vervolgens naar
127.0.0.1:11434. Ollama behoudt zijn localhost-bind; de proxy is het enige dat luistert op de publieke poort. Dit is dezelfde opzet als het plaatsen van een Let's Encrypt-certificaat op nginx voor een lokale service.
De reverse-proxy-optie is precies wat de chat-UI u hierna biedt, inclusief een echte login.
Een chat-UI toevoegen met Open WebUI, achter TLS
Open WebUI is een zelfgehoste chatinterface. Draai deze in Docker en koppel deze aan de lokale Ollama:
docker run -d \
--name open-webui \
--network=host \
-e OLLAMA_BASE_URL=http://127.0.0.1:11434 \
-v open-webui:/app/backend/data \
--restart always \
ghcr.io/open-webui/open-webui:mainDe vlag --network=host is het cruciale detail op een Linux VPS. Hiermee wordt de container in de netwerk-namespace van de host geplaatst, waardoor 127.0.0.1 binnen de container de eigen loopback van de host is en de container Ollama bereikt op 127.0.0.1:11434, zonder dat Ollama op een andere interface hoeft te luisteren. Het bridge-netwerk-recept dat u elders zult zien, --add-host=host.docker.internal:host-gateway met OLLAMA_BASE_URL=http://host.docker.internal:11434, werkt hier niet: die naam verwijst naar de Docker-bridge-gateway, en een service die op de host is gebonden aan 127.0.0.1 is niet bereikbaar via de bridge, waardoor Open WebUI blijft melden dat het geen verbinding kan maken met Ollama.
Het nadeel van host-networking is dat Open WebUI nu op elke interface van de host luistert op poort 8080; elke -p-mapping wordt genegeerd en Docker geeft hiervoor een waarschuwing. Sluit daarom 8080 af in zowel de firewall van de host als die van de provider en laat de TLS-reverse-proxy de enige publieke ingang zijn. Bij het eerste bezoek vraagt Open WebUI u om een beheerdersaccount aan te maken; dat account is uw authenticatielaag, dus kies een sterk wachtwoord.
Om de chat vanaf uw laptop via HTTPS te openen, plaatst u een TLS-reverse-proxy voor 127.0.0.1:8080. Als u al meerdere Docker-apps op de server routeert, is Traefik met automatische TLS voor meerdere apps de meest overzichtelijke oplossing: één label-blok regelt het certificaat en routeert chat.example.com naar Open WebUI. De regel uit de beveiligingssectie blijft van kracht: de proxy beheert de publieke poort en de login, terwijl Ollama op localhost blijft en de eigen 8080 van Open WebUI achter de firewall blijft.
Gebruik het OpenAI-compatibele eindpunt in uw code
Ollama ondersteunt een subset van de OpenAI chat API op /v1, waardoor de meeste OpenAI-clientbibliotheken werken na het aanpassen van twee zaken: de base URL en een willekeurige API-sleutel.
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:11434/v1", api_key="ollama")
resp = client.chat.completions.create(
model="llama3.2:3b",
messages=[{"role": "user", "content": "Name three Linux distributions."}],
)
print(resp.choices[0].message.content)De api_key is vereist door de clientbibliotheek, maar wordt door Ollama genegeerd; elke willekeurige string volstaat dus. model moet een modelnaam zijn die u reeds heeft binnengehaald; een onbekende naam resulteert in model "x" not found, try pulling it first. Een standaard curl-aanroep werkt op dezelfde wijze:
curl http://127.0.0.1:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"llama3.2:3b","messages":[{"role":"user","content":"Hello"}]}'Op deze manier koppelt u het model ook aan agent- en editor-tools. Als u reeds op de server ontwikkelt, kan een lokaal model scripts en plugins ondersteunen, naast Claude Code draaiend op de VPS binnen tmux. Hiermee houdt u goedkoop, privaat conceptwerk buiten een betaalde API, terwijl het zware redeneerwerk wordt afgehandeld door een gehost model.
Foutmodi, met de exacte meldingen die u zult zien
Het proces wordt tijdens het genereren gestopt met "Killed". U start een groot model en de terminal geeft Killed weer, of het serverlogboek bevat llama runner process has terminated: signal: killed. De Linux OOM-killer heeft het proces gestopt omdat het model meer RAM nodig had dan de server beschikbaar heeft. Bevestig de oorzaak met sudo dmesg | grep -i oom. Daar ziet u een regel zoals Out of memory: Killed process ... (ollama). De oplossing is een kleiner of zwaarder gequantiseerd model, bijvoorbeeld llama3.2:3b in plaats van een 13B-model, of extra swap. Daardoor blijft een belasting die het fysieke RAM maar net overschrijdt langzaam werken in plaats van te stoppen. Swap maakt van een onmiddellijke crash een traag antwoord. Daarmee wordt een 70B-model niet praktisch op 4 GB. Het proces wordt stil beëindigd, tenzij u toevallig de terminal bewaakt. Op een server die u vanaf een andere locatie beheert, meldt een aan ollama.service gekoppelde OnFailure=-unit die berichten naar een ntfy-server die u voor pushmeldingen host verstuurt het direct wanneer het proces stopt. U ontdekt het probleem dan niet pas bij het volgende verzoek.
"Error: model requires more system memory". Ollama weigert het model te starten en toont Error: model requires more system memory (X GiB) than is available (Y GiB). Dit is de beleefde versie van de bovenstaande crash: Ollama heeft de berekening uitgevoerd en is gestopt in plaats van de OOM killer het werk te laten doen. Het programma geeft u zelfs de twee getallen. Kies een model waarvan de vereiste onder uw vrije RAM-geheugen ligt (controleer dit met free -h), verklein de contextlengte of stap over naar een grotere VPS. Er is geen vlag die het model passend maakt; het geheugen is een fysiek gegeven.
De eerste token laat lang op zich wachten, daarna gaat het goed. Een model dat nog niet is geladen, geeft gedurende vijf tot dertig seconden niets terug en streamt daarna normaal. Tijdens die pauze worden de gewichten voor het eerst van schijf naar RAM geladen. Trage opslag maakt dit erger. Nadat het model is geladen, blijft het gedurende de looptijd van OLLAMA_KEEP_ALIVE in het geheugen aanwezig. Daardoor beantwoordt het de tweede prompt direct. Als het eerste laden langer duurt dan een timeout ergens in het aanroeppad, krijgt u een foutmelding in plaats van een traag antwoord. Met vaststellen welke laag de foutmelding context deadline exceeded heeft gerapporteerd kunt u bepalen of de client, de proxy of het laden zelf de timeout heeft overschreden. Verhoog die waarde als de wachttijden u hinderen. Gebruik ollama ps om te controleren of er momenteel een model is geladen.
Alles is simpelweg traag. Tien tokens per seconde of minder, zonder enige foutmelding. Dit is CPU-inferentie die precies doet wat CPU-inferentie doet. ollama ps toont 100% CPU, wat betekent dat er geen GPU aanwezig is. Dit is geen bug en geen enkele instelling lost dit op, omdat de beperking de geheugenbandbreedte is en geen verkeerde configuratie. Gebruik een kleiner model, accepteer de snelheid of stap over naar een GPU-instantie, en meet uw werkelijke snelheid met --verbose voordat u concludeert dat er iets defect is.
Connection refused vanaf een andere machine. Vanaf uw laptop krijgt u curl: (7) Failed to connect to <ip> port 11434: Connection refused. Dit werkt zoals ontworpen: Ollama bindt alleen aan localhost. "Los dit niet op" door te binden aan 0.0.0.0, wat precies de blootstellingsfout is die hierboven wordt beschreven. Benader het model via de VPN of via de authenticerende proxy.
U heeft 11434 blootgesteld aan het internet. Als u OLLAMA_HOST=0.0.0.0 heeft ingesteld, de firewall heeft geopend en nu model-pulls ziet die u niet bent gestart of de CPU op 100% ziet door onbekende clients, dan bent u gevonden en wordt uw systeem gebruikt. Dit is de belangrijkste fout, geen randgeval. Bind opnieuw aan 127.0.0.1 of het VPN-adres, sluit poort 11434 in de firewall en plaats authenticatie ervoor. Ga ervan uit dat alles wat bereikbaar was op dat adres terwijl het openstond, is bevraagd door vreemden.
Back-ups en upgrades
Er is weinig status die verloren kan gaan. De modellen zijn opnieuw te downloaden, dus de enige zaken die het back-uppen waard zijn, zijn het datavolume van Open WebUI, accounts, chatgeschiedenis, instellingen en eventuele door u geschreven systemd drop-in bestanden. Maak een back-up van het volume met een tijdelijke container:
docker run --rm -v open-webui:/data -v "$PWD":/backup alpine \
tar czf /backup/open-webui.tgz -C /data .Upgrade Ollama door het installatiescript opnieuw uit te voeren; upgrade Open WebUI met docker pull ghcr.io/open-webui/open-webui:main en maak daarna de container opnieuw aan. Pin niets voor de lange termijn: zowel de modelkwaliteit als de runtime ontwikkelen zich snel. Lees daarom de release notes en voer zelf benchmarks uit op uw eigen systeem in plaats van te vertrouwen op de cijfers van het vorige kwartaal.
FAQ
Kan ik echt een LLM draaien op een VPS zonder GPU?
Ja, binnen bepaalde grenzen. Kleine gekwantiseerde modellen in de range van 3B tot 8B draaien op een CPU en zijn bruikbaar voor het opstellen van teksten, samenvatten en classificatie, zij het traag, met een snelheid van enkele tot tientallen tokens per seconde op een gedeelde vCPU. Alles vanaf 13B is extreem traag of past simpelweg niet in het RAM. Voor echte snelheid of grotere modellen heeft u een GPU-instantie nodig.
Hoeveel RAM heeft elk model nodig?
Een grove vuistregel voor de standaard 4-bit gekwantiseerde modellen: ongeveer 0,5 GB RAM per miljard parameters voor de gewichten, plus ongeveer 1 GB overhead en wat extra ruimte voor de context. Een 3B-model vereist dus ongeveer 4 GB vrije ruimte, een 7-8B-model ongeveer 8 GB en een 14B-model ongeveer 16 GB. Controleer uw beschikbare ruimte met free -h en houd rekening met het besturingssysteem en andere processen op de server.
Is de Ollama API beveiligd met authenticatie?
Nee. Ollama heeft geen ingebouwde authenticatie, API-sleutels of rate limiting; iedereen die poort 11434 kan bereiken, heeft volledige controle. Dit is precies de reden waarom het standaard bindt aan 127.0.0.1 en waarom u poort 11434 nooit direct aan 0.0.0.0 op het internet moet blootstellen. Benader het lokaal, via een privé-VPN of via een reverse proxy die een inlogscherm toevoegt.
Hoe voeg ik een web-chatinterface toe?
Draai Open WebUI in Docker met --network=host zodat het de loopback van de host deelt en de lokale Ollama-instantie bereikt op http://127.0.0.1:11434. Plaats vervolgens een TLS-reverse proxy voor poort 8080 voor toegang vanaf uw laptop. Houd 8080 gesloten in de firewall, zodat de proxy de enige publieke toegangspoort is. Het beheerdersaccount van Open WebUI voorziet in de inlogfunctionaliteit; het wachtwoord stelt u in bij de eerste keer opstarten.
Hoe roep ik het aan vanuit mijn eigen applicatie?
Gebruik het OpenAI-compatibele eindpunt op http://127.0.0.1:11434/v1. Wijs een willekeurige OpenAI SDK naar die basis-URL, geef een willekeurige string op als API-sleutel (aangezien deze wordt genegeerd) en stel model in op de naam van het model dat u heeft binnengehaald. Bestaande OpenAI-code werkt doorgaans zonder wijzigingen, afgezien van de basis-URL en de sleutel.