SSD Nodes Learn Hosting plans →
Gidsen Matt ConnorDoor Matt Connor · Bijgewerkt 2026-08-28

llama.cpp server draaien op een VPS: handleiding

Leer hoe u llama-server bouwt vanaf een specifieke tag, GGUF-modellen serveert via de OpenAI-API en de service beheert met systemd inclusief strikte geheugenlimieten voor uw VPS.

Wat u bouwt

Het draaien van de llama.cpp server op een VPS betekent één binary, llama-server, die een enkel GGUF-modelbestand laadt en HTTP-verzoeken beantwoordt via een OpenAI-compatibele API. Wijs een willekeurige OpenAI-client naar http://127.0.0.1:8080/v1 en het werkt. De installatie is het eenvoudige gedeelte.

Het overige werk betreft beheer: zet een versie vast, houd de poort op localhost, schrijf een systemd-unit en bepaal wat er gebeurt wanneer het systeem onvoldoende geheugen heeft. Dat is wat deze handleiding behandelt. Als u nog niet heeft gekozen tussen de twee voor de hand liggende opties, lees dan eerst de afwegingen tussen Ollama en llama.cpp, aangezien dit de handleiding is die die vergelijking bewust weglaat.

Kies een release-tag en noteer deze

llama.cpp voorziet vrijwel elke merge van een release-tag, waardoor de tags fungeren als build-nummers. b10488 is de nieuwste versie per 18 augustus 2026. Er is geen stabiele branch voor de lange termijn, wat betekent dat "latest" continu verandert en de versie die u heeft getest de enige is die u kunt ondersteunen. Kies een tag, noteer deze en gebruik exact dezelfde string bij het klonen, in de naam van uw binary en in uw aantekeningen.

Elke tag bevat ook vooraf gebouwde archieven. Voor een CPU-only x86 VPS is dat llama-b10488-bin-ubuntu-x64.tar.gz, en een arm64-archief staat daarnaast als u gebruikmaakt van een ARM VPS in plaats van x86.

curl -LO https://github.com/ggml-org/llama.cpp/releases/download/b10488/llama-b10488-bin-ubuntu-x64.tar.gz
tar tf llama-b10488-bin-ubuntu-x64.tar.gz | head

Bekijk de inhoud van het archief voordat u het uitpakt, zodat u weet waar de bestanden terechtkomen. Deze binaries zijn gelinkt aan de C-library van de image waarin ze zijn gebouwd; op een oudere distributie falen ze daarom bij het opstarten met een foutmelding over een GLIBC_-versie die niet is geïnstalleerd. Zelf compileren vanaf de broncode duurt op een kleine VPS slechts enkele minuten en voorkomt deze hele categorie problemen; daarom volgen we hieronder die methode.

llama-server bouwen vanaf een specifieke tag

sudo apt update
sudo apt install -y build-essential cmake git libssl-dev
git clone --depth 1 --branch b10488 https://github.com/ggml-org/llama.cpp
cd llama.cpp
cmake -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DLLAMA_BUILD_TESTS=OFF -DLLAMA_BUILD_EXAMPLES=OFF
cmake --build build --config Release -t llama-server -j 2

--branch b10488 op een --depth 1 clone checkt uitsluitend die specifieke tag uit, waardoor de build niet kan afwijken terwijl u aan het werk bent.

libssl-dev is van belang omdat de optie LLAMA_OPENSSL standaard is ingeschakeld; dit stelt het binaire bestand in staat om later modellen via HTTPS te downloaden. Zonder de headers mislukt de configuratiestap.

-DBUILD_SHARED_LIBS=OFF levert één op zichzelf staand binaire bestand op. De standaard build plaatst gedeelde bibliotheken naast het uitvoerbare bestand, waardoor het kopiëren van alleen het uitvoerbare bestand naar /usr/local/bin vervolgens faalt met error while loading shared libraries: libllama.so.

-t llama-server bouwt uitsluitend het server-target. De standaard build compileert ook de overige tools en tests, wat op een VPS met twee cores enkele extra minuten kost voor bestanden die u nooit zult uitvoeren.

