MAATRIX / Блог / Как установить и настроить llama.cpp на VPS

Как установить и настроить llama.cpp на VPS

Как установить и настроить llama.cpp на VPS

MAATRIX

Инструкции по llama.cpp обычно заканчиваются на cmake --build build, а дальше начинается настоящая жизнь: сборка падает по памяти, бинарь ловит Illegal instruction, скачанный GGUF оказывается текстовым файлом на 130 байт, сервер молча отвечает 503. Разберём установку llama.cpp на VPS без видеокарты — от флагов CMake до systemd-юнита, потоков и защиты порта.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Что даёт llama.cpp и когда он лучше готовых обёрток

llama.cpp — движок инференса на C/C++ поверх библиотеки ggml, работающий с моделями в формате GGUF. Ему не нужны ни Python, ни PyTorch, ни CUDA: каталог бинарников занимает десятки мегабайт, тогда как venv у vLLM переваливает за 5 ГБ и без GPU не стартует вовсе. Это единственный вменяемый способ гонять локальную модель на VPS с четырьмя гигабайтами памяти.

Инструментов несколько: llama-cli для проверки в терминале, llama-server с OpenAI-совместимым API и веб-мордой (он и работает постоянно), llama-bench для замеров, llama-quantize для сжатия весов, llama-gguf-split для томов. Ollama и LM Studio — обёртки над той же ggml: удобнее в первый день и менее управляемы на второй. llama.cpp даёт прямой доступ к тому, что они прячут: потоки на генерацию и на промпт по отдельности, размер контекста, число слотов, тип KV-кэша.

Минусы стоит знать заранее. Семантического версионирования нет: релизы нумеруются сборками вида b9222, и флаги между ними меняются — булев -fa превратился в --flash-attn on|off|auto со значением auto по умолчанию, и старые скрипты ругаются на неизвестный аргумент. Параллелизм слабее специализированных серверов: четырёх пользователей движок держит отлично, сотни сессий — задача для vLLM на видеокарте. Скорость на CPU — единицы и десятки токенов в секунду: хватит личному ассистенту, но не публичному чат-боту.

Готовим VPS: пакеты, swap и честный расчёт памяти

Проверялось на Ubuntu 24.04 (cmake 3.28, gcc 13) и Debian 12 (cmake 3.25, gcc 12): нужен C++17 и CMake не ниже 3.14, штатных пакетов хватает.

sudo apt update
sudo apt install -y build-essential cmake git libcurl4-openssl-dev ccache

Дальше арифметика памяти — источник основного разочарования. RAM складывается из трёх слагаемых: веса + KV-кэш под контекст + вычислительные буферы. Первое известно заранее — вот наши замеры на стенде AMD EPYC 9554 (16 vCPU), снятые через Ollama 0.33.1: это обёртка над той же ggml с теми же GGUF, цифры переносятся напрямую.

Модель, квант Q4_K_MЗанято в памяти
qwen2.5:3b2,2 ГБ
mistral:7b5,0 ГБ
qwen2.5:7b5,1 ГБ
llama3.1:8b5,6 ГБ

Второе считается формулой: на токен контекста уходит 2 × слои × KV-головы × размер головы × 2 байта — двойка в начале это ключи и значения, двойка в конце f16.

  • Qwen2.5-7B: 28 слоёв, 4 KV-головы, голова 128 → 56 КиБ на токен. Контекст 8192 стоит 448 МиБ, 32768 — уже 1,75 ГиБ.
  • Llama-3.1-8B: 32 слоя, 8 KV-голов, голова 128 → 128 КиБ на токен. Контекст 8192 стоит 1 ГиБ, а обещанные в описании 128k потребуют 16 ГиБ только под кэш, сверх 5,6 ГБ весов.

Вывод: модель 8B в Q4 с контекстом 8k просит около 7 ГБ свободной памяти — на VPS с 8 ГБ это впритык. Подробнее — в статье сколько RAM нужно для Llama.

Swap нужен на сборке: компиляция ggml на двухгигабайтной машине с -j$(nproc) приводит к c++: fatal error: Killed signal terminated program cc1plus.

sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile && sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
sudo sysctl -w vm.swappiness=10

Но swap спасает компиляцию, а не инференс: если веса не влезли в RAM, генерация падает до долей токена в секунду. Лечится памятью, а не настройками: что делать при нехватке RAM.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Сборка из исходников: CMake, флаги и грабля с -march=native

Базовый сценарий — три команды и 5–20 минут.

git clone https://github.com/ggml-org/llama.cpp /opt/llama.cpp
cd /opt/llama.cpp
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release -j 4

