Перейти к содержанию
modelium.
Начать с задачи
←

llama.cpp server: API-ключ, проверка доступа и границы защиты

У llama-server можно включить проверку ключа через --api-key-file и отправлять его в заголовке Authorization: Bearer. На защищённом API-запросе без ключа ожидается HTTP 401, с верным ключом — доступ; однако /health и файлы веб-интерфейса остаются публичными. Ключ не шифрует трафик и не заменяет закрытый сетевой периметр.

Версия документации и кода: коммит llama.cpp a7fb71f от 4 октября 2026 года, проверено 5 октября 2026 года. Это инструкция для вашего тестового стенда, а не отчёт об испытании Modelium. Не открывайте пробный сервер с данными на публичном IP. s1 s2 s5

Зачем llama-server нужен ключ, если модель работает локально?

Один процесс llama-server предоставляет HTTP API для локальной GGUF-модели. Без настроенных ключей middleware пропускает запросы; по умолчанию сервер привязывается к 127.0.0.1:8080, но при смене адреса привязки круг возможных клиентов меняется. Ключ помогает отсечь запросы к защищённым endpoint, но не делает открытый сервер безопасным для интернета. s1 s2 s3 s5

Сценарий этой страницы — разработчик с собственной совместимой GGUF-моделью и тестовым локальным сервером. Сначала проверьте, что модель загружается по обычному гайду llama.cpp. Файл весов, его размер и демонстрационный путь -m не являются гарантией доступной RAM/VRAM или качества на вашем устройстве; для выбранной модели отдельно проверьте формат, лицензию, ресурсы и ответ. Проверяемая цепочка: задача клиента → конкретная GGUF → собственное железо → llama-server на localhost → ответ/отказ по ключу → анализ сетевой границы. s1 s5

Это не руководство по безопасной публикации сервера в недоверенной сети: SECURITY.md llama.cpp прямо предостерегает от использования функциональности llama-server в таком окружении. Предположение «добавлю ключ, потом открою порт наружу» нарушает границу задачи. Для удалённого доступа нужен отдельно спроектированный защищённый периметр; даже при наличии обратного прокси и TLS это не отменяет предупреждение проекта и вашей оценки угроз. s1 s5

Как включить проверку ключа без секретов в командной строке?

На собственной машине подготовьте текстовый файл /path/to/keys.txt: одна длинная случайная строка на строку, без пробелов и без комментария с секретом. Защитите доступ к файлу правами ОС и не помещайте его в репозиторий или резервные копии без шифрования. Параметр --api-key-file читает непустые строки, кроме начинающихся с #; пустой файл — плохая конфигурация, потому что при отсутствии загруженных ключей проверка вообще пропускается. Для устойчивой проверки убедитесь, что файл реально содержит ключ и что сервер его прочитал. s2 s3

После установки llama.cpp и выбора вашего совместимого GGUF, в локальном тесте запустите llama-server -m /path/to/model.gguf --host 127.0.0.1 --port 8080 --api-key-file /path/to/keys.txt --no-ui. Здесь оба пути — заменяемые примеры, не существующие файлы Modelium. README подтверждает флаги --host, --port, --api-key-file и --no-ui; наличие именно вашего бинарника, поддерживаемого backend и доступной памяти проверяется до теста. Не включайте экспериментальные --tools, --agent и --ui-mcp-proxy для простого API: они расширяют возможности и угрозы. s1 s3

--api-key KEY и переменная LLAMA_API_KEY также поддерживаются, но для долгоживущего процесса файл помогает не прописывать секрет прямо в аргументы запуска. Это снижение риска случайного попадания в историю команд, а не гарантия тайны: доступ к файлу и конфигурации сервиса всё равно надо контролировать. Если ключей несколько, README допускает список в параметре или строки в файле; не объявляйте это системой прав пользователей — middleware лишь сверяет полученное значение со списком. s1 s2 s3

Как проверить 401 и успешный запрос?

Дождитесь загрузки модели: GET /health может отвечать 503 в фазе загрузки и 200 с status: ok при готовности. Этот endpoint публичен даже при заданном ключе — используйте его только для readiness, не для проверки закрытости API. Пробный запрос curl -i http://127.0.0.1:8080/health не должен содержать секрет. s1 s2 s4

На той же машине выполните curl -i http://127.0.0.1:8080/v1/models без заголовка авторизации: после готовности сервера ожидается HTTP 401 и authentication_error. Затем отправьте запрос на тот же адрес с Authorization: Bearer <ВАШ_ТЕСТОВЫЙ_КЛЮЧ>; защищённый /v1/models должен вернуть 200 со списком модели. Не записывайте настоящий ключ в историю shell, лог команд, скриншот или статью; подстановка через защищённое хранилище нужна на вашей машине. Это ожидаемые результаты согласно коду и тестам проекта, не протокол прогона Modelium. s1 s2 s4

Для полноты проверьте неверный ключ: он тоже должен дать 401, а правильный ключ в X-Api-Key также поддерживается middleware. OPTIONS preflight может проходить без ключа, чтобы браузер сделал CORS-проверку; это не означает, что последующий GET/POST освобождён от авторизации. Сохраните статусы и заголовки ответов без значения ключа, не логируя содержимое чувствительных запросов. s2 s4