-j 2 is een bewuste keuze. Elke parallelle compileer-taak gebruikt zijn eigen werkgeheugen, waardoor -j $(nproc) op een klein abonnement eindigt met c++: fatal error: Killed signal terminated program cc1plus; dit is de kernel out-of-memory killer die de compiler stopt. Verlaag het aantal taken of voeg swap toe voor de build.

Eén vlag die u wellicht wilt aanpassen: GGML_NATIVE staat standaard aan, waardoor de compiler de instructieset van de CPU gebruikt waarop de build plaatsvindt. Dit is gewenst wanneer u bouwt op de machine die de software ook gaat draaien. Als u de software eenmaal bouwt en het binaire bestand naar een andere host kopieert, voeg dan -DGGML_NATIVE=OFF toe. Een binaire bestand dat instructies gebruikt die de andere CPU niet ondersteunt, crasht namelijk met Illegal instruction (core dumped) bij de eerste inferentie.

Installeer het onder een naam die de tag bevat.

./build/bin/llama-server --version
sudo install -m 755 build/bin/llama-server /usr/local/bin/llama-server-b10488
sudo ln -sfn /usr/local/bin/llama-server-b10488 /usr/local/bin/llama-server

--version toont het buildnummer en de commit. Dit moet overeenkomen met de tag die u heeft uitgecheckt. Als dit niet het geval is, heeft u iets anders gebouwd. Door het nummer in de bestandsnaam op te nemen en er een symlink naar te laten verwijzen, is een upgrade slechts één ln -sfn plus een herstart, en een rollback is hetzelfde commando met het oude nummer.

Verkrijg een GGUF-model en controleer eerst de schijfruimte

GGUF is het bestandsformaat dat door llama.cpp wordt geladen. Eén bestand bevat de gewichten, de tokenizer en de metadata, waardoor er niets anders geïnstalleerd hoeft te worden. Het achtervoegsel in de bestandsnaam duidt op de kwantisatie, oftewel de precisie waarin de gewichten zijn opgeslagen: Q4_K_M is een 4-bit mix, Q8_0 is 8-bit en f16 is het ongekwantiseerde bestand in halve precisie.

Maak een service-account en een modeldirectory aan voordat u iets downloadt.

sudo useradd --system --home /srv/llama --create-home --shell /usr/sbin/nologin llama
sudo install -d -o llama -g llama /srv/models
df -h /srv

De server kan zelf een model ophalen met -hf; dit is de snelste manier om te verifiëren of uw build werkt.

sudo -u llama env LLAMA_CACHE=/srv/models /usr/local/bin/llama-server \
  -hf ggml-org/gemma-3-1b-it-GGUF:Q4_K_M --host 127.0.0.1 --port 8080

LLAMA_CACHE stelt de downloadmap in. Zonder deze instelling wordt het bestand opgeslagen in ~/.cache/llama.cpp onder het account dat het commando uitvoerde. Dit is de verkeerde locatie voor een service waarvan u de home-directory ontoegankelijk gaat maken. Voer daarna ls -lh /srv/models uit, omdat de naam van het gecachte bestand is afgeleid van de repositorynaam in plaats van de oorspronkelijke bestandsnaam.

Download voor een service naar een pad naar keuze, zodat het unit-bestand naar een stabiele locatie kan verwijzen.

sudo -u llama curl -L --output-dir /srv/models -O \
  https://huggingface.co/ggml-org/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-Q4_K_M.gguf

Schijfruimte is de beperking waar men het eerst tegenaan loopt. Dit zijn de gepubliceerde bestandsgroottes voor twee modellen, gecontroleerd op 18 augustus 2026.

ChartGGUF file size on disk, published figures, 18 August 2026
The data behind this chart
[
  {
    "label": "gemma-3-1b-it Q4_K_M",
    "size_gb": 0.81
  },
  {
    "label": "gemma-3-1b-it Q8_0",
    "size_gb": 1.07
  },
  {
    "label": "gemma-3-1b-it f16",
    "size_gb": 2.01
  },
  {
    "label": "gpt-oss-20b MXFP4",
    "size_gb": 12.11
  }
]