Обратите внимание на адрес: проект переехал из ggerganov/llama.cpp в ggml-org. Бинарники окажутся в build/bin/.

Could NOT find CURL (missing: CURL_LIBRARY CURL_INCLUDE_DIR) — самая частая ошибка первой сборки: LLAMA_CURL включён по умолчанию, а заголовков libcurl нет. Либо ставите пакет из раздела выше, либо собираете с -DLLAMA_CURL=OFF и теряете загрузку моделей флагом -hf.

Illegal instruction (core dumped) — бинарь собрался, но падает при первом запуске без единой строчки лога. GGML_NATIVE включён по умолчанию и даёт компилятору -march=native: код затачивается под инструкции хоста в момент сборки. На VPS это мина — провайдер переносит виртуалку на другую ноду, и вчера работавший сервер умирает молча. Портируемая сборка та же, что в релизах:

cmake -B build -DCMAKE_BUILD_TYPE=Release \
  -DGGML_NATIVE=OFF -DGGML_BACKEND_DL=ON -DGGML_CPU_ALL_VARIANTS=ON
cmake --build build --config Release -j 4

GGML_CPU_ALL_VARIANTS собирает варианты бэкенда без AVX, с AVX2 и с AVX-512, а GGML_BACKEND_DL подгружает нужный при запуске.

llama-server: error while loading shared libraries: libllama.so: cannot open shared object file — после установки: разделяемые библиотеки уезжают в /usr/local/lib, куда линковщик не смотрит.

sudo cmake --install build --prefix /usr/local
sudo ldconfig
llama-server --version

Нужен самодостаточный файл для переноса между машинами — соберите с -DBUILD_SHARED_LIBS=OFF. Собирать вовсе не обязательно: в releases лежат архивы вида llama-b9222-bin-ubuntu-x64.zip. А OpenBLAS (-DGGML_BLAS=ON) ускоряет только промпт и заметен на процессорах без AVX2.

Модели в GGUF: где брать, как не скачать заглушку, как квантовать своё

Со сборкой, знающей curl, llama-server скачает модель сам: llama-server -hf bartowski/Qwen2.5-7B-Instruct-GGUF:Q4_K_M. Файл ляжет в ~/.cache/llama.cpp (каталог задаётся через LLAMA_CACHE). На продакшене удобнее качать явно:

pip install -U "huggingface_hub[cli]"
hf download bartowski/Qwen2.5-7B-Instruct-GGUF \
  --include "Qwen2.5-7B-Instruct-Q4_K_M.gguf" \
  --local-dir /opt/models

Команда huggingface-cli download из старых мануалов работает, но объявлена устаревшей в пользу hf.

Главная ловушка. Утянете файл через wget по ссылке вида .../blob/main/... — получите не модель, а указатель Git LFS: 130 байт текста, начинающихся с version https://git-lfs.github.com/spec/v1. Запуск закончится так:

gguf_init_from_file: invalid magic characters 'vers'
llama_model_load: error loading model: llama_model_loader: failed to load model from /opt/models/model.gguf
common_init_from_params: failed to load model '/opt/models/model.gguf'
srv    load_model: failed to load model

Настоящий GGUF начинается с четырёх байт GGUF, проверка за секунду:

head -c 4 /opt/models/Qwen2.5-7B-Instruct-Q4_K_M.gguf; echo
ls -lh /opt/models/*.gguf

Сверьте и размер: оборванная закачка даёт ту же ошибку, только магия будет корректной. Для прямой ссылки нужен путь resolve, а не blob, плюс wget --content-disposition -c.

Вторая ошибкаllama_model_load: error loading model architecture: unknown model architecture: 'qwen3moe': модель новее бинарника, лечится git pull и пересборкой. Многотомные веса вида model-00001-of-00003.gguf свежие сборки подхватывают сами, если указать первую часть.

Своё квантование требуется, когда подходящего уровня никто не выложил:

python3 -m venv /opt/llama.cpp/venv && source /opt/llama.cpp/venv/bin/activate
pip install -r /opt/llama.cpp/requirements.txt
python3 /opt/llama.cpp/convert_hf_to_gguf.py /opt/hf/Qwen2.5-7B-Instruct \
  --outfile /opt/models/qwen2.5-7b-f16.gguf --outtype f16
llama-quantize /opt/models/qwen2.5-7b-f16.gguf \
  /opt/models/qwen2.5-7b-Q4_K_M.gguf Q4_K_M

Честно про цену: промежуточный F16 для 7B занимает около 15 ГБ сверх исходных safetensors — держите свободными 35 ГБ. Разумный дефолт — Q4_K_M; ниже спускаться не стоит: первым ломается не английский, а русский и вывод в JSON. Подробнее — в разборе какое квантование выбрать.

Первый запуск: llama-cli, llama-server и проверка API

Убедитесь, что модель читается:

llama-cli -m /opt/models/Qwen2.5-7B-Instruct-Q4_K_M.gguf \
  -p "Назови три достопримечательности Лондона" -n 96 -no-cnv

Флаг -no-cnv выключает интерактивный режим: модель отвечает и процесс завершается. В логе смотрите строки n_ctx и n_threads — там видно, что движок решил сам.

llama-server -m /opt/models/Qwen2.5-7B-Instruct-Q4_K_M.gguf \
  --host 127.0.0.1 --port 8080 \
  -c 8192 -t 8 -np 1 --jinja

Дефолты стоит знать: адрес 127.0.0.1, порт 8080, контекст 4096 токенов. Наружу сервер из коробки не смотрит — это ломают первым же --host 0.0.0.0. Флаг --jinja включает разбор чат-шаблона из GGUF; без него ломаются вызовы инструментов.

curl -s http://127.0.0.1:8080/health
curl -s http://127.0.0.1:8080/props | jq '.default_generation_settings.n_ctx'
curl -s http://127.0.0.1:8080/v1/chat/completions -H 'Content-Type: application/json' \
  -d '{"model":"any","messages":[{"role":"user","content":"Одно предложение о Темзе"}]}' \
  | jq -r '.choices[0].message.content'

Здоровый сервер отвечает {"status":"ok"}. Пока веса читаются с диска, приходит HTTP 503 и тело {"error":{"code":503,"message":"Loading model","type":"unavailable_error"}} — это не поломка, а загрузка: на холодном кэше страниц для модели в 5 ГБ она занимает десятки секунд. Учитывайте в скриптах деплоя.

Поле model сервер игнорирует: модель у него одна. Кроме OpenAI-совместимых путей есть родные /completion, /props, /slots и /metrics, а по корню / — встроенный веб-интерфейс.

Настройка под нагрузку: потоки, контекст, слоты и обвязка

Самый недооценённый параметр — число потоков. Наш замер на AMD EPYC 9554, 16 vCPU (8 физических ядер плюс HT), qwen2.5:7b в Q4_K_M, Ollama 0.33.1 — тот же ggml-движок, что внутри llama.cpp:

ПотоковГенерация, ток/сОбработка промпта, ток/с
25,712,6
47,631,0
87,661,7
167,468,0
320,3510,9

Генерация выходит на полку уже на четырёх потоках. Дальше она не растёт: упирается не в процессор, а в пропускную способность памяти — на каждый токен движок читает все веса. Обработка промпта считает матрицы и растёт до 8–16 потоков. Отсюда: -t по числу физических ядер, -tb (потоки на батч) — по числу vCPU.

Потоков больше, чем vCPU, — катастрофа. 32 потока на 16 vCPU дали обвал в двадцать раз: 0,35 токена в секунду вместо 7,4. Никогда не выставляйте -t «с запасом».

Модель важнее числа ядер. На том же стенде при 16 потоках llama3.1:8b дала 12,8 токена в секунду, mistral:7b — 12,1, gemma2:9b — 8,8, qwen2.5:3b — 34,1. Смежные грабли — в статьях Ollama медленно генерирует токены и Ollama не использует все ядра CPU.

Контекст и слоты. Параметр -c задаёт не контекст на запрос, а общий бюджет токенов, делящийся между слотами -np: -c 8192 -np 4 даёт четырём клиентам по 2048 токенов, и на первом же длинном документе прилетит 400: the request exceeds the available context size. try increasing the context size or enable context shift. Контекстный сдвиг по умолчанию выключен — сервер отказывает вместо молчаливого обрезания диалога.

Память под KV-кэш ополовинивает его квантование; при -fa auto (по умолчанию) flash attention включается сам. Плата — деградация на длинных контекстах, заметная в точном цитировании:

llama-server -m /opt/models/Qwen2.5-7B-Instruct-Q4_K_M.gguf \
  -c 32768 -np 2 -t 8 -tb 16 \
  --cache-type-k q8_0 --cache-type-v q8_0 --jinja

Systemd вместо nohup. У всех аргументов есть парные переменные LLAMA_ARG_*, и юнит выходит компактным:

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

[Service]
User=llama
Group=llama
WorkingDirectory=/opt/llama.cpp
Environment=LLAMA_ARG_MODEL=/opt/models/Qwen2.5-7B-Instruct-Q4_K_M.gguf
Environment=LLAMA_ARG_CTX_SIZE=8192
Environment=LLAMA_ARG_THREADS=8
Environment=LLAMA_ARG_HOST=127.0.0.1
Environment=LLAMA_ARG_PORT=8080
EnvironmentFile=-/etc/llama/llama.env
ExecStart=/usr/local/bin/llama-server
Restart=on-failure
RestartSec=5
LimitMEMLOCK=infinity

[Install]
WantedBy=multi-user.target

Ключ кладите в /etc/llama/llama.env строкой LLAMA_ARG_API_KEY=sk-... под chown root:llama и chmod 640. LimitMEMLOCK=infinity нужен при --mlock, иначе в логе будет failed to mlock ... Cannot allocate memory.

Доступ снаружи. Порт 8080 не публикуйте: без --api-key сервер обслуживает любого, кто дотянулся. Схема — ufw allow 22/tcp, ufw allow 443/tcp, ufw deny 8080/tcp, наружу только Nginx с TLS. Для стриминга обязательны две директивы, иначе ответ придёт одним куском в конце:

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

Какой сервер под llama.cpp взять в MAATRIX

llama.cpp упирается в память и её пропускную способность, а не в частоту, — это видно по таблице выше. Конфигурацию подбирают от модели и контекста, а не от числа ядер.

Честный минимум: 2 vCPU, 4 ГБ RAM, 40 ГБ NVMe. Влезает модель 3B в Q4 — по нашему замеру 2,2 ГБ весов — плюс контекст 4096 и место под сборку. Но два ядра не дотягивают до полки, которая начинается на четырёх: это площадка для знакомства и фоновых задач по расписанию.

Рабочий вариант: 4 vCPU, 8 ГБ RAM, 80 ГБ NVMe. Под модели 7–8B в Q4_K_M: 5,0–5,6 ГБ весов, контекст 8–16k, запас на систему и сборку. Точка входа для личного ассистента, помощника по коду или обработки документов.

Комфорт: 8 vCPU, 16 ГБ RAM, 160 ГБ NVMe. Здесь можно позволить 7–8B в Q5_K_M или Q6_K ради качества, контекст 32k, два-три слота и соседей — векторную базу, веб-интерфейс. Диск не про запас: пять GGUF набирают 30–40 ГБ незаметно.

Где llama.cpp честно не подходит: сотни пользователей и сотни токенов в секунду. Это уже GPU-сервер под инференс — ядрами тут не добрать по физике памяти.

Локация — Великобритания, Лондон. Инференс идёт локально, и зарубежный адрес нужен не ради чужого API, а ради двух вещей: веса с Hugging Face тянутся напрямую, без прокси и обрывов на многогигабайтных файлах, а RTT от Москвы до Лондона держится в районе 45–60 мс — на стриминге незаметно. Европейской аудитории UK даёт минимальную задержку, а тексты клиентов никуда не уходят.

Про установку честно: llama.cpp в каталоге apps.maatrix.io нет — сервер приезжает чистым, с Ubuntu 24.04 или Debian 12, и собирается по разделам выше за 10–20 минут. Зато в каталоге есть родственные сервисы: они ставятся автоматически при заказе, доступы появляются в кабинете — Ollama, AnythingLLM и Dify для интерфейса и RAG, LiteLLM как шлюз к вашему llama-server. Оплата — картой российского банка, по СБП, криптой или токеном MAAT. Конфигурацию выбирают на странице аренды VPS.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Частые вопросы

Бинарник падает с Illegal instruction (core dumped) без единой строчки лога. Что делать?

GGML_NATIVE=ON по умолчанию даёт -march=native, и после миграции виртуалки набор инструкций перестаёт совпадать. Пересоберите портируемо: cmake -B build -DGGML_NATIVE=OFF -DGGML_BACKEND_DL=ON -DGGML_CPU_ALL_VARIANTS=ON.

Сколько потоков ставить в -t на VPS с 4 vCPU?

Четыре, и никогда не больше числа vCPU: по нашему замеру на 16 vCPU генерация выходит на полку уже на четырёх потоках, а 32 потока обрушили скорость с 7,4 до 0,35 токена в секунду. Промпт можно отдать всем ядрам флагом -tb.

Сервер отвечает 400 про available context size, хотя контекст задан 8192. Почему?

-c — общий бюджет токенов, делящийся между слотами -np: при -c 8192 -np 4 клиенту достаётся 2048. Увеличьте -c кратно числу слотов, уменьшите -np или включите сдвиг флагом --context-shift.

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.