bolt Valebyte VPS от $4/мес — NVMe, запуск за 60 секунд.

Получить VPS arrow_forward
eco Начальный Туториал

vLLM на GPU-сервере: OpenAI-совместимый API для своей LLM

calendar_month Sep 17, 2026 schedule 19 мин. чтения visibility 37 просмотров
vLLM на GPU-сервере: OpenAI-совместимый API для своей LLM
info

Нужен сервер для этого гайда? Мы предлагаем выделенные серверы и VPS в 50+ странах с мгновенной настройкой.

Нужен сервер для этого гайда?

Разверните VPS или выделенный сервер за минуты.

vLLM на GPU-сервере: OpenAI-совместимый API для своей LLM

TL;DR

В этом гайде вы развернёте vLLM на GPU-сервере с Docker, запустите локальную языковую модель и получите защищённый OpenAI-совместимый API на адресе /v1/chat/completions. Такой сервер можно подключить к собственному приложению, LangChain, OpenWebUI, ботам и внутренним сервисам без отправки промптов стороннему AI-провайдеру.

  • vLLM обслуживает LLM быстрее обычного Hugging Face inference благодаря PagedAttention и continuous batching.
  • Для первого запуска подойдёт модель уровня Qwen3-8B или Llama 3.1 8B на GPU с 16–24 ГБ VRAM.
  • API vLLM совместим с форматом OpenAI: /v1/models, /v1/chat/completions, /v1/completions.
  • Модель, API-ключ и конфигурация запускаются через Docker Compose и файл .env.
  • Внешний доступ закрывается TLS-прокси Caddy, а порт vLLM остаётся доступным только локально.
  • Для продакшена нужно сохранять конфигурацию, список моделей, API-ключи и при необходимости кеш Hugging Face.

Что мы настраиваем и зачем

Схема: Что мы настраиваем и зачем
Схема: Что мы настраиваем и зачем

vLLM — это сервер инференса больших языковых моделей. Он загружает модель в память GPU, принимает HTTP-запросы и возвращает сгенерированный текст. Главная практическая особенность vLLM — совместимость с API OpenAI. Приложение, которое умеет работать с OpenAI SDK, обычно можно переключить на собственный сервер заменой base_url и API-ключа.

В этом сценарии GPU-сервер работает как частный endpoint для одной или нескольких LLM. Например, вы можете использовать Qwen3-8B для внутреннего чат-бота, Llama 3.1 8B для суммаризации документов, DeepSeek-R1-Distill для рассуждений или embedding-модель для поиска по базе знаний. Сам vLLM не является веб-чатом: это API-слой. Интерфейс для сотрудников или клиентов подключается отдельно.

Что получится в итоге

  • Ubuntu 24.04 LTS-сервер с установленным NVIDIA-драйвером, Docker и NVIDIA Container Toolkit.
  • Контейнер vllm/vllm-openai, использующий GPU через Docker.
  • Модель Qwen/Qwen3-8B, автоматически загружаемая в локальный кеш Hugging Face.
  • OpenAI-совместимый API: https://llm.example.com/v1/chat/completions.
  • Авторизация Bearer-токеном, который проверяет сам vLLM.
  • TLS-сертификат Let’s Encrypt, автоматически управляемый Caddy.
  • Понятная схема обновления, резервного копирования и диагностики ошибок GPU.

Почему vLLM, а не обычный запуск Transformers

Запуск модели через Python-библиотеку Transformers удобен для эксперимента, но плохо подходит для постоянного API. При нескольких одновременных запросах Python-приложение часто простаивает или обрабатывает запросы последовательно. vLLM использует непрерывную пакетную обработку запросов: GPU генерирует токены для разных пользователей в одном вычислительном цикле.

Также vLLM экономнее управляет KV-кешем — памятью, в которой модель хранит контекст диалога. Для чатов с длинной историей именно KV-кеш часто становится ограничением раньше, чем вес самой модели. PagedAttention разбивает этот кеш на блоки и снижает фрагментацию VRAM.