Het 4-bit bestand voor het 1B-model is 0.81 GB. Hetzelfde model zonder kwantisatie is 2.01 GB; de keuze voor het formaat zorgt dus voor een verschil van meer dan een factor twee. Een 20B-model in MXFP4 is 12.11 GB. Dit past op veel instappakketten niet op de schijf, en bovendien moet het bestand daarna nog in het geheugen worden geladen. Als u een specifieke familie op het oog heeft, laat dezelfde omvangsberekening voor GLM zien hoe snel het topmodel te duur wordt voor een VPS, terwijl een kleiner model wel past.

Controleer df -h vóór elke download. Een root-bestandssysteem dat volloopt tijdens een overdracht van 12 GB verstoort alle andere processen die naar de schijf moeten schrijven, inclusief de journal.

Voer het handmatig eenmaal uit en controleer het

sudo -u llama /usr/local/bin/llama-server \
  --model /srv/models/gemma-3-1b-it-Q4_K_M.gguf \
  --host 127.0.0.1 --port 8080 \
  --ctx-size 4096 --parallel 1 --threads 2 --no-webui

Vraag in een tweede sessie aan de server of deze gereed is.

curl -s http://127.0.0.1:8080/health

Terwijl het bestand wordt geladen, ontvangt u een HTTP 503-foutmelding met de volgende body:

{"error":{"code":503,"message":"Loading model","type":"unavailable_error"}}

Wanneer de server gereed is, is de body {"status": "ok" }. Verstuur daarna een daadwerkelijk verzoek.

curl -s http://127.0.0.1:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model":"local","messages":[{"role":"user","content":"Say hello in five words."}]}'

Een JSON-object met een choices-array duidt op een werkende server. Het model-veld is aanwezig omdat OpenAI-clients dit altijd meesturen. Deze server heeft één model geladen, dus de waarde wordt niet gebruikt voor selectiedoeleinden.

De OpenAI-compatibele API en wat er nog meer op de poort staat

POST /v1/chat/completions, POST /v1/completions en POST /v1/embeddings zijn de OpenAI-compatibele routes en GET /v1/models rapporteert het geladen model. GET /health is de hierboven genoemde readiness-check, GET /props retourneert de huidige instellingen van de server en GET /metrics stelt Prometheus-tellers beschikbaar wanneer u start met --metrics.

Elke OpenAI SDK werkt zodra u de base URL instelt op http://127.0.0.1:8080/v1 en een niet-lege API-key-string doorgeeft. Niets controleert die sleutel totdat u --api-key zelf instelt.

Neem de doorvoersnelheid van een ander niet als uitgangspunt voor uw eigen plan. De snelheid van CPU-inference hangt af van het aantal cores, de geheugenbandbreedte en de buren waarmee u de host deelt. Meet daarom zelf het aantal tokens per seconde op uw eigen machine en beschouw dat resultaat als de waarheid. Steal time van een luidruchtige buur uit zich hier als een generatiesnelheid die van uur tot uur varieert.

Houd het op 127.0.0.1 en plaats er een proxy voor

--host staat standaard al op 127.0.0.1, waardoor de server van buitenaf onbereikbaar is totdat u dit wijzigt. Laat dit ongewijzigd. Er is geen gebruikersmodel, geen rate limit en geen bruikbaar auditlogboek in llama-server, en de enige ingebouwde controle is --api-key, die één string vergelijkt. Een open inference-poort is gratis rekenkracht voor iedereen die deze vindt, en dezelfde fout bij Ollama heeft dezelfde gevolgen: het beveiligen van een zelfgehoste model-API is hier regel voor regel van toepassing.

Beëindig TLS (transport layer security) in nginx en proxy naar de loopback-poort.

server {
    listen 443 ssl;
    server_name llm.example.com;

    location /v1/ {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_buffering off;
        proxy_read_timeout 600s;
    }
}

