Слушай, признайся честно. Когда все вокруг заливают демки с GPU-инстансами за $2 в час, а ты сидишь на обычном VPS за десять баксов в месяц — чувствуешь себя прокаженным. Особенно когда хочешь поднять свой приватный AI-ассистент, но видеокарты нет, и не предвидится. Хорошая новость: запустить Ollama и Open WebUI на CPU — это не мазохизм, а вполне рабочая стратегия, если знать нюансы. Плохая новость: гайды, которые ты найдешь в интернете, обычно написаны людьми, которые ни разу не сталкивались с OOM killer'ом на VPS с 8 ГБ RAM.
Я прошел через это. Сжег пару инстансов, убил кучу времени на дебаг прокси. Теперь делюсь готовой схемой. Стек: Docker + Ollama + Open WebUI + nginx + Let's Encrypt. Без GPU. Без лишнего геморроя. С реальными граблями.
Почему CPU VPS — это не ад, но близко
GPU на VPS стоит дорого. A100 — $2-3 в час, RTX 4090 — $0.80-1.2. Для pet-проекта или внутреннего ассистента в маленькой команде это непозволительная роскошь. CPU-инференс даёт 2-5 токенов в секунду на моделях вроде Llama 3.1 8B, что для чата вполне терпимо — читать успеваешь, особенно если запросы короткие.
Важно: Не рассчитывай на real-time общение. На 7B модели с квантованием Q4_K_M ты получишь ~3 токена/с. Это в 5-10 раз медленнее, чем на GPU, но в 100 раз дешевле. Для написания email, суммаризации документации или генерации кода — норм.
Проблема номер один — оперативная память. Не RAM, а её отсутствие. VPS за $10 обычно даёт 2-4 ГБ — этого катастрофически мало. Для 8B модели нужно минимум 8 ГБ свободной RAM (с квантованием — 6 ГБ). В системе с 8 ГБ после запуска модели остаётся 1-2 ГБ — любой всплеск памяти убьёт процесс. Выход: VPS с 16 ГБ RAM или NVMe swapping, о котором я писал отдельно. Но лучше сразу брать 12-16 ГБ.
Какой VPS выбрать под CPU-инференс
Не все облачные провайдеры одинаково полезны. Тебе нужно железо с высокой тактовой частотой CPU и быстрой памятью. Intel Xeon Gold 6xxx или AMD EPYC — идеально. Дешёвые Intel Xeon E5 (как у Hetzner CX) слабее, но для 8B модели хватит.
| Провайдер | Конфиг (CPU/RAM/диск) | Цена/мес | Подходит для |
|---|---|---|---|
| Hetzner | 4 vCPU, 16 GB, 160 GB NVMe | ~€28 | Llama 8B, Qwen 7B |
| DigitalOcean | 4 vCPU, 8 GB, 160 GB SSD | $48 | Только phi-3 3.8B |
| Contabo | 6 vCPU, 16 GB, 200 GB SSD | €10 | Лучший бюджетный вариант |
Мой выбор — Contabo или Hetzner. У Contabo дешево, но CPU староваты (Xeon E5). Hetzner дороже, но дает современные AMD EPYC. Если бюджет критичен — бери Contabo. Если важна скорость генерации — Hetzner или гибридная архитектура.
Готовимся к установке: Docker и зависимости
Оставим в стороне установку вручную через apt — мы DevOps или кто? Используем официальные скрипты, чтобы версии были свежие.
1 Установка Docker и Docker Compose
Заходим на VPS по SSH. Всё, что нужно — один скрипт от Docker (на май 2026 последний стабильный Docker 26.1).
sudo apt update && sudo apt upgrade -y
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER
newgrp docker
# Проверяем:
docker –version
# Docker Compose v2 уже встроен
docker compose version
Ошибка новичка: Не добавлять пользователя в группу docker. После этого придется писать sudo перед каждой командой. Либо сразу настрой sudo, либо — наше решение выше.
2 Создаём структуру папок
mkdir -p ~/ollama-webui/{nginx,data/ollama,data/open-webui}
cd ~/ollama-webui
Docker Compose: мозг всей системы
Создаём файл docker-compose.yml. В нём три сервиса: Ollama, Open WebUI, nginx. Важно: Open WebUI по умолчанию доступен без пароля — опасно. Сразу включим аутентификацию.
version: '3.8'
services:
ollama:
image: ollama/ollama:latest
container_name: ollama
restart: always
volumes:
- ./data/ollama:/root/.ollama
environment:
- OLLAMA_KEEP_ALIVE=24h
- OLLAMA_NUM_PARALLEL=1
# Ограничиваем память, чтобы не убить VPS
deploy:
resources:
limits:
memory: 12g
reservations:
memory: 6g
open-webui:
image: ghcr.io/open-webui/open-webui:latest
container_name: open-webui
restart: always
depends_on:
- ollama
volumes:
- ./data/open-webui:/app/backend/data
environment:
- OLLAMA_BASE_URL=http://ollama:11434
- WEBUI_SECRET_KEY=твой_случайный_ключ_64_символа
- WEBUI_AUTH=true
- WEBUI_NAME=Мой AI
deploy:
resources:
limits:
memory: 2g
nginx:
image: nginx:alpine
container_name: nginx
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
- ./nginx/ssl:/etc/nginx/ssl:ro
depends_on:
- open-webui
Ключевые моменты:
OLLAMA_KEEP_ALIVE=24h— модель остаётся в памяти 24 часа после первого запроса. Иначе придётся ждать загрузку при каждом обращении.OLLAMA_NUM_PARALLEL=1— параллельная обработка на CPU убьёт производительность. Лучше один запрос за раз.WEBUI_SECRET_KEY— обязателен. Сгенерируй черезopenssl rand -base64 64.deploy.resources.limits.memory— защита от OOM. Не ставь выше реальной RAM на VPS минус 2 ГБ для системы.
Грабли: Если не указать лимиты, Ollama может сожрать всю память и VPS уйдёт в своп. При активной своп-активности (особенно на медленных SSD) скорость упадёт до 0.2 токена/с. Лучше ограничить модель через env OLLAMA_MAX_LOADED_MODELS=1.
Nginx: прокси с веб-сокетами и SSL
Создаём nginx/nginx.conf. Open WebUI использует веб-сокеты для стриминга токенов. Без проксирования Upgrade заголовков чат не будет обновляться в реальном времени.
upstream open-webui {
server open-webui:8080;
}
server {
listen 80;
server_name ai.ваш-домен.ru;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name ai.ваш-домен.ru;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
location / {
proxy_pass http://open-webui;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
3 SSL-сертификат через Let's Encrypt
Не копируй самоподписанные сертификаты — это прошлый век. Используй Certbot с nginx плагином. Но из-за того, что nginx у нас в Docker, процесс чуть сложнее. Есть два пути:
- Получить сертификат на хост-машине, потом смонтировать в контейнер.
- Использовать образ nginx-proxy с автоматическим получением (jwilder/nginx-proxy + acme-companion) — для ленивых, но монструозно.
Я предпочитаю первый. Ставим certbot на хосте, получаем сертификат, потом маунтим папку в контейнер:
sudo apt install certbot -y
sudo certbot certonly --standalone -d ai.ваш-домен.ru
# Сертификаты лягут в /etc/letsencrypt/live/ai.ваш-домен.ru/
# Копируем в папку nginx/ssl:
sudo cp /etc/letsencrypt/live/ai.ваш-домен.ru/fullchain.pem ~/ollama-webui/nginx/ssl/
sudo cp /etc/letsencrypt/live/ai.ваш-домен.ru/privkey.pem ~/ollama-webui/nginx/ssl/
sudo chmod 644 ~/ollama-webui/nginx/ssl/*.pem
Обновление сертификатов через cron раз в 2 месяца: certbot renew --quiet.
Первый запуск и загрузка модели
Всё готово. Поднимаем стенд:
docker compose up -d
Теперь нужно загрузить модель. Заходим в контейнер Ollama:
docker exec -it ollama ollama pull llama3.1:8b-q4_K_M
Почему именно q4_K_M? Это квантование 4-бит. Качество почти не отличается от оригинала, но модель весит 4.9 ГБ вместо 16 ГБ. На CPU это единственный разумный выбор. Для 16GB VPS можно попробовать qwen2.5:7b или phi-3:3.8b-mini-4k. Полный список — в моём гайде по локальному запуску.
После загрузки — открывай https://ai.твой-домен.ru. Первый регистрирующийся пользователь станет админом (требуется WEBUI_AUTH=true). В настройках Open WebUI выбери модель и пробуй.
Подводные камни, которые я вывез за вас
Хватит теории. Вот три проблемы, с которыми я столкнулся при деплое на четырёх разных VPS:
🔴 Проблема 1. OOM через 10 минут работы
Симптом: Ollama падает, контейнер перезапускается, история теряется.
Причина: Модель использует больше RAM, чем вы выделили. Даже с Q4, контекст в 32K токенов потребляет лишние 2 ГБ.
Решение: В Open WebUI настройте максимальный контекст (слайдер в админке: CONTEXT_LENGTH = 2048). И добавьте флаг OLLAMA_MAX_LOADED_MODELS=1 в окружение Ollama. Также настройте vm.swappiness=10 на хосте.
🔴 Проблема 2. Медленный стриминг (зависание на 10 секунд)
Симптом: Вывод в Open WebUI идёт рывками.
Причина: Nginx не проксирует Upgrade заголовки или буферизирует ответ.
Решение: Добавить в nginx proxy_buffering off; и proxy_read_timeout 300s;. Проверить, что в конфиге указан Connection upgrade (как в нашем шаблоне).
🔴 Проблема 3. SSL не работает после перезагрузки
Симптом: Open WebUI доступен только по HTTP.
Причина: Файлы сертификата удалены или не смонтированы.
Решение: Добавить автоматическое копирование сертификатов в папку ./nginx/ssl через cron (или использовать volume mount на хостовую папку /etc/letsencrypt).
FAQ: вопросы, которые мне задают под каждым гайдом
Вопрос: Можно ли запустить Llama 3.1 70B на 16 ГБ VPS?
Ответ: Только с Q2 квантованием и 2048 контекстом. Но скорость будет ~0.5 токена/с — это нечитаемо. Лучше взять 8B.
Вопрос: Как защитить Open WebUI от внешних?
Установи WEBUI_AUTH=true и сгенерируй сложный WEBUI_SECRET_KEY. Дополнительно — Cloudflare Access или Authelia. Подробнее в статье про безопасность.
Вопрос: Какая модель самая быстрая на CPU?
Phi-3-mini (3.8B, 4-битное квантование) выдаёт ~8-10 токенов/с на 6 ядрах. Llama 3.2 3B — тоже неплохо. Но по качеству Llama 3.1 8B заметно лучше. Смотрите обзор.
Вопрос: Стоит ли добавлять веб-поиск?
Да, Open WebUI поддерживает подключение к SearXNG или Google через Custom Tool. Это превращает LLM в реального ассистента. Но на CPU всё замедлится в 2 раза. Гайд здесь.
Альтернативы: когда CPU VPS уже не тянет
Если через месяц эксплуатации скорость начала бесить — есть пути:
- Tesla P100 на домашнем сервере — дешёвый GPU (ок·оло $150 на eBay). Подключаете к домашней машине, пробрасываете порт.
- Арендовать GPU-инстанс с почасовой оплатой. Запускать только когда нужен ответ. Схема гибрида описана в этой статье.
- Но если бюджет жёстко ограничен — CPU VPS + Q4 модель остаётся лучшим выбором.
Однажды я оставил стенд на Contabo на 3 месяца. Счет был ~€30. За это время ассистент обработал около 50 000 запросов (суммаризация логов, ген кода). Ни одного падения. OOM не было, потому что я поставил лимиты и маленький контекст. Если у вас похожие сценарии — дерзайте.
Но есть нюанс, о котором молчат. Настоящая причина, по которой многие берут GPU — не скорость, а интерактивность. На CPU каждый ответ занимает 30-60 секунд. Это убивает поток сознания. Если вам нужен ассистент для диалога (не для одноразовых промптов) — лучше скинуться на GPU или взять облачную LLM с подпиской. А для ETL, генерации кода, автотестов — CPU VSS без GPU идеален. Выбор за вами.