Self-hosted или managed API

Критерий Managed API Свой vLLM на GPU-сервере
Старт Нужен ключ и биллинг Нужны сервер, GPU и настройка
Данные промптов Передаются внешнему поставщику Остаются в вашей инфраструктуре
Выбор модели Ограничен каталогом сервиса Можно выбирать совместимые открытые модели
Цена при постоянной нагрузке Зависит от числа токенов Фиксирована стоимость GPU-сервера
Обслуживание Выполняет поставщик Вы отвечаете за безопасность, обновления и мониторинг

Self-hosted вариант оправдан, если данные нельзя отправлять во внешнее API, нагрузка предсказуема, требуется конкретная open-weight модель или нужен полный контроль над лимитами, логированием и версиями. Если трафик редкий и непредсказуемый, managed API обычно экономичнее: GPU не должен простаивать круглосуточно.

Важно: не каждая модель на Hugging Face имеет лицензию для коммерческого использования. Перед интеграцией в продукт проверьте лицензию модели, требования к указанию авторства и условия доступа к gated-репозиториям.

Какой VPS-конфиг нужен под эту задачу

Схема: Какой VPS-конфиг нужен под эту задачу
Схема: Какой VPS-конфиг нужен под эту задачу

Для vLLM важнее всего не число CPU-ядер, а объём и тип GPU-памяти. В VRAM должны одновременно разместиться веса модели, KV-кеш контекста, временные тензоры и запас на фрагментацию. Оперативная память сервера используется для загрузки файлов модели, Docker, кеша и операционной системы.

Оценка памяти для модели

Грубая формула для весов: число параметров умножается на размер одного параметра. Модель на 8 миллиардов параметров в FP16 занимает около 16 ГБ только под веса. В 4-битном формате AWQ или GPTQ она занимает примерно 5–7 ГБ, но точное значение зависит от архитектуры, quantization-конфига и версии движка.

Задача GPU и VRAM RAM Диск NVMe Практический результат
Тесты, 7B–8B в 4-bit NVIDIA L4 24 ГБ или RTX 4090 24 ГБ 32 ГБ 100 ГБ Небольшой чат и разработка
8B FP16, несколько пользователей 24–48 ГБ VRAM 64 ГБ 200 ГБ Качественный общий API
32B в 4-bit 48 ГБ VRAM 64–128 ГБ 300 ГБ Серьёзные задачи и длинный контекст
70B в 4-bit 80 ГБ VRAM или несколько GPU 128 ГБ 500 ГБ Высокое качество при дорогом инференсе

Для этого руководства оптимален сервер с одной GPU на 24 ГБ VRAM, 8 vCPU, 32–64 ГБ RAM, 200 ГБ NVMe и сетью от 1 Гбит/с. Такой конфиг даёт запас для Qwen3-8B, Llama 3.1 8B и сопоставимых моделей. Как один из нейтральных вариантов можно взять VPS с указанными характеристиками, если в описании явно гарантированы выделенная NVIDIA GPU, объём VRAM и доступ к ней из виртуальной машины.

Почему нельзя ориентироваться только на название GPU

Уточняйте объём VRAM, а не только модель ускорителя. Например, датацентровые GPU могут выпускаться в конфигурациях с разной памятью. Уточните, что GPU выделена вам целиком, а не разделяется между клиентами без гарантированной доли. Также убедитесь, что провайдер разрешает Docker и предоставляет драйвер NVIDIA либо совместимый GPU passthrough.

Когда нужен dedicated, а не GPU VPS

Выделенный сервер нужен при нескольких GPU, модели от 70B параметров, высокой постоянной нагрузке, строгих требованиях к изоляции или необходимости полного контроля над PCIe-топологией. Он также полезен, если вы хотите запускать отдельные модели на нескольких GPU или обслуживать десятки параллельных пользователей.

GPU VPS рационален для одной GPU и умеренной нагрузки: он проще в запуске, дешевле на старте и легче масштабируется заменой конфигурации. Для одиночной 8B-модели dedicated обычно избыточен.