proxy_buffering off is vereist voor streaming. Als buffering is ingeschakeld, houdt nginx de server-sent events (SSE) vast totdat het antwoord is voltooid; de client wacht dan in stilte en ontvangt vervolgens het volledige antwoord in één keer. proxy_read_timeout 600s dekt lange generaties, omdat de standaardwaarde van 60 seconden een traag antwoord verandert in 504 Gateway Time-out. Verkrijg het certificaat met Certbot en Let's Encrypt op nginx.

De systemd unit

Schrijf /etc/systemd/system/llama-server.service.

[Unit]
Description=llama.cpp server
After=network-online.target
Wants=network-online.target

[Service]
User=llama
Group=llama
Environment=LLAMA_ARG_MODEL=/srv/models/gemma-3-1b-it-Q4_K_M.gguf
Environment=LLAMA_ARG_HOST=127.0.0.1
Environment=LLAMA_ARG_PORT=8080
Environment=LLAMA_ARG_CTX_SIZE=4096
Environment=LLAMA_ARG_N_PARALLEL=1
Environment=LLAMA_ARG_THREADS=2
ExecStart=/usr/local/bin/llama-server --no-webui
Restart=on-failure
RestartSec=5
TimeoutStopSec=30
MemoryHigh=3G
MemoryMax=3500M
OOMPolicy=stop
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes

[Install]
WantedBy=multi-user.target

De instellingen staan in Environment=-regels omdat llama-server voor de meeste vlaggen LLAMA_ARG_*-variabelen inleest, en een opdrachtregelargument de overeenkomstige variabele overschrijft. Dit geeft u één centrale plek om de contextgrootte te wijzigen en houdt ExecStart kort genoeg om in één oogopslag te lezen.

ProtectSystem=strict maakt het volledige bestandssysteem alleen-lezen voor deze unit, wat prima is omdat de server het model alleen leest. Voeg ReadWritePaths=/srv/models toe als u wilt dat de service zelf modellen downloadt met -hf. ProtectHome=yes verbergt /home en /root, en dat is de tweede reden om modellen in /srv te bewaren: met ProtectHome ingeschakeld is het standaard ~/.cache/llama.cpp-pad voor het proces in het geheel niet zichtbaar.

sudo systemctl daemon-reload
sudo systemctl enable --now llama-server
systemctl status llama-server
curl -s http://127.0.0.1:8080/health
journalctl -u llama-server -n 50 --no-pager

enable --now is de stap die mensen vaak overslaan. Zonder enable is de server na de volgende herstart verdwenen. Als u geplande taken rondom de service wilt uitvoeren, zoals een dagelijkse controle op een nieuwe release, dan is een systemd service plus timer het juiste mechanisme daarvoor.

Bepaal wat er gebeurt bij OOM voordat het zover is

Geheugengebruik bestaat uit twee delen, en deze reageren verschillend onder een limiet. Het modelbestand wordt standaard via memory-mapping geladen, waardoor de pagina's file-backed zijn: de kernel kan deze verwijderen en opnieuw inlezen vanaf de schijf. De KV cache, de status per token die de server bijhoudt voor elke actieve conversatie, is anoniem geheugen. Dit kan niet worden verwijderd, waardoor dit de oorzaak is van het beëindigen van het proces.

Daarom hebben de twee limieten in de unit verschillende functies. MemoryHigh=3G is een soft limit: daarboven zet de kernel de cgroup onder druk om geheugen vrij te maken, waardoor gemapte modelpagina's worden verwijderd en bij het volgende token opnieuw vanaf de schijf worden ingelezen. De service blijft werken, maar wordt trager. MemoryMax=3500M is een hard limit: daarboven wordt het proces beëindigd en dit wordt duidelijk vermeld in de journal.

llama-server.service: A process of this unit has been killed by the OOM killer.

