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 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.
De rest van het werk is beheer: zet een versie vast, houd de poort op localhost, schrijf een systemd-unit en bepaal wat er gebeurt wanneer de server geen geheugen meer 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, omdat 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 langdurig stabiele branch, wat betekent dat "latest" een bewegend doelwit is en de versie die u heeft getest de enige versie is die u kunt ondersteunen. Kies een tag, noteer deze en gebruik diezelfde string in uw clone, in uw binairienaam 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 | headBekijk 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 waarmee ze zijn gebouwd; op een oudere distributie falen ze daarom bij het opstarten met een foutmelding die een GLIBC_-versie noemt die niet is geïnstalleerd. Het bouwen vanuit de broncode duurt op een kleine VPS slechts enkele minuten en elimineert deze gehele categorie problemen; daarom volgen we hieronder dat pad.
Bouw llama-server vanaf een vastgezette 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-kloon checkt uitsluitend die 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 de binary in staat om later modellen via HTTPS te downloaden. Zonder de headers mislukt de configuratiestap.
-DBUILD_SHARED_LIBS=OFF levert één op zichzelf staande binary 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 alleen 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 compile-taak houdt een eigen werkset vast, 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 mogelijk wilt wijzigen: GGML_NATIVE staat standaard aan, waardoor de compiler zich richt op de specifieke CPU die de build uitvoert. Dit is gewenst wanneer u bouwt op de machine die de software ook gaat draaien. Als u eenmalig bouwt en de binary naar een andere host kopieert, voeg dan -DGGML_NATIVE=OFF toe, omdat een binary die instructies gebruikt die de andere CPU niet ondersteunt, crasht 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 te behouden en er een symlink naar te laten wijzen, is een upgrade slechts één ln -sfn plus een herstart, en een rollback is hetzelfde commando met het oude nummer.
Een GGUF-model ophalen en eerst de schijfruimte controleren
GGUF is het bestandsformaat dat llama.cpp inlaadt. Eén bestand bevat de gewichten, de tokenizer en de metadata, waardoor er geen verdere installatie nodig is. 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 half-precision bestand.
Maak een service-account en een modelmap 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 /srvDe server kan zelf een model ophalen met -hf; dit is de snelste manier om te verifiëren of uw build correct 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 8080LLAMA_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 een stabiele verwijzing heeft.
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.ggufSchijfruimte is de beperking waar men het eerst tegenaan loopt. Dit zijn de gepubliceerde bestandsgroottes voor twee modellen, gecontroleerd op 18 augustus 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 instapabonnementen niet op de schijf, en bovendien moet het bestand daarna nog in het geheugen worden geladen.
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-webuiVraag in een tweede sessie aan de server of deze gereed is.
curl -s http://127.0.0.1:8080/healthTerwijl 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 gereedheidscontrole, 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 basis-URL instelt op http://127.0.0.1:8080/v1 en een niet-lege API-sleutelreeks 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-inferentie 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 generatiesnelheid die van uur tot uur verandert.
Houd het op 127.0.0.1 en plaats een proxy ervoor
--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 limiting 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, waardoor de client in stilte wacht en vervolgens het volledige antwoord in één keer ontvangt. 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.targetDe instellingen staan in Environment=-regels omdat llama-server de variabelen uit LLAMA_ARG_* leest voor de meeste vlaggen, en een opdrachtregelargument de overeenkomstige variabele overschrijft. Dit biedt éé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 standaardpad ~/.cache/llama.cpp 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-pagerenable --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 nachtelijke controle op een nieuwe release, dan is een systemd service plus timer het juiste mechanisme hiervoor.
Bepaal wat er bij OOM gebeurt voordat het zover is
Geheugengebruik bestaat uit twee delen, en deze gedragen zich verschillend onder een limiet. Het modelbestand is standaard via memory-mapping gekoppeld, dus de pagina's zijn bestand-gebaseerd: de kernel kan deze verwijderen en opnieuw inlezen vanaf de schijf. De KV-cache, de per-token status die de server bijhoudt voor elke actieve conversatie, is anoniem geheugen. Dit kan niet worden verwijderd, waardoor het proces wordt beëindigd.
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 meldt het journal dit duidelijk.
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 staat voor de context waarmee het model is getraind; bij een modern model met een lange context wordt bij het opstarten een zeer grote KV-cache toegewezen. De service sterft dan voordat deze een enkel verzoek kan verwerken. --parallel vermenigvuldigt dezelfde kosten, omdat elke slot zijn eigen conversatiestatus vasthoudt; laat dit dus op 1 staan totdat u weet dat u gelijktijdigheid nodig heeft.
Met Restart=on-failure komt een beëindigde service weer terug. Als deze 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 erger dan een uitval. Corrigeer de limiet of de contextgrootte en wis vervolgens de status met sudo systemctl reset-failed llama-server.
Houd het werkelijke getal in de gaten 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 tussen twee paden. 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 voeten 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 de andere kant op 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 overstapt.
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-serverHet 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 bestanden 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, faalt bij het opstarten met een melding 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 gehele 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 het 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, en systemd rapporteert de unit als actief zodra het proces start, nog voordat het model in het geheugen is geladen.
Verzoeken blijven hangen en retourneren daarna 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 uiteindelijk met start request repeated too quickly. Iets beëindigt het proces bij elke start. Controleer journalctl -u llama-server op de OOM killer-regel, verlaag vervolgens --ctx-size, verlaag --parallel, of verhoog MemoryMax.
FAQ
Moet ik de server van llama.cpp of Ollama draaien op mijn VPS?
Draai llama-server wanneer u een specifieke build wilt vastzetten, exacte flags wilt meegeven en één model in één bestand wilt houden dat niet ongemerkt wordt bijgewerkt. Draai Ollama wanneer u modelbeheer en upgrades met één commando wenst, omdat het ophalen van modellen op naam, het bewaren van meerdere modellen op schijf en het ontladen van inactieve modellen werk is 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 vastpinnen?
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 daarnaar 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 voeg daar de KV-cache aan toe, die groeit met --ctx-size en met 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 een verzoek wordt verwerkt en gebruik het getal dat u ziet.
Waarom geeft /health een 503-fout 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 het {"status": "ok" } teruggeeft.
Kan ik llama-server rechtstreeks blootstellen aan het internet?
Bind de server 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 bind aan, plaats nginx ervoor met TLS en stel ook --api-key in, zodat één fout in de proxyconfiguratie het model niet voor iedereen openstelt.