SSD Nodes Learn 🎉 VPS from $5.50/mo
Guides Matt ConnorBy Matt Connor

Pin llama.cpp releases on your server

llama.cpp now cuts v0.x tags beside its bNNNN build tags. Pin one, record it with the GGUF and quant, and treat every upgrade as a drill you can undo.

What changed in llama.cpp versioning

Pinning llama.cpp releases means building one named tag and recording that name beside the model file. The tag never moves on its own, so the server keeps producing tomorrow what it produced today. For years there was only one kind of tag to choose: a build number like b10502, cut from master automatically. Since 2026 there is a second kind, a version tag like v0.1.2, and both tracks are cut from the same history at the same time.

The version tags do not yet mean what a version number usually means. The release notes on v0.1.2 say so in one line:

Semantic versioning is still work in progress. More info can be found in https://github.com/ggml-org/ggml/discussions/1579

Take that at face value. The ggml discussion behind that link is where the scheme is still being worked out, including how often to cut a release and what counts as a patch. A v0. tag tells you the project chose to mark a point in the history. It does not promise that the next one is a safe drop-in because the last digit moved by one.

The number in a build tag carries no version meaning either. It comes from the commit count, so it rises on its own whether or not anything relevant to your setup changed. As of 19 August 2026 the front page of the releases list held nine build tags, from b10455 to b10502, with v0.1.2 sitting among them.

Never build from master on a box that serves anything

git pull followed by a rebuild gives you whatever landed in the last few hours. That is fine on a laptop. On a server it removes your ability to answer the question that matters when behaviour changes: what is running now, and what was running last week. The text a model produces and the speed it produces it at both move with the build. A complaint that answers got worse last Tuesday has no answer if Tuesday's commit was never written down.

Pin a tag instead. The project cuts them for you, and every prebuilt release archive is named after one.

Which tag should you pin llama.cpp releases to?

Pin a build tag when you want one specific known state. This is the track with the long history, the track the release archives are named after, and the one most bug reports quote, so a build number is the easiest thing to compare with somebody else.

Pin a version tag if you would rather follow a shorter list of deliberate points. Read its notes before you move, and keep the caveat above in mind, because the numbering is not a compatibility contract yet.

Either way the operational rule is identical. The tag string lives in a file, the box is rebuilt only when that string changes, and the change is a decision somebody made on purpose.

Build the pinned tag

sudo apt update
sudo apt install -y build-essential cmake git
git clone --depth 1 --branch b10502 https://github.com/ggml-org/llama.cpp.git ~/src/llama.cpp-b10502
cd ~/src/llama.cpp-b10502
git describe --tags

git describe --tags should print b10502. A shallow clone at a tag holds that commit and nothing after it, so nobody can move it later with a careless git pull. If the configure step stops on a missing dependency, install what it names and run it again.

Build with the options your hardware needs. CPU only:

cmake -B build
cmake --build build --config Release -j $(nproc)

NVIDIA GPU, which needs the CUDA toolkit installed first:

cmake -B build -DGGML_CUDA=ON
cmake --build build --config Release -j $(nproc)

OpenBLAS on a CPU-only box:

cmake -B build -DGGML_BLAS=ON -DGGML_BLAS_VENDOR=OpenBLAS
cmake --build build --config Release -j $(nproc)

Binaries land in build/bin, next to the shared libraries they load (libllama.so and the libggml files). Confirm the build runs before you install it:

./build/bin/llama-server --version

Install the whole directory under a path named after the tag, then point one symlink at it:

sudo install -d /opt/llama.cpp/b10502
sudo cp -a build/bin /opt/llama.cpp/b10502/bin
sudo ln -sfn /opt/llama.cpp/b10502 /opt/llama.cpp/current

Copy the directory, not the single file. A lone llama-server fails on its first run with error while loading shared libraries: libllama.so: cannot open shared object file, because the libraries it needs sit beside it in that directory.

Point the service at the symlink, never at a tag directory:

[Service]
ExecStart=/opt/llama.cpp/current/bin/llama-server -m /srv/models/model-q4_k_m.gguf -c 8192 -ngl 99 --host 127.0.0.1 --port 8080

systemd resolves the symlink when it starts the process, so switching builds is a new symlink target plus sudo systemctl restart llama-server. The rest of the unit file and the reverse proxy in front of it are covered in the full walkthrough for a llama.cpp server on a VPS.

Record the tag beside the GGUF file and the quant

The build is half of what decides the output. The model file is the other half. GGUF (GGML universal file format) is the container the weights ship in, and the same model is published at many quantisation levels, so two servers on the same tag can still disagree because one holds a Q4_K_M file and the other a Q8_0. Keep one small file next to the model holding everything needed to rebuild the setup exactly:

tag: b10502
commit: 7c1f2a9
model_file: model-q4_k_m.gguf
model_sha256: <output of sha256sum>
quant: Q4_K_M
cmake_args: -DGGML_CUDA=ON
cuda: <output of nvcc --version>
bench_cmd: llama-bench -p 512 -n 128 -r 5
bench_result: <fill in from the run on this box>

Get the commit with git rev-parse --short HEAD inside the pinned checkout. Get the checksum with sha256sum model-q4_k_m.gguf, and compare it with the publisher's value at download time too, because checking a download against its published checksum catches a truncated file before it turns into a confusing bug. How much the quantisation level itself changes the answers is a separate question, and what each quantisation level costs you covers it.

How do you upgrade without breaking the server?

Run the upgrade as a drill. Build the new tag beside the old one, measure both, and keep the old one until the new one has won.

  1. Clone the new tag into its own directory. Do not reuse the old checkout.
  2. Build it with the same cmake arguments recorded in the manifest.
  3. Run llama-bench on both builds against the same model file, with the same prompt length and the same repetition count.
  4. Send a prompt whose answer you know well through both servers and read the two replies.
  5. Move the symlink, restart the service, and leave the old directory on disk.
/opt/llama.cpp/b10502/bin/llama-bench -m /srv/models/model-q4_k_m.gguf -p 512 -n 128 -r 5
/opt/llama.cpp/<new tag>/bin/llama-bench -m /srv/models/model-q4_k_m.gguf -p 512 -n 128 -r 5

llama-bench prints one row per test, with a backend column, an ngl column and a tokens per second column carrying its standard deviation. Compare the same row between the two builds, not one build's prompt row against the other's generation row. A figure taken at a different prompt length is a different measurement, which is why measuring tokens per second the same way every time matters more than the number itself.

Rolling back is two commands, and it works only because the old directory is still there:

sudo ln -sfn /opt/llama.cpp/b10502 /opt/llama.cpp/current
sudo systemctl restart llama-server

Keep at least the previous build. It costs a fraction of the disk the model file beside it already uses.

What breaks across llama.cpp upgrades