Stel --ctx-size zelf in. De standaardwaarde is 0, wat overeenkomt met de context waarvoor het model is getraind. Bij een modern model met een lange context wordt bij het opstarten een zeer grote KV cache toegewezen. De service crasht vervolgens voordat er ook maar één verzoek is verwerkt. --parallel vermenigvuldigt deze kosten, omdat elke slot een eigen conversatiestatus bijhoudt. Laat deze waarde op 1 staan totdat u weet dat u gelijktijdigheid nodig heeft.

Met Restart=on-failure komt een beëindigde service weer terug. Als de service bij elke start wordt beëindigd, geeft systemd het op en print systemctl status de melding start request repeated too quickly. Dat is het juiste gedrag: een herstartlus die elke vijf seconden een bestand van 12 GB opnieuw inleest, is schadelijker dan een uitval. Corrigeer de limiet of de contextgrootte en wis vervolgens de status met sudo systemctl reset-failed llama-server.

Monitor het werkelijke getal met systemctl show llama-server -p MemoryCurrent terwijl een verzoek wordt uitgevoerd. Het beperken van procesgeheugen en CPU met systemd behandelt deze richtlijnen in meer detail.

Vermijd swap voor deze workload. Een geswapt model verandert elk token in willekeurige schijfleestoegang. Memory-mapping van het modelbestand bereikt hetzelfde effect met minder schade, omdat de kernel de benodigde pagina's direct uit het bestand leest.

Wanneer Ollama de betere keuze is

Dit is een keuze die u moet maken. Kies llama-server wanneer u één proces wilt met door u ingestelde flags, een build die u hebt vastgezet en een bestand dat u hebt gekozen, waarbij niets onder uw handen verandert omdat er niets anders draait.

Kies Ollama wanneer u modelbeheer wilt: modellen ophalen op naam, er meerdere op schijf bewaren, een inactief model ontladen en upgraden met één enkel commando in plaats van een herbouw. Dat is echt werk dat u anders zelf zou moeten scripten. Ollama draaien op een VPS is dezelfde taak waarbij de afweging andersom is gemaakt. Beide bieden een OpenAI-compatibele API, waardoor clientcode in beide richtingen bruikbaar blijft na de overstap.

Upgraden van een vastgezette build

Vervang bNNNNN door de tag waarnaar u wilt overstappen.

cd llama.cpp
git fetch --tags
git checkout bNNNNN
cmake -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DLLAMA_BUILD_TESTS=OFF -DLLAMA_BUILD_EXAMPLES=OFF
cmake --build build --config Release -t llama-server -j 2
sudo install -m 755 build/bin/llama-server /usr/local/bin/llama-server-bNNNNN
sudo ln -sfn /usr/local/bin/llama-server-bNNNNN /usr/local/bin/llama-server
sudo systemctl restart llama-server

Het oude binaire bestand blijft op de schijf staan, waardoor een rollback slechts één ln -sfn terug naar llama-server-b10488 en één herstart vereist. Lees de release notes voordat u de overstap maakt. GGUF-bestanden zijn voorzien van versienummers en oude versies blijven laden, maar vlaggen worden wel hernoemd: --mlock en --no-mmap zijn reeds verouderd ten gunste van --load-mode, en een unit-bestand dat een verwijderde vlag doorgeeft, zal bij het opstarten falen met een foutmelding over een niet-herkend argument.

Foutmodi en de meldingen die u zult zien

error while loading shared libraries: libllama.so nadat u het binaire bestand naar een andere locatie heeft gekopieerd. De standaard build genereert gedeelde bibliotheken in dezelfde map. Bouw opnieuw met -DBUILD_SHARED_LIBS=OFF of kopieer de volledige build/bin map.

Illegal instruction (core dumped) bij het opstarten of bij het eerste verzoek. Het binaire bestand is gecompileerd met GGML_NATIVE ingeschakeld, voor een ander type CPU dan de huidige machine. Bouw opnieuw op deze machine of configureer met -DGGML_NATIVE=OFF.

c++: fatal error: Killed signal terminated program cc1plus tijdens het build-proces. De compiler is beëindigd omdat deze te veel geheugen verbruikte. Verlaag -j of voeg tijdelijk swap toe voor de build en verwijder deze daarna weer.