Выбор локации

Локация влияет на задержку API. Если пользователи и приложение находятся в Европе, сервер в европейском дата-центре обычно даст задержку сети 10–60 мс вместо сотен миллисекунд. Для LLM это не единственный фактор: генерация каждого токена тоже занимает время. Но удалённый сервер заметно ухудшает ощущение отзывчивости в потоковом чате.

Если API обрабатывает персональные данные, учитывайте требования юрисдикции и хранения данных. Не отправляйте логи запросов в регионы, где их хранение противоречит вашим договорам или правилам обработки данных.

Подготовка сервера

Схема: Подготовка сервера
Схема: Подготовка сервера

Ниже используется Ubuntu 24.04 LTS. На момент подготовки этого руководства это практичный базовый выбор для GPU-нагрузок: система имеет долгий срок поддержки, совместима с актуальными драйверами NVIDIA, Docker Engine 29 и NVIDIA Container Toolkit. Выполняйте начальную настройку под пользователем с правами sudo, а не под root.

Создайте пользователя и настройте SSH-ключ

Подключитесь к серверу первоначальным способом, который предоставил хостинг. На своём компьютере создайте ключ, если его ещё нет, затем добавьте публичную часть на сервер. Не закрывайте текущую SSH-сессию до проверки входа под новым пользователем.

# На сервере: создаём отдельного администратора и добавляем его в sudo
sudo adduser deploy
sudo usermod -aG sudo deploy

# На локальном компьютере: копируем публичный SSH-ключ на сервер
ssh-copy-id deploy@SERVER_IP

Проверьте вход в новом окне терминала:

# На локальном компьютере: проверяем вход по ключу
ssh deploy@SERVER_IP

Обновите систему и установите базовые инструменты

# Обновляем пакеты Ubuntu и устанавливаем диагностические утилиты
sudo apt update && sudo apt full-upgrade -y
sudo apt install -y ca-certificates curl gnupg git jq htop tmux \
  fail2ban ufw unzip ncdu

После обновления ядра или NVIDIA-драйвера перезагрузите сервер. На GPU-узлах перезагрузка особенно важна: загруженный драйвер должен соответствовать установленным библиотекам.

# Перезагружаем сервер, если обновлялось ядро или драйвер
sudo reboot

Закройте лишние сетевые порты

vLLM по умолчанию слушает HTTP-порт 8000. Не публикуйте его напрямую в интернет: API-ключ не заменяет сетевой периметр, а незашифрованный HTTP передаёт запросы и токен открытым текстом. Снаружи будут доступны только SSH, HTTP для выпуска сертификата и HTTPS.

# Разрешаем SSH, HTTP и HTTPS; все остальные входящие соединения запрещаем
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

Настройте Fail2ban и отключите вход по паролю

Fail2ban блокирует источники с серией неудачных попыток SSH-входа. После проверки SSH-ключа отключите парольную авторизацию. Если вы потеряете приватный ключ и не имеете консольного доступа через панель сервера, восстановление потребует вмешательства провайдера.

# Включаем защиту SSH и создаём локальную конфигурацию Fail2ban
sudo systemctl enable --now fail2ban
sudo tee /etc/fail2ban/jail.d/sshd.local > /dev/null <<'EOF'
[sshd]
enabled = true
maxretry = 5
findtime = 10m
bantime = 1h
EOF
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
# Отключаем SSH-пароли и root-вход только после проверки ключа
sudo tee /etc/ssh/sshd_config.d/99-hardening.conf > /dev/null <<'EOF'
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
PubkeyAuthentication yes
EOF
sudo sshd -t && sudo systemctl reload ssh

Проверьте также правила firewall в панели самого сервера, если они существуют. Внешний firewall должен совпадать с UFW: разрешите 22, 80 и 443, а 8000 не открывайте.

Установка ПО — пошагово

Схема: Установка ПО — пошагово
Схема: Установка ПО — пошагово