Если нужен именно результат модели, после успешного /v1/models отправьте один POST /v1/chat/completions со своим model и коротким тестовым сообщением, а затем проверьте непустой ответ и соответствие ID выбранной модели. README описывает этот endpoint, но предупреждает, что совместимость OpenAI API не абсолютна и зависит от chat template конкретной модели. Ответ на /v1/models проверяет доступ и метаданные, а не качество инференса. Modelium этот вызов и запуск модели не выполнял. s1 s4

Что остаётся доступным и почему CORS не заменяет ключ?

Список исключений в server-http.cpp включает /health, /v1/health и встроенные ресурсы UI: они доступны без ключа. Поэтому по одному ключу нельзя обещать, что все URL сервера скрыты. --no-ui отключает отображение интерфейса, но не меняет факт публичного readiness; после запуска проверьте фактические ответы своей сборки. В официальных unit-тестах проверены и публичный /health, и UI-assets, и 401 на защищённом пути. s1 s2 s4

CORS определяет, какие браузерные origins могут читать ответы, а не кто может отправить HTTP-запрос из curl или другого сервиса. README фиксирует широкий CORS по умолчанию и рекомендует настройку для локальной сети; код отражает Origin при включённых credentials и разрешении *. Даже узкий --cors-origins localhost не является firewall, а запрет CORS не заменяет проверку Bearer. Для простого локального API не открывайте 0.0.0.0; если приложение требует отдельного сетевого сервиса, рассмотрите другой изолированный контур и отдельную модель угроз. s1 s2 s4 s5 s6

API-ключ передаётся заголовком, а не шифрует HTTP. --ssl-key-file и --ssl-cert-file существуют в документации, но сборка с SSL требует отдельного LLAMA_OPENSSL=ON; обратный прокси и TLS следует проектировать отдельно, не выдавая их наличие за результат установки одного флага. Рекомендации разработчиков для публичного сервера с proxy и ключом в README сосуществуют с более жёстким предупреждением SECURITY.md о недоверенных сетях; для этой страницы выбираем более осторожный локальный сценарий, а не обещаем безопасный публичный endpoint. s1 s3 s5

Что делать при 200 без ключа, 401 с ключом или утечке?

  • /v1/models отвечает 200 без ключа: проверьте, не подменился ли адрес/порт, не пуст ли файл ключей и прочитан ли он. Код при пустом api_keys отключает проверку; открытый /health для этого теста не годится. Остановите процесс и устраните конфигурационную ошибку до подключения клиентов. s1 s2 s3
  • 401 с корректным на вид ключом: сравните значение без вывода секрета в общие логи, проверьте заголовок Authorization: Bearer, строку файла ключей и то, что после изменения файла сервер перезапущен. Код загружает файл при разборе аргументов и сравнивает полученное значение, так что само изменение файла не подтверждает ротацию процесса. s2 s3
  • Готовность 200, но модель не отвечает: readiness и успешный инференс — разные проверки; сверьте модель, шаблон диалога, статус API и ресурсы машины. Код может отвечать 503 до готовности, а документация отдельно описывает /v1/chat/completions. s1 s2
  • Ключ оказался в журнале или на чужой машине: прекратите доступ в пределах вашего контура, замените значение, перезапустите сервер, проверьте логи и сетевые правила. Несанкционированные запросы нельзя исключить задним числом только по успешной смене ключа. s2 s3 s5

После проверки остановите тестовый процесс, удалите ненужный тестовый ключ из рабочего окружения и сохраните только обезличенные статусы HTTP. Основной следующий шаг — подготовить собственный локальный llama-server с совместимой моделью, повторить 401/200-тест на 127.0.0.1 и отдельно проверить сетевую доступность на своём стенде. Встроенного подтверждения безопасности сети одним ключом нет; необходимость изолированного контура разберите в гайде проверки офлайн-режима. s1 s2 s5

Источники

  1. llama.cpp: llama-server README — flags, CORS, API and health — revision a7fb71fab83b474a0892b9a05aaa3a8ddca2729b. Получено 05.10.2026.
  2. llama.cpp: server-http.cpp — auth middleware and public endpoint list — revision a7fb71fab83b474a0892b9a05aaa3a8ddca2729b. Получено 05.10.2026.
  3. llama.cpp: common/arg.cpp — server flags and key-file parser — revision a7fb71fab83b474a0892b9a05aaa3a8ddca2729b. Получено 05.10.2026.
  4. llama.cpp: test_security.py — public routes, 401, valid key and CORS — revision a7fb71fab83b474a0892b9a05aaa3a8ddca2729b. Получено 05.10.2026.
  5. llama.cpp: SECURITY.md — untrusted networks and model isolation — revision a7fb71fab83b474a0892b9a05aaa3a8ddca2729b. Получено 05.10.2026.
  6. llama.cpp: server.cpp — routes and security warning — revision a7fb71fab83b474a0892b9a05aaa3a8ddca2729b. Получено 05.10.2026.