curl: (7) Failed to connect ... Connection refused vanaf uw laptop. Dit is correct: de server luistert op het loopback-adres van de VPS. Test op de VPS zelf of open een tunnel met ssh -L 8080:127.0.0.1:8080 user@your-vps en gebruik http://127.0.0.1:8080 lokaal.

HTTP 503 met "message":"Loading model" gedurende de eerste seconden of minuten na een herstart. Het inlezen van een bestand van meerdere gigabytes kost tijd. systemd rapporteert de unit als actief zodra het proces start, nog voordat het model in het geheugen is geladen.

Verzoeken blijven hangen en retourneren vervolgens 504 Gateway Time-out. De proxy heeft de verbinding verbroken voordat het model klaar was. Verhoog proxy_read_timeout en schakel proxy_buffering uit zodat tokens de client bereiken zodra ze worden gegenereerd.

De unit blijft herstarten en stopt vervolgens met start request repeated too quickly. Een proces beëindigt de unit bij elke start. Controleer journalctl -u llama-server op de OOM killer-regel en verlaag vervolgens --ctx-size, verlaag --parallel of verhoog MemoryMax.

FAQ

Moet ik de server van llama.cpp of Ollama draaien op mijn VPS?

Gebruik llama-server wanneer u een specifieke build wilt vastzetten, exacte vlaggen wilt meegeven en één model in één bestand wilt houden dat niet ongemerkt wordt bijgewerkt. Gebruik Ollama wanneer u modelbeheer en upgrades met één commando wenst; het ophalen van modellen op naam, het bewaren van meerdere modellen op schijf en het ontladen van inactieve modellen is werk dat u anders zelf zou moeten scripten. Beide bieden een OpenAI-compatibele API, waardoor clientcode niet hoeft te veranderen als u later overstapt.

Aan welke versie van llama.cpp moet ik mijn installatie vastzetten?

Aan elke tag die u daadwerkelijk hebt gebouwd en getest. llama.cpp voorziet bijna elke merge van een tag en de namen zijn buildnummers zoals b10488, wat de nieuwste was op 18 augustus 2026. Er is geen afzonderlijke stabiele branch, dus "huidig" verandert meerdere keren per dag. Kloon met --branch <tag>, installeer het binaire bestand onder een bestandsnaam die die tag bevat en laat een symlink ernaar wijzen, zodat upgraden en terugdraaien elk slechts één commando kosten.

Hoeveel RAM heeft llama-server nodig?

Begin bij de grootte van het GGUF-bestand en tel daar de KV-cache bij op, die groeit met --ctx-size en het aantal --parallel-slots. Gepubliceerde cijfers zijn geen vervanging voor het meten van uw eigen configuratie, omdat het totaal afhangt van het model, de kwantisatie en de context die u toestaat. Voer systemctl show llama-server -p MemoryCurrent uit terwijl er een verzoek wordt verwerkt en gebruik het getal dat u ziet.

Waarom geeft /health een 503 met "Loading model"?

Het proces is gestart, maar het modelbestand staat nog niet in het geheugen, dus de server antwoordt met {"error":{"code":503,"message":"Loading model","type":"unavailable_error"}}. Dit is normaal na elke herstart en duurt zolang als het inlezen van het bestand in beslag neemt. Het wordt pas een probleem wanneer een client of proxy die eerste 503 als een fatale fout beschouwt. Pols /health totdat deze {"status": "ok" } teruggeeft.

Kan ik llama-server rechtstreeks blootstellen aan het internet?

Bind deze niet aan 0.0.0.0 en open de poort niet. De software heeft geen accounts, geen rate limiting en geen verzoeklogboek dat de moeite waard is om te controleren, en de enige ingebouwde controle is --api-key, die een enkele string vergelijkt. Houd de standaard 127.0.0.1-binding aan, plaats nginx ervoor met TLS en stel ook --api-key in, zodat één fout in de proxyconfiguratie het model niet voor iedereen openstelt.