A model file stops loading. This is usually what makes people upgrade in the first place: a newly published model uses an architecture the pinned build does not know, so it never loads. llama-server exits during startup and the log carries a failed to load model from /srv/models/model-q4_k_m.gguf line. Read the lines printed just before it, which show how far the loader got. GGUF also carries a format version in its header (the spec's current value is 3, and version 2 widened the length fields from 32 to 64 bits), though in practice an unknown architecture name stops you long before the format version does. The fix is a newer tag, chosen and written down.

A server flag is renamed or deprecated. An unrecognised flag stops llama-server at startup rather than being ignored, which under systemd looks like a service that starts and dies in a loop. journalctl -u llama-server -n 50 shows the real message. As of 19 August 2026 the server documentation marks --mlock and --mmap as deprecated in favour of -lm, --load-mode, which takes values such as auto, mmap, mlock and dio. The GPU offload flag is documented as -ngl, --gpu-layers, while older guides write --n-gpu-layers. Before you move the symlink, run /opt/llama.cpp/<new tag>/bin/llama-server --help and check every flag in your unit file against it.

A build option is renamed. The CMake options moved from a LLAMA_ prefix to a GGML_ prefix, and the root CMakeLists.txt still carries the mapping. LLAMA_CUBLAS is now a fatal error naming GGML_CUDA as its replacement, while LLAMA_CUDA and LLAMA_METAL produce a warning and are translated for you. A build script that stops at the configure step is the good outcome. The quiet failure is worse: leave out -DGGML_CUDA=ON by accident and the build succeeds, the server starts, and everything runs on the CPU. llama-bench shows it at once, because the backend column reads CPU.

The accelerator build is not portable. As of 19 August 2026 the Linux assets attached to a build tag are the CPU, Vulkan, SYCL and OpenVINO variants, for x64, arm64 and s390x. There is no CUDA archive for Linux in that list, so an NVIDIA server means building from source or running a container image. The Windows CUDA archives are published per toolkit version, which is a useful hint: the toolkit version is part of what identifies your binary, so record it alongside the cmake arguments.

Pinning the container image instead

Same rule, different noun. The published images (ghcr.io/ggml-org/llama.cpp:server and its accelerator variants) are moving names, so pulling :server next month gives you a different program under the same label. Pull once and read the digest:

docker pull ghcr.io/ggml-org/llama.cpp:server

docker pull prints a Digest: sha256:... line. Put that digest in the compose file in place of the tag, and the image cannot change under you the next time somebody runs docker compose pull. Keep the previous digest in a comment so a rollback is one edit, the same way the upgrade and rollback routine for a Compose stack treats every other service.

The point of a pin

A pin lets you say exactly what is running, and it lets you put the previous build back within a minute when a change makes things worse. llama.cpp asks you to track two things for that, the build tag and the model file, because it hands you the two separately. Runtimes that bundle them behave differently, and the comparison of Ollama and llama.cpp as servers covers that trade: one version number over the whole thing is less to record and less to control.

FAQ

Should I pin the bNNNN build tag or the v0.x tag?

Either works, as long as you pin something. Build tags such as b10502 are the long-running track: every prebuilt release archive is named after one and most bug reports quote one, so a build number is the easiest thing to compare with another operator. Version tags such as v0.1.2 are a shorter list of deliberate points, which suits a server you touch a few times a year. What matters more than the choice is that the tag string sits recorded next to the model file, and that upgrading is a decision rather than a side effect of git pull.

Does llama.cpp follow semantic versioning now?

Not yet, by the project's own statement. The v0.1.2 release notes say that semantic versioning is still work in progress and point at a ggml discussion where the scheme is being worked out, including release cadence and what counts as a patch. Read a version tag as a point the maintainers chose to mark. Do not assume a change in the last digit guarantees a drop-in upgrade, and test the new tag against your own model file before switching to it.

How do I tell which llama.cpp build my server is running?

llama-server --version prints the version and build information. The startup log also opens with a build line holding the build number, the commit hash and the compiler used, so journalctl -u llama-server finds it for a running service. On a source install, git describe --tags inside the pinned checkout prints the tag, and readlink /opt/llama.cpp/current shows which directory the service is actually pointed at.

Why did my model stop loading after I upgraded llama.cpp?

A load failure straight after an upgrade is a mismatch between the build and the GGUF file. The log ends with a failed to load model from line naming the path, and the lines above it show how far the loader read. Moving forwards, a very new model file needs a build that knows its architecture. Moving backwards, a rollback below the tag the file was made for can break a file that worked yesterday. Point the symlink at the previous build, restart, and confirm which build and file paired correctly before deciding which of the two to change.

Are there prebuilt Linux binaries I can pin instead of building?

Yes, for some setups. Each build tag carries release archives named after it, such as llama-b10502-bin-ubuntu-x64.tar.gz, with arm64, s390x, Vulkan, SYCL and OpenVINO variants alongside it as of 19 August 2026. The naming makes pinning easy, since the tag is in the filename. There was no CUDA archive for Linux in that list, so an NVIDIA server still means building from source with -DGGML_CUDA=ON or running one of the CUDA container images.