LiteLLM: прокси и роутер LLM для команды. Гайд
Что такое LiteLLM?
LiteLLM - открытая (MIT) Python-библиотека и прокси-сервер (AI Gateway), которые приводят вызовы 100+ LLM-провайдеров к формату OpenAI. SDK подключают в код одного приложения, Proxy поднимают как общий шлюз для команды: с виртуальными ключами, бюджетами, fallback между моделями и централизованными логами.
TL;DR
- -У LiteLLM две роли. Python SDK (litellm.completion и Router) встраивают в одно приложение. Proxy поднимают отдельным сервером на порту 4000, и любой клиент OpenAI-формата подключается к нему сменой base_url.
- -Модели описываются в config.yaml, в секции model_list: model_name - имя для клиента, litellm_params - реальный провайдер и модель. Несколько записей с одним model_name образуют группу с балансировкой, fallbacks задают запасную модель.
- -Virtual keys, бюджеты, команды и Admin UI работают только с Postgres. Без базы прокси принимает лишь master key, а бюджеты не применяются. Redis нужен, когда инстансов или воркеров больше одного.
- -Ядро под MIT, каталог enterprise/ под отдельной лицензией. SSO больше чем на 5 пользователей, JWT-аутентификация, audit logs, бюджеты по моделям на ключ и часть guardrails требуют Enterprise-ключа.
- -Прокси хранит ключи всех провайдеров. В 2026 году у LiteLLM были критичные CVE в аутентификации и management-эндпоинтах и компрометация PyPI-релизов 1.82.7 и 1.82.8, поэтому версию фиксируют, а прокси не выставляют в интернет.
LiteLLM - открытая (MIT) Python-библиотека и прокси-сервер, которые приводят вызовы 100+ LLM-провайдеров к формату OpenAI. Python SDK подключают в код одного приложения. Proxy (в документации AI Gateway) поднимают как общий шлюз для команды: виртуальные ключи на сотрудника, бюджеты, fallback между моделями, логи в одном месте. У репозитория BerriAI/litellm около 62 тысяч звёзд, последний stable-релиз на 2 ноября 2026 года - 1.106.6 от 28 октября.
Первый config.yaml укладывается в два десятка строк. Сложности начинаются, когда прокси отдают команде: виртуальные ключи и бюджеты молча не работают без Postgres, часть функций из документации требует Enterprise-лицензии, а сам прокси хранит ключи всех провайдеров. За 2026 год у LiteLLM вышло больше десятка CVE с оценкой High и Critical, а в марте на PyPI на 40 минут попали два релиза с вредоносным кодом.
Статья о том, как поднять LiteLLM Proxy, описать модели в config.yaml, настроить fallback с локальной модели на облачную, выдать ключи с бюджетами, подключить OpenAI SDK, Claude Code и OpenCode и как эксплуатировать прокси с учётом его истории уязвимостей. Fallback, накладные расходы прокси, авторизация без базы и Anthropic-формат проверены на LiteLLM 1.108.1 (вышла 5 ноября) с Ollama 0.40.14 на Mac с Apple M4 Max. Docker, Postgres, Redis, Admin UI и Enterprise-функции описаны по документации.
Что такое LiteLLM и когда он нужен
Запрос «litellm» объединяет два продукта с разными задачами.
| LiteLLM SDK | LiteLLM Proxy | |
|---|---|---|
| Что это | Python-библиотека | Отдельный HTTP-сервер, порт 4000 |
| Клиенты | Код на Python | Любой язык, OpenAI SDK, агенты, curl |
| Функции | completion() для 100+ провайдеров, Router с ретраями и fallback, стоимость ответа, callbacks | Всё из SDK плюс virtual keys, бюджеты, rate limits, учёт расходов, Admin UI, кэш, guardrails, MCP Gateway |
| Хранилище | Не нужно | Postgres для ключей и бюджетов, Redis для нескольких инстансов |
| Кому | Одному приложению | Команде, нескольким сервисам, агентам |
Выбор по ситуации:
| Ситуация | Что брать |
|---|---|
| Одно Python-приложение, два-три провайдера | SDK |
| Один разработчик, одна модель | Ни то, ни другое: хватит SDK провайдера |
| Несколько сервисов на разных языках ходят к LLM | Proxy |
| Нужны ключи на сотрудника, лимиты и отчёт по расходам | Proxy + Postgres |
| Локальная модель с запасной облачной | SDK Router или Proxy |
| Нет желания администрировать сервер | Облачный агрегатор, например OpenRouter |
Где self-hosted proxy стоит в общей архитектуре провайдеров рядом с адаптерами в коде и managed-шлюзами, разобрано в статье о провайдерах LLM в production.
Чем LiteLLM отличается от OpenRouter и Portkey
| LiteLLM | OpenRouter | Portkey Gateway | |
|---|---|---|---|
| Модель | Self-hosted SDK и Proxy, MIT + каталог enterprise/ | SaaS, единый API и счёт | Open-source шлюз (MIT, ~13 тысяч звёзд) плюс облачный Portkey |
| Ключи провайдеров | Ваши, лежат на вашем сервере | Ключ OpenRouter или свои (BYOK) | Ваши |
| Деньги | Софт бесплатный, платите за инфраструктуру; Enterprise по запросу | Комиссия платформы 5,5% (Standard), 8% (Business); BYOK без комиссии до $25 000 в месяц по прайсу, дальше 5% | Условия на сайте Portkey |
| Данные | Через ваш хост | Через серверы OpenRouter | Через ваш хост (open-source версия) |
Цены OpenRouter взяты со страницы pricing в начале ноября 2026. Подробно облачный вариант разобран в гайде по OpenRouter. Схемы совмещаются: OpenRouter подключается к LiteLLM как ещё один провайдер.
Быстрый старт LiteLLM Proxy
Установка по quick start:
uv tool install 'litellm[proxy]==1.106.6'
# или
pip install 'litellm[proxy]==1.106.6'
С версии 1.84.0 LiteLLM требует Python 3.10 или новее, верхняя граница на PyPI <3.15. uv tool install сам подберёт подходящий интерпретатор. Голый pip на старом Python, по документации, молча поставит последнюю совместимую старую версию. Если системный Python 3.15 или новее, версию интерпретатора для uv задают явно, разовый запуск выглядит так:
uvx --python 3.12 --from 'litellm[proxy]==1.106.6' litellm --config config.yaml --host 127.0.0.1 --port 4000
Версию лучше указывать сразу. Релизы выходят несколько раз в неделю, исправления выпускают сразу для нескольких минорных линий, а версии 1.82.7 и 1.82.8 были вредоносными (подробности в разделе о безопасности).
Минимальный config.yaml с локальной и облачной моделью:
model_list:
- model_name: local-qwen
litellm_params:
model: ollama_chat/qwen3:8b
api_base: http://127.0.0.1:11434
- model_name: cloud-sonnet
litellm_params:
model: anthropic/claude-sonnet-5-5
api_key: os.environ/ANTHROPIC_API_KEY
general_settings:
master_key: os.environ/LITELLM_MASTER_KEY # должен начинаться с sk-
Первый запрос:
curl http://127.0.0.1:4000/v1/chat/completions \
-H "Authorization: Bearer $LITELLM_MASTER_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "local-qwen", "messages": [{"role": "user", "content": "ping"}]}'
Клиент OpenAI SDK меняет только адрес и ключ:
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:4000", api_key="sk-...") # master или virtual key
resp = client.chat.completions.create(
model="cloud-sonnet", # model_name из config.yaml
messages=[{"role": "user", "content": "ping"}],
)
print(resp.choices[0].message.content)
Клиент видит только model_name. Какой провайдер стоит за алиасом, решает конфиг, и модель меняют без правки кода приложений.
SDK: LiteLLM без сервера
Если шлюз не нужен, тот же вызов делается библиотекой:
from litellm import completion
resp = completion(
model="ollama_chat/qwen3:8b",
api_base="http://127.0.0.1:11434",
messages=[{"role": "user", "content": "ping"}],
)
print(resp.choices[0].message.content)
Для балансировки и fallback в SDK есть класс Router с тем же форматом model_list, что и в конфиге прокси.
config.yaml: модели, роутинг, секреты
В config.yaml пять секций:
| Секция | Что в ней |
|---|---|
model_list | Модели: model_name (алиас для клиента), litellm_params (провайдер, модель, api_base, api_key, rpm, tpm), опционально model_info |
router_settings | Стратегия роутинга, ретраи, cooldown, fallbacks |
litellm_settings | Поведение библиотеки: fallbacks, таймауты, кэш, callbacks, глобальный бюджет |
general_settings | Master key, база данных, параметры сервера |
environment_variables | Переменные окружения прямо в конфиге |
Секреты не пишут в файл открытым текстом. Запись os.environ/ИМЯ прокси читает из окружения при старте.
Несколько записей с одинаковым model_name образуют группу, и прокси распределяет запросы между ними:
model_list:
- model_name: fast
litellm_params:
model: anthropic/claude-haiku-5-5
api_key: os.environ/ANTHROPIC_API_KEY
rpm: 500
- model_name: fast
litellm_params:
model: openai/<модель GPT-6>
api_key: os.environ/OPENAI_API_KEY
rpm: 300
router_settings:
routing_strategy: simple-shuffle
Стратегии по документации роутинга:
| Стратегия | Как выбирает |
|---|---|
simple-shuffle | По умолчанию, рекомендована для production; выбирает с учётом rpm/tpm или weight, без них случайно |
least-busy | Деплой с наименьшим числом запросов в работе |
latency-based-routing | Самый быстрый по недавним замерам |
usage-based-routing-v2 | По текущему расходу rpm/tpm через Redis; документация не советует её для production |
cost-based-routing | Самый дешёвый деплой |
Имена моделей в примерах документации LiteLLM меняются вместе с релизами провайдеров и не всегда совпадают с актуальными ID. Реальный идентификатор берут из документации провайдера: у Anthropic на ноябрь 2026 это claude-opus-5-5, claude-sonnet-5-5, claude-haiku-5-5.
Ollama за прокси
LiteLLM поддерживает два префикса для Ollama. ollama_chat/ отправляет запросы в /api/chat, его рекомендует документация. ollama/ идёт в /api/generate. api_base указывает на сервер Ollama, по умолчанию http://localhost:11434.
- model_name: local-qwen
litellm_params:
model: ollama_chat/qwen3:8b
api_base: http://127.0.0.1:11434
keep_alive: 30m
model_info:
supports_function_calling: true
supports_function_calling нужен, когда модель умеет нативные tool calls, а LiteLLM этого не определил: иначе он эмулирует вызовы инструментов через JSON-режим. Какие модели Ollama действительно справляются с инструментами и почему агенту нужен контекст от 64k, разобрано в гайде по Ollama. Выбор между Ollama и LM Studio как локальным бэкендом - в отдельном сравнении.
Fallback, ретраи и таймауты
Fallback - запасная модель, на которую прокси переключает запрос после ошибки основной. Параметры по документации reliability:
| Параметр | Что делает |
|---|---|
fallbacks: [{"a": ["b", "c"]}] | При ошибке группы a пробует b, затем c |
context_window_fallbacks | Переключение при превышении контекста; для проверки до отправки нужен router_settings.enable_pre_call_checks: true |
content_policy_fallbacks | Переключение, когда провайдер отказал по контент-политике |
default_fallbacks | Запасные модели для всех групп без своего правила |
num_retries | Повторы на той же группе до перехода к fallback |
request_timeout | Таймаут запроса, секунды |
allowed_fails, cooldown_time | Сколько ошибок допустимо, прежде чем деплой уйдёт в cooldown, и на сколько |
Документация показывает fallbacks в litellm_settings. Ключ принимается и в router_settings, так он и настроен в проверке ниже. Отключить fallback для одного запроса можно полем "disable_fallbacks": true в теле.
Сценарий «локальная модель упала, отвечает облако»:
model_list:
- model_name: local-qwen
litellm_params:
model: ollama_chat/qwen3:8b
api_base: http://127.0.0.1:11434
- model_name: cloud-deepseek
litellm_params:
model: deepseek/deepseek-flash
api_key: os.environ/DEEPSEEK_API_KEY
router_settings:
num_retries: 0
fallbacks:
- local-qwen: ["cloud-deepseek"]
Проверено: 7 ноября 2026 года, LiteLLM 1.108.1 через uvx --python 3.12, без Docker и Postgres, Ollama 0.40.14 с qwen3:8b, резервная модель DeepSeek deepseek-flash. Падение Ollama имитировала отдельная группа с api_base на закрытый порт, это та же ошибка соединения. Запрос к ней вернул ответ облачной модели, в заголовках ответа: x-litellm-model-group: cloud-deepseek, x-litellm-attempted-fallbacks: 1, x-litellm-attempted-retries: 0, x-litellm-response-duration-ms: 1280.09, x-litellm-overhead-duration-ms: 234.18.
По этим заголовкам видно, что ответ пришёл с запасной модели. Если их не логировать, приложение получит обычный ответ и не узнает, что основная модель лежит.
В той же проверке всплыла деталь про резервную модель. deepseek-flash - рассуждающая модель, и при max_tokens: 200 все 200 токенов ушли в reasoning_tokens, а текст ответа оказался пустым. У запасной модели в цепочке должен быть запас по max_tokens, либо в fallback ставят модель без рассуждений.
Как проектировать роутинг и деградацию на уровне всего стека, а не одного прокси, описано в статье Production LLM Stack.
Накладные расходы прокси
Прокси добавляет ещё один сетевой хоп. Насколько это заметно, проверялось на локальной модели, где сеть до провайдера не маскирует задержку самого LiteLLM.
Проверено: 7 ноября 2026 года, LiteLLM 1.108.1, Ollama 0.40.14, прогретая qwen3:8b, запросы с max_tokens: 1. 15 запросов на каждый путь, первые 3 отброшены, n=12.
| Путь | Медиана, мс | p90, мс |
|---|---|---|
Напрямую в Ollama (/v1/chat/completions) | 19,5 | 19,7 |
| Через LiteLLM Proxy | 26,8 | 26,9 |
Разница около 7 мс на запрос. Заголовок x-litellm-overhead-duration-ms в трёх отдельных запросах показал 7,13, 6,77 и 5,59 мс. Первый запрос после старта прокси медленнее: в fallback-запросе выше overhead 234 мс, и туда входит переключение на запасную модель. Для облачных моделей, где ответ занимает секунды, 7 мс теряются в шуме. Под параллельной нагрузкой замер не делался.
Virtual keys, бюджеты и лимиты
Virtual key - ключ вида sk-..., который прокси выдаёт сотруднику, сервису или агенту вместо ключа провайдера. Для них нужны две вещи (virtual keys): Postgres в DATABASE_URL и master key, начинающийся с sk-.
general_settings:
master_key: os.environ/LITELLM_MASTER_KEY
database_url: os.environ/DATABASE_URL
Ключ с доступом к одной группе моделей, бюджетом $10 на 30 дней и лимитом 60 запросов в минуту:
curl http://127.0.0.1:4000/key/generate \
-H "Authorization: Bearer $LITELLM_MASTER_KEY" \
-H "Content-Type: application/json" \
-d '{"models": ["cloud-sonnet"], "max_budget": 10, "budget_duration": "30d",
"rpm_limit": 60, "metadata": {"owner": "dev-1"}}'
Команда с общим бюджетом создаётся через /team/new, ключ привязывается к ней полем team_id:
curl http://127.0.0.1:4000/team/new \
-H "Authorization: Bearer $LITELLM_MASTER_KEY" \
-H "Content-Type: application/json" \
-d '{"team_alias": "backend", "max_budget": 100, "budget_duration": "30d"}'
Уровни бюджетов по документации:
| Уровень | Как задаётся |
|---|---|
| Ключ | /key/generate: max_budget, budget_duration, rpm_limit, tpm_limit, max_parallel_requests |
| Пользователь | /user/new |
| Команда | /team/new |
| Участник команды | /team/member_add с max_budget_in_team |
| Внешний клиент | /budget/new + /customer/new, поле user в запросе |
| Весь прокси | litellm_settings.max_budget и budget_duration |
budget_duration принимает секунды, минуты, часы и дни: 30s, 30m, 30h, 30d. Ключ сверх бюджета получает ошибку с ExceededTokenBudget или ExceededBudget в тексте.
Нюансы, которые легко пропустить:
- Без базы бюджеты не применяются. Документация показывает пример: в конфиге
max_budget, а прокси продолжает отвечать. - Модели с нулевой стоимостью обходят проверку бюджета целиком. Документация описывает это для моделей с явными
input_cost_per_token: 0иoutput_cost_per_token: 0, чтобы ключ с исчерпанным бюджетом мог уйти на бесплатную модель. В карте цен LiteLLM модели Ollama записаны с нулевой стоимостью: расход по ним не растёт, и денежный бюджет их не ограничит. Локальную модель ограничивают черезrpm_limitиtpm_limit. - У ключа с
team_idличный бюджет владельца не действует, работают командные лимиты.
Проверено: 7 ноября 2026 года, LiteLLM 1.108.1 через uvx, без Postgres и без пакета prisma в окружении. Запрос без заголовка Authorization получил 500 Internal Server Error, неверный ключ sk-wrong - 400, верный master key - 200. В логе ModuleNotFoundError: No module named 'prisma': обработка ошибки авторизации обращается к слою базы данных, которого нет.
Запросы без ключа прокси отклонил, но кодом 500 вместо 401. Мониторинг, который ловит неавторизованные попытки по 401, в такой конфигурации ничего не увидит. Без Postgres прокси годится для локального теста, для команды база обязательна.
budget_fallbacks и бюджеты по моделям
С версии 1.92.0 у ключа есть поле budget_fallbacks: когда бюджет ключа на конкретную модель исчерпан, запрос уходит на модель из цепочки вместо ошибки. Страница budget_fallbacks пометки Enterprise не содержит. Но срабатывает он только при model_max_budget (бюджет ключа по отдельным моделям), а model_max_budget документация бюджетов помечает как Enterprise, и в коде /key/generate без лицензии отказывает с сообщением, что для model_max_budget нужен Enterprise. На практике budget_fallbacks без лицензии не работает.
Docker и production
Быстрый старт с Postgres по Docker quickstart:
curl -sSLO https://github.com/BerriAI/litellm/raw/main/docker/docker-compose.quickstart.yml
printf 'LITELLM_MASTER_KEY=sk-%s\nLITELLM_SALT_KEY=sk-%s\n' \
"$(openssl rand -hex 32)" "$(openssl rand -hex 32)" > .env
docker compose -f docker-compose.quickstart.yml up -d
Compose поднимает шлюз на порту 4000 и Postgres. Перед запуском файл стоит прочитать и заменить тег образа на конкретную версию. Одиночный docker run с конфигом без базы даёт только OpenAI-совместимый API: без ключей, бюджетов и учёта расходов.
Образы и теги по Docker Image Security:
ghcr.io/berriai/litellm- основной образ, есть вариантыlitellm-non_rootиlitellm-spend_logs;- теги
vX.Y.Zнеизменяемы,main-stableиmain-latestпомечены deprecated,latestв production не используют; - с v1.83.0 все образы в GHCR подписаны cosign, подпись проверяют до деплоя:
cosign verify \
--key https://raw.githubusercontent.com/BerriAI/litellm/<commit>/cosign.pub \
ghcr.io/berriai/litellm:v1.106.6
Что нужно для чего (production, deploy):
| Компонент | Когда нужен |
|---|---|
| Postgres | Virtual keys, команды, пользователи, бюджеты, журнал расходов, модели из UI |
| Redis 7+ | Больше одного инстанса или воркера: общие rate limits, состояние роутера, кэш |
LITELLM_SALT_KEY | Шифрует креды провайдеров в базе. Менять после добавления моделей нельзя: сохранённые ключи станут нечитаемыми |
DISABLE_SCHEMA_UPDATE=true | На инстансах прокси, миграции выполняет отдельная job |
/health/readiness, /health/liveliness | Пробы для Kubernetes |
Рекомендации документации по размеру: 1 vCPU и 4 GiB на воркер, в Kubernetes --num_workers 1 на pod и 2+ реплики. Среди прочего там советуют proxy_batch_write_at: 60 (пакетная запись расходов в базу) и LITELLM_LOG=ERROR. Флаг allow_requests_on_db_unavailable пропускает запросы при недоступной базе, документация разрешает его только внутри VPC.
Admin UI и наблюдаемость
Admin UI открывается по адресу <прокси>/ui и требует базу данных. Логин - UI_USERNAME (по умолчанию admin) и UI_PASSWORD. Если пароль не задан, подходит master key, и любой вошедший так получает права админа прокси (Admin UI). Через UI выпускают ключи, добавляют модели без рестарта, заводят команды и смотрят расходы и логи.
Трейсы и метрики отправляют через callbacks:
- Langfuse. Для Langfuse v3 и v4 документация LiteLLM рекомендует пресет
langfuse_otelчерез OpenTelemetry v2 вместо старого SDK-колбэкаlangfuse. Пошаговая настройка Langfuse, включая строку про LiteLLM, есть в гайде по Langfuse, а какие метрики и алерты собирать - в статье об LLM observability. - OpenTelemetry v2.
litellm_settings.callbacks: ["otel"]иLITELLM_OTEL_V2=true, адрес коллектора вOTEL_EXPORTER,OTEL_ENDPOINT,OTEL_HEADERS. На запрос пишется один trace: аутентификация, guardrails, вызов модели с атрибутамиgen_ai.*, запись в базу. Содержимое промптов по умолчанию в трейс не попадает.
Кэш и guardrails
Кэш бывает точным (local, disk, redis, s3, gcs) и семантическим (redis-semantic, valkey-semantic, qdrant-semantic). In-memory кэш живёт внутри воркера: у прокси с четырьмя воркерами четыре отдельных кэша, поэтому начиная со второго воркера нужен Redis. Точный кэш ключуется по хешу всего запроса, и любое изменение диалога даёт промах. Семантический кэш, по словам самой документации, подходит для одиночных промптов и сильно ошибается на агентском трафике.
Guardrails подключаются блоком guardrails: с режимами pre_call, post_call, during_call и logging_only. Встроены litellm_content_filter, Presidio для маскирования PII, интеграции Lakera, Bedrock, Aporia и другие (guardrails). Конкретный guardrail включают на запрос полем "guardrails": ["имя"].
Подключение клиентов
OpenAI SDK
Любой клиент OpenAI-формата: base_url на прокси, в api_key виртуальный ключ, в model - model_name из конфига. Пример в разделе быстрого старта.
Claude Code
По туториалу LiteLLM Claude Code подключается двумя переменными:
export ANTHROPIC_BASE_URL="http://127.0.0.1:4000"
export ANTHROPIC_AUTH_TOKEN="sk-..." # virtual key или master key
claude --model cloud-sonnet # model_name из config.yaml
Master key даёт Claude Code доступ ко всем моделям прокси, виртуальный ключ ограничивает его моделями, разрешёнными этому ключу. Если за прокси стоит Bedrock, туториал советует CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1: Bedrock принимает не все beta-заголовки Claude Code.
Две оговорки из документации Claude Code:
- Anthropic поддерживает шлюзы с совместимым форматом API для моделей Claude, но не аудирует сторонние шлюзы и не поддерживает работу Claude Code с не-Claude моделями через любой шлюз. Технически LiteLLM это позволяет, но качество и совместимость - на вашей стороне.
- Пока задана переменная с кредом шлюза, запросы идут с этим ключом, а не с логином подписки claude.ai. Лимиты подписки к ним не применяются, оплата - по токенам на владельца ключа.
Проверено: 7 ноября 2026 года, LiteLLM 1.108.1. POST /v1/messages с заголовками x-api-key и anthropic-version: 2023-06-01 на группу local-qwen вернул ответ в формате Anthropic: type: message, stop_reason: end_turn, размышления Qwen3 отдельным блоком thinking, ответ блоком text, usage 16 входных и 98 выходных токенов. Сам Claude Code в этой проверке не запускался.
Клиент Anthropic-формата, значит, может разговаривать с локальной моделью через прокси. Справится ли 8B-модель с агентным циклом Claude Code, это уже вопрос модели, и в тестах OpenCode локальные модели этого размера работали нестабильно. Что из Claude Code доступно в России и как ведут себя альтернативные провайдеры, разобрано в отдельной статье.
OpenCode
Отдельной записи про LiteLLM в документации OpenCode нет, работает общий механизм OpenAI-совместимого провайдера (providers). Пример для OpenCode 1, в том же формате, что и подключение Ollama в гайде по OpenCode:
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"litellm": {
"npm": "@ai-sdk/openai-compatible",
"name": "LiteLLM",
"options": {
"baseURL": "http://127.0.0.1:4000/v1",
"apiKey": "{env:LITELLM_API_KEY}"
},
"models": {
"cloud-sonnet": { "name": "Sonnet 5.5 via LiteLLM" }
}
}
}
}
Ключ в models должен совпадать с model_name в конфиге прокси. В OpenCode 2 схема другая: блок providers, поля package и settings.baseURL. Адрес прокси подставляется туда же.
Локальные модели
Ollama подключается к прокси как обычный провайдер (раздел про config.yaml). Клиенты тогда ходят на один адрес и одним ключом и к локальной, и к облачной модели, а fallback переключает их без участия приложения. Обзор вариантов локального запуска собран в гайде по локальным LLM.
Что платное: MIT и Enterprise
Лицензия делит репозиторий на две части. Всё вне каталога enterprise/ распространяется под MIT. Код в enterprise/ можно копировать и менять для разработки и тестов, а в production он работает только при действующей подписке BerriAI на нужное число мест; распространять его нельзя. Enterprise - тот же образ, функции включает лицензионный ключ LITELLM_LICENSE после полного рестарта.
| Бесплатно (MIT) | Нужен Enterprise-ключ |
|---|---|
| Python SDK, Router, fallback | SSO и SCIM (SSO бесплатен до 5 пользователей) |
| Virtual keys, бюджеты и rate limits на ключ, пользователя, команду | JWT-аутентификация, назначение админов команд |
| Учёт расходов, Admin UI | Audit logs с retention, RBAC (организации, команды, роли) |
| Балансировка и роутинг | IP allowlist, ротация ключей, secret managers |
| Guardrails-фреймворк, кастомные guardrails, Presidio | Guardrail-колбэки llmguard_moderations, llamaguard_moderations, hide_secrets, openai_moderations, google_text_moderation, lakera_prompt_injection, aporia_prompt_injection |
| MCP gateway | Теговые бюджеты, бюджеты по моделям на ключ (model_max_budget), временное повышение бюджета |
| Кэш, логирование в Langfuse и OTel | Soft-budget алерты на email, отчёты по расходам, логи по командам, выгрузка в GCS и Azure Blob, guardrails на ключ и команду, лимиты размера запроса и ответа |
Список взят со страницы Enterprise. Цена зависит от объёма использования и обсуждается с продажами, есть бесплатный 30-дневный trial, покупка через AWS и Azure Marketplace или по счёту.
Безопасность LiteLLM: инциденты и CVE 2026
Прокси хранит master key, ключи всех провайдеров и креды в базе. Взлом прокси означает утечку всех этих ключей сразу. Поэтому история уязвимостей за 2026 год важна для любого self-hosted развёртывания.
Компрометация PyPI, 24 марта 2026. Версии 1.82.7 и 1.82.8 содержали вредоносный код, собиравший креды, в 1.82.8 был ещё файл litellm_init.pth, который Python выполняет при старте интерпретатора. По отчёту команды пакеты были доступны с 10:39 UTC около 40 минут, затронутыми считаются установки через pip с 10:39 до 16:00 UTC. Официальный Docker-образ прокси не пострадал. Источником команда называет зависимость Trivy в CI, к расследованию подключили Mandiant. Чистые версии - 1.82.6 и раньше, 1.83.0 и новее.
Основные CVE и advisories по NVD и GitHub Security Advisories, оценка CVSS от GitHub как CNA:
| ID | Опубликовано | CVSS | Суть | Исправлено в |
|---|---|---|---|---|
| CVE-2026-35030 | 06.04 | 9.4 | Обход аутентификации при включённом JWT-auth (коллизия ключа кэша OIDC userinfo), по умолчанию выключено | 1.83.0 |
| CVE-2026-35029 | 06.04 | 8.7 | /config/update не проверял роль admin | 1.83.0 |
| CVE-2026-42208 | 08.05 | 9.3 | SQL-инъекция в проверке API-ключа: запрос без аутентификации на любой LLM-роут читает и меняет базу прокси (1.81.16-1.83.6) | 1.83.7 |
| CVE-2026-42203 | 08.05 | 8.6 | SSTI в POST /prompts/test: выполнение кода с любым валидным ключом | 1.83.7 |
| CVE-2026-42271 | 08.05 | 8.7 | Выполнение команд через тестовые MCP-эндпоинты с stdio-транспортом | 1.83.7 |
| CVE-2026-49468 | 22.06 | 9.5 | Обход аутентификации через заголовок Host: доступ к management-роутам без ключа | 1.84.0 |
| CVE-2026-59822 | 08.07 | 8.8 | Обход аутентификации в MCP Streamable HTTP через OAuth2 passthrough | 1.84.0 |
| CVE-2026-89032 | 25.09 | 8.7 | Семантический кэш отдавал ответы другим тенантам (/v1/responses, /bedrock/*) | 1.101.0-rc.1 |
| CVE-2026-93355 | 28.09 | 7.6 | JWT-auth: вход под любым пользователем по email без проверки email_verified | В записи NVD не указано |
| CVE-2026-114612 | 22.10 | 9.9 | Общий криптоконтекст для секретов и сессий: internal_user подделывает admin-токен и выполняет команды через MCP stdio; с 1.91.0 в конфигурации по умолчанию | 1.100.4, 1.101.3, 1.102.2, 1.103.1 |
| GHSA-w4c7-34wj-hqm8 | 27.10 | 10.0 | Только Enterprise: запрос без аутентификации заставляет прокси прочитать локальный файл (например, /proc/self/environ с master key и ключами провайдеров) и отправить его на адрес атакующего | 1.103.10, 1.104.8, 1.105.6, 1.106.5 |
Даты - публикация в NVD, у GitHub advisory обычно раньше на несколько дней или недель. Кроме таблицы, в 2026 году были SSRF и утечки кредов провайдера через api_base и user_config в теле запроса (CVE-2026-84377, CVE-2026-59823, Moderate), выполнение кода через тест кастомных guardrails (CVE-2026-40217) и чтение локальных файлов через vertex_ai_credentials (GHSA-g5ff-637f-6q2m).
Почти все серьёзные дыры сидят в аутентификации, management-, test- и MCP-эндпоинтах, JWT и SSO, а не в маршрутизации запросов. Последний critical был в коде Enterprise: лицензия расширяет поверхность атаки.
Чек-лист для self-hosted:
- Фиксировать версию:
litellm[proxy]==X.Y.Zили тег образаvX.Y.Z, лучше digest, но неlatest. - Проверять подпись образа cosign (подписаны с v1.83.0).
- Для pip и uv: убедиться, что не стоят 1.82.7 и 1.82.8 (
pip show litellm), и поискатьlitellm_init.pthв site-packages. - Не выставлять прокси в интернет. Доступ через VPN, mTLS, аутентифицирующий ingress или IP allowlist. Отдельно закрыть
/ui,/key/*,/team/*,/config/*и MCP-роуты. - Ограничить исходящий трафик прокси адресами провайдеров. В GHSA-w4c7 именно это обрывает эксфильтрацию даже при уязвимой версии.
- Не включать MCP gateway, JWT и SSO, если они не нужны.
- Задать отдельный
LITELLM_SALT_KEY, master key по возможности держать в secret manager, а не в переменных окружения процесса. - Подписаться на advisories репозитория и обновляться по ним: исправления выходят сразу в нескольких поддерживаемых линиях.
Риски MCP-эндпоинтов не уникальны для LiteLLM, общая модель угроз описана в статье о MCP-серверах.
Ограничения и подводные камни LiteLLM
Postgres обязателен для команды
Без базы нет ключей, бюджетов, Admin UI и журнала расходов, а лимиты из конфига молча игнорируются. В проверке без базы запрос без ключа получил 500 вместо 401. Для команды Postgres закладывают с первого дня.
Лишний хоп и лишняя точка отказа
Около 7 мс на запрос на локальной машине мало, но прокси становится единой точкой отказа для всех клиентов. В production нужны 2+ реплики, Redis и health-пробы, то есть ещё одна система, которую надо администрировать.
Версия каждую неделю
Релизы выходят несколько раз в неделю: 27 октября одно и то же исправление вышло в четырёх линиях сразу (1.103.10, 1.104.8, 1.105.6, 1.106.5). Поведение между версиями меняется: проверки этой статьи сделаны на 1.108.1, вышедшей через три дня после даты статьи. Перед обновлением в production читают changelog и advisories.
Плейсхолдеры в документации
Примеры в документации LiteLLM используют имена моделей, которые не всегда совпадают с актуальными ID провайдеров. Копировать их в конфиг без сверки с документацией провайдера не стоит.
Семантический кэш и агенты
Семантический кэш отдаёт ближайший по смыслу ответ. Для агентского трафика с вызовами инструментов это источник ошибок, а в CVE-2026-89032 он ещё и отдавал ответы между тенантами.
Когда LiteLLM не нужен
Одна модель и один сервис обходятся SDK провайдера. Одному разработчику с несколькими провайдерами хватит LiteLLM SDK без сервера. Если администрировать шлюз некому, облачный агрегатор дешевле по времени, хотя и дороже по комиссии.
С чего начать
- Поставьте зафиксированную версию:
uv tool install 'litellm[proxy]==1.106.6'и проверьтеlitellm --version. - Напишите
config.yamlс одной локальной и одной облачной моделью, master key из переменной окружения, запустите прокси на127.0.0.1. - Проверьте запрос через curl и OpenAI SDK, затем настройте
fallbacksи посмотрите заголовкиx-litellm-attempted-fallbacksпри недоступной основной модели. - Для команды поднимите Postgres (compose-quickstart), задайте
LITELLM_SALT_KEY, выпустите ключи сmax_budgetиrpm_limit. - Подключите клиентов: OpenAI SDK, Claude Code через
ANTHROPIC_BASE_URL, OpenCode через OpenAI-совместимый провайдер. - Пройдите чек-лист безопасности: закрытая сеть, ограниченный egress, подпись образа, подписка на advisories.