Перед установкой контейнера убедитесь, что GPU видна операционной системе. Многие GPU VPS поставляются с готовым драйвером NVIDIA. Если команда nvidia-smi не работает, сначала установите рекомендованный драйвер из репозитория Ubuntu или обратитесь к документации образа сервера.

Проверьте NVIDIA-драйвер

# Показываем модель GPU, версию драйвера и доступную VRAM
nvidia-smi

Вы должны увидеть таблицу с GPU и версией драйвера. Для современных образов vLLM с CUDA 12 обычно требуется драйвер NVIDIA серии 535 или новее; на практике предпочтительны ветки 550, 570 или новее, совместимые с вашей ОС. Не устанавливайте CUDA Toolkit на хост без необходимости: контейнер vLLM уже содержит нужные пользовательские CUDA-библиотеки.

Установите Docker Engine

Устанавливайте Docker из официального репозитория Docker, а не старый пакет docker.io из базового репозитория Ubuntu. Это даст актуальный Docker Engine 29.x и плагин Docker Compose.

# Добавляем официальный GPG-ключ и репозиторий Docker для Ubuntu
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin
# Разрешаем пользователю deploy запускать Docker без sudo и проверяем версию
sudo usermod -aG docker deploy
newgrp docker
docker version
docker compose version

Установите NVIDIA Container Toolkit

NVIDIA Container Toolkit передаёт GPU из хоста в Docker-контейнер. Репозиторий и ключ ниже используются для актуальных пакетов toolkit. После установки перезапускается Docker daemon, поэтому кратковременно остановятся уже работающие контейнеры.

# Подключаем официальный репозиторий NVIDIA Container Toolkit
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg

curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
  sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list

sudo apt update
sudo apt install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

Проверьте GPU внутри контейнера

# Запускаем официальный CUDA-контейнер и проверяем, что GPU передаётся в Docker
docker run --rm --gpus all nvidia/cuda:12.8.0-base-ubuntu24.04 nvidia-smi

Если вывод внутри контейнера показывает вашу GPU, базовая инфраструктура готова. Ошибка could not select device driver "" with capabilities: [[gpu]] обычно означает, что toolkit не установлен или Docker не был перезапущен.

Подготовьте каталог приложения

Разделяйте данные приложения и данные контейнера. В каталоге проекта будут Compose-файл, Caddyfile, переменные окружения и скрипты. Кеш Hugging Face вынесен в отдельный volume, чтобы не скачивать десятки гигабайт модели после пересоздания контейнера.

# Создаём структуру проекта vLLM и каталоги для постоянных данных
sudo mkdir -p /opt/vllm/{caddy,data/hf-cache,backups,scripts}
sudo chown -R deploy:deploy /opt/vllm
cd /opt/vllm

Получите токен Hugging Face при необходимости

Для публичной Qwen3-8B токен обычно не нужен. Но он потребуется для gated-моделей, например некоторых вариантов Llama. Создайте access token с минимальным правом Read в личном кабинете Hugging Face и сохраните его только в .env. Не вставляйте такой токен в Git, Docker image или Compose-файл.

Конфигурация

Схема: Конфигурация
Схема: Конфигурация

В примере используется vLLM OpenAI server и модель Qwen/Qwen3-8B. Образ закреплён на конкретном теге v0.10.2, чтобы обновление не меняло поведение незаметно. Перед новым развёртыванием проверьте актуальный стабильный тег в официальном реестре vLLM и протестируйте его в отдельном окружении; не используйте latest в продакшене.

Создайте файл переменных окружения

Сгенерируйте длинный случайный API-ключ. Пользовательские приложения будут передавать его в заголовке Authorization: Bearer .... Значение VLLM_MAX_MODEL_LEN ограничивает контекст: 8192 токена — безопасная начальная настройка для GPU с 24 ГБ VRAM.

# Генерируем секреты и создаём .env с правами только для владельца
cd /opt/vllm
umask 077
cat > .env <<EOF
DOMAIN=llm.example.com
VLLM_API_KEY=$(openssl rand -hex 32)
HF_TOKEN=
MODEL_NAME=Qwen/Qwen3-8B
SERVED_MODEL_NAME=qwen3-8b
VLLM_MAX_MODEL_LEN=8192
GPU_MEMORY_UTILIZATION=0.88
EOF
chmod 600 .env

# Просматриваем ключ только локально; не копируйте его в публичные чаты и репозитории
grep VLLM_API_KEY .env

Замените llm.example.com на свой домен. До запуска Caddy создайте DNS-запись типа A, указывающую на публичный IPv4-адрес сервера. Если используется IPv6, добавьте AAAA-запись и убедитесь, что порт 443 доступен по IPv6.

Создайте Docker Compose-конфигурацию

Порт 8000 привязан к 127.0.0.1, поэтому его нельзя открыть напрямую из интернета. Caddy и vLLM находятся в одной Docker-сети. Переменная HF_TOKEN передаётся контейнеру только если вы указали её в .env.

services:
  vllm:
    image: vllm/vllm-openai:v0.10.2
    container_name: vllm-api
    restart: unless-stopped
    env_file:
      - .env
    environment:
      HF_HOME: /root/.cache/huggingface
      HUGGING_FACE_HUB_TOKEN: ${HF_TOKEN}
      TOKENIZERS_PARALLELISM: "false"
    volumes:
      - ./data/hf-cache:/root/.cache/huggingface
    ports:
      - "127.0.0.1:8000:8000"
    ipc: host
    gpus: all
    command:
      - --model
      - ${MODEL_NAME}
      - --served-model-name
      - ${SERVED_MODEL_NAME}
      - --host
      - 0.0.0.0
      - --port
      - "8000"
      - --api-key
      - ${VLLM_API_KEY}
      - --max-model-len
      - ${VLLM_MAX_MODEL_LEN}
      - --gpu-memory-utilization
      - ${GPU_MEMORY_UTILIZATION}
      - --enable-prefix-caching
    healthcheck:
      test: ["CMD-SHELL", "python3 -c \"import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=5)\""]
      interval: 30s
      timeout: 10s
      retries: 10
      start_period: 180s

  caddy:
    image: caddy:2.10-alpine
    container_name: vllm-caddy
    restart: unless-stopped
    env_file:
      - .env
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./data/caddy-data:/data
      - ./data/caddy-config:/config
    depends_on:
      vllm:
        condition: service_started

Сохраните этот файл как /opt/vllm/compose.yml. Параметр --gpu-memory-utilization 0.88 не резервирует всю VRAM, оставляя запас для CUDA и системных процессов. Если модель не помещается, сначала снизьте контекст, затем уменьшите это значение до 0.80–0.85 либо выберите квантованную модель.

Настройте Caddy и HTTPS

Caddy автоматически запросит и продлит TLS-сертификат, если домен уже указывает на сервер, а порты 80 и 443 открыты. Ниже проксируются только API и health endpoint. Не включайте подробные логи HTTP-запросов без необходимости: промпты пользователей могут оказаться в логах.

{
    email [email protected]
}

{$DOMAIN} {
    encode zstd gzip

    @api {
        path /v1/ /health
    }

    handle @api {
        reverse_proxy vllm:8000 {
            flush_interval -1
        }
    }

    respond "Not found" 404
}

Сохраните конфигурацию как /opt/vllm/Caddyfile и замените email на рабочий адрес для уведомлений Let’s Encrypt. Caddy не добавляет авторизацию самостоятельно: проверку Bearer-токена выполняет vLLM через параметр --api-key.

Запустите сервис

# Скачиваем образы и запускаем Caddy с сервером модели в фоне
cd /opt/vllm
docker compose -f compose.yml pull
docker compose -f compose.yml up -d

# Смотрим прогресс скачивания модели и загрузки движка vLLM
docker compose -f compose.yml logs -f vllm

Первый запуск может занять от нескольких минут до часа: зависит от скорости сети, размера модели и компиляции CUDA kernels. Когда в логе появится сообщение о запуске API-сервера, прервите просмотр сочетанием Ctrl+C; контейнер продолжит работать в фоне.

Проверьте API локально и через HTTPS

# Проверяем readiness напрямую с сервера, не раскрывая API наружу
curl -s http://127.0.0.1:8000/health && echo

# Получаем перечень моделей через публичный HTTPS endpoint
source /opt/vllm/.env
curl -s https://$DOMAIN/v1/models \
  -H "Authorization: Bearer $VLLM_API_KEY" | jq

Запрос должен вернуть объект с моделью qwen3-8b. Теперь отправьте тестовый запрос в формате Chat Completions:

# Отправляем тестовый запрос к OpenAI-совместимому API
source /opt/vllm/.env
curl -s https://$DOMAIN/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $VLLM_API_KEY" \
  -d '{
    "model": "qwen3-8b",
    "messages": [
      {"role": "system", "content": "Отвечай кратко и технически."},
      {"role": "user", "content": "Что такое KV-кеш в LLM?"}
    ],
    "temperature": 0.2,
    "max_tokens": 180
  }' | jq '.choices[0].message.content'

Для Python-клиента используйте официальный SDK OpenAI, но направьте его на свой адрес:

from openai import OpenAI
import os

client = OpenAI(
    base_url="https://llm.example.com/v1",
    api_key=os.environ["VLLM_API_KEY"],
)

response = client.chat.completions.create(
    model="qwen3-8b",
    messages=[{"role": "user", "content": "Составь план резервного копирования."}],
    temperature=0.3,
)

print(response.choices[0].message.content)

Ограничьте доступ приложений

Один общий ключ удобен на старте, но недостаточен для команды или публичного SaaS. vLLM проверяет ключ, однако не предоставляет полноценные квоты, роли, отдельные ключи и биллинг. Для таких задач поставьте перед ним API gateway, например Kong, Traefik с middleware или отдельный backend, который выдаёт ключи, считает токены и применяет rate limit.

Не передавайте ключ браузеру. Клиентское веб-приложение должно обращаться к вашему backend, а backend — к vLLM. Иначе любой посетитель сможет извлечь токен из JavaScript или панели разработчика и использовать GPU за ваш счёт.

Бэкапы и обслуживание

Схема: Бэкапы и обслуживание
Схема: Бэкапы и обслуживание

Вес модели можно повторно скачать, поэтому это не главный объект резервного копирования. Критичны файлы .env, compose.yml, Caddyfile, TLS-данные Caddy и скрипты обслуживания. Если вы добавите RAG, базы векторного поиска, пользовательские файлы или собственные LoRA-адаптеры, их нужно включить в отдельный план бэкапов.

Что сохранять

Данные Нужно бэкапить Причина
.env Да, с шифрованием Содержит API-ключ и настройки модели
compose.yml, Caddyfile Да Быстрое восстановление инфраструктуры
Данные Caddy Да TLS-сертификаты и состояние ACME
HF cache Необязательно Экономит время скачивания, но легко восстанавливается
Логи запросов Обычно нет Могут содержать чувствительные промпты
Векторная БД и документы RAG Обязательно Это уникальные бизнес-данные

Резервное копирование через restic

Restic шифрует архивы до отправки в S3-совместимое хранилище, на отдельный сервер по SFTP или в поддерживаемый облачный backend. Ниже показан вариант с S3. Не храните пароль репозитория в том же публичном Git-репозитории, где лежит инфраструктурный код.

# Устанавливаем restic и создаём каталог для секретов резервного копирования
sudo apt install -y restic
sudo install -d -m 700 /root/.config/restic

# Создаём файл окружения; замените значения своими S3-реквизитами
sudo tee /root/.config/restic/vllm.env > /dev/null <<'EOF'
export RESTIC_REPOSITORY="s3:https://s3.example.net/vllm-backups"
export RESTIC_PASSWORD="CHANGE_THIS_TO_A_LONG_UNIQUE_SECRET"
export AWS_ACCESS_KEY_ID="CHANGE_ME"
export AWS_SECRET_ACCESS_KEY="CHANGE_ME"
EOF
sudo chmod 600 /root/.config/restic/vllm.env

# Инициализируем зашифрованный репозиторий один раз
sudo bash -c 'source /root/.config/restic/vllm.env && restic init'
# Создаём ежедневный скрипт: конфиги и сертификаты сохраняются, кеш модели исключается
sudo tee /opt/vllm/scripts/backup.sh > /dev/null <<'EOF'
#!/usr/bin/env bash
set -euo pipefail

source /root/.config/restic/vllm.env

restic backup /opt/vllm \
  --exclude /opt/vllm/data/hf-cache \
  --exclude /opt/vllm/backups \
  --tag vllm-config

restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
restic check
EOF
sudo chmod 700 /opt/vllm/scripts/backup.sh

# Выполняем первый бэкап вручную и убеждаемся, что он завершается без ошибок
sudo /opt/vllm/scripts/backup.sh
# Запускаем бэкап ежедневно в 03:20 и сохраняем технический журнал в syslog
sudo crontab -e

# Добавьте следующую строку в открывшийся файл:
20 3    /opt/vllm/scripts/backup.sh >> /var/log/vllm-backup.log 2>&1

Проверяйте не только успешный статус бэкапа, но и восстановление. Раз в квартал разверните конфиги на тестовой машине или выполните restic restore latest --target /tmp/vllm-restore, не перезаписывая рабочие данные.

Обновления без неожиданностей

Для одного GPU-сервера безопаснее maintenance window: остановите API, обновите образ, запустите его и прогоните тестовый запрос. Rolling update имеет смысл при двух и более репликах за балансировщиком, когда можно выводить серверы из трафика по одному.

# Перед обновлением фиксируем текущий статус и делаем бэкап
cd /opt/vllm
docker compose -f compose.yml ps
sudo /opt/vllm/scripts/backup.sh

# После изменения тега образа в compose.yml перезапускаем только сервисы проекта
docker compose -f compose.yml pull
docker compose -f compose.yml up -d
docker compose -f compose.yml logs --tail=100 vllm

Не обновляйте одновременно Ubuntu, NVIDIA-драйвер, Docker, CUDA-базовые образы и vLLM перед важным релизом. Меняйте один слой за раз, фиксируйте версию, проверяйте nvidia-smi, затем выполняйте API smoke test.

Troubleshooting + FAQ

Почему контейнер vLLM не видит GPU?

Если в логах есть сообщение о недоступном CUDA-устройстве, сначала выполните nvidia-smi на хосте. Если оно не работает, проблема в драйвере или GPU passthrough. Если на хосте GPU видна, но не видна в Docker, проверьте команду docker run --rm --gpus all nvidia/cuda:12.8.0-base-ubuntu24.04 nvidia-smi. Переустановите NVIDIA Container Toolkit, выполните sudo nvidia-ctk runtime configure --runtime=docker и перезапустите Docker.

Ошибка CUDA out of memory при загрузке модели — что делать?

Ошибка CUDA out of memory означает, что VRAM не хватает для весов, KV-кеша или служебных буферов. Сначала уменьшите VLLM_MAX_MODEL_LEN, например с 8192 до 4096, и снизьте GPU_MEMORY_UTILIZATION до 0.80. Затем используйте меньшую либо квантованную модель AWQ/GPTQ, совместимую с vLLM. Посмотрите nvidia-smi: возможно, память занята другим контейнером или зависшим процессом.

API возвращает 401 Unauthorized, хотя ключ кажется правильным

Проверьте, что заголовок отправляется в формате Authorization: Bearer ВАШ_КЛЮЧ, без кавычек и лишних пробелов. Затем сравните ключ с содержимым /opt/vllm/.env. После изменения .env нужен перезапуск: docker compose -f compose.yml up -d --force-recreate vllm. Не используйте переменную с пустым значением из другой shell-сессии; выполните source /opt/vllm/.env перед curl.

Почему Caddy не выпускает HTTPS-сертификат?

Чаще всего DNS-запись домена ещё не указывает на IP сервера или порт 80 блокируется облачным firewall. Проверьте dig +short llm.example.com, затем sudo ufw status и сетевые правила в панели сервера. Посмотрите docker logs vllm-caddy: там будет причина ACME-ошибки. Для HTTP-01 проверки домен должен быть доступен извне по порту 80, даже если основной API работает только по HTTPS.

Модель отвечает слишком медленно. Что проверять?

Разделите задержку на время первого токена и скорость генерации. Проверьте GPU Utilization и VRAM через watch -n 1 nvidia-smi, логи vLLM и нагрузку CPU. Слишком длинный контекст, высокая параллельность и reasoning-модели увеличивают задержку. Уменьшите max_tokens, ограничьте контекст, включите потоковый режим stream: true в клиенте. Если GPU простаивает, убедитесь, что запросы действительно попадают в vLLM, а не блокируются proxy или приложением.

Какой VPS-конфиг минимально подойдёт?

Для учебного или личного API с 7B–8B моделью в 4-bit минимально разумный вариант — одна NVIDIA GPU с 16 ГБ VRAM, 4–8 vCPU, 32 ГБ RAM и 100 ГБ NVMe. Но комфортнее начинать с 24 ГБ VRAM: это оставляет запас для контекста и нескольких одновременных запросов. Для FP16-весов 8B-модели 16 ГБ обычно недостаточно, поскольку память нужна не только для самих весов.

Что выбрать — VPS или dedicated для этой задачи?

Для одной GPU, модели до 8B–14B и внутреннего API выбирайте GPU VPS, если платформа гарантирует доступ к ускорителю и позволяет запуск Docker. Dedicated нужен при нескольких GPU, 48–80 ГБ VRAM, моделях 32B–70B, высокой постоянной нагрузке и жёстких требованиях к изоляции. Начните с VPS, измерьте реальные токены в секунду, пиковую параллельность и VRAM, а затем переходите на выделенное железо при подтверждённой необходимости.

Можно ли открыть API напрямую на порту 8000?

Технически можно, но для продакшена это плохая практика. Прямой HTTP не шифрует Bearer-токен и содержимое промптов, а порт проще случайно оставить без ограничений. Оставьте 127.0.0.1:8000:8000 в Compose и публикуйте наружу только Caddy на 443. Если API нужен только вам, ещё безопаснее не открывать 443 вовсе и подключаться через WireGuard или SSH-туннель.

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

Измените MODEL_NAME и при необходимости SERVED_MODEL_NAME в .env, затем перезапустите контейнер командой docker compose -f compose.yml up -d --force-recreate vllm. Учитывайте требования новой модели к VRAM, chat template, лицензии и токену Hugging Face. Старый кеш можно оставить: он не мешает работе, но занимает диск. Перед заменой модели сохраните текущую конфигурацию и протестируйте новый вариант в отдельное окно обслуживания.

Выводы и следующие шаги

Схема: Выводы и следующие шаги
Схема: Выводы и следующие шаги

Теперь у вас есть собственный OpenAI-совместимый API на базе vLLM: модель работает на выделенной GPU, API защищён токеном и TLS, а конфигурация воспроизводима через Docker Compose. Такая схема подходит для внутренних ассистентов, RAG-систем, автоматизации разработки и частных AI-приложений.

  1. Измерьте реальную нагрузку: токены в секунду, время первого токена, VRAM и число параллельных запросов.
  2. Добавьте API gateway с отдельными ключами, rate limit и метриками, если сервисом пользуются несколько команд или клиентов.
  3. Для поиска по документам подключите embedding-модель и векторную БД, а для роста нагрузки разверните несколько vLLM-реплик за балансировщиком.

Был ли этот гайд полезен?

Ваш отзыв помогает нам улучшать гайды.

Поделиться записью:

Отправьте гайд тому, кому он может пригодиться.

Telegram VKVK WhatsApp Facebook LinkedIn XX

vllm на gpu-сервере: openai-совместимый api для своей llm
support_agent
Valebyte Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply as soon as possible.