MAATRIX / Блог / Open WebUI на сервере: частые ошибки и решения

Open WebUI на сервере: частые ошибки и решения

Open WebUI на сервере: частые ошибки и решения

MAATRIX

Open WebUI ставится одной командой docker run, а ломается по короткому и предсказуемому списку: белый экран вместо интерфейса, пустой селектор моделей, «Account Activation Pending» у коллеги, ответ одним куском через минуту, кончившийся диск на третьей неделе. Почти каждая из этих ошибок Open WebUI лечится одной переменной окружения, строкой в nginx или запросом к базе — ниже разбор с реальными строками из логов и консоли браузера.

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

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

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

Быстрая диагностика: три слоя и четыре команды

Open WebUI — это три слоя, и поломка почти всегда живёт ровно в одном: контейнер, бэкенды моделей (Ollama, внешний OpenAI-совместимый эндпоинт) и транспорт до браузера (прокси, WebSocket, куки). Определяйте слой, а не гуглите текст ошибки целиком.

docker ps --filter name=open-webui --format "{{.Status}}\t{{.Ports}}"
curl -s -w " HTTP %{http_code}\n" http://127.0.0.1:3000/health
docker logs --tail 300 open-webui 2>&1 | grep -iE "error|traceback|refused"
docker exec open-webui env | grep -E "OLLAMA|OPENAI|WEBUI"

Здоровая машина отвечает Up 6 hours (healthy) 127.0.0.1:3000->8080/tcp и {"status":true} HTTP 200. Если health отдаёт 200, а в браузере пусто — виноват третий слой. Пока в логах нет строки INFO: Application startup complete., браузер честно получает белый экран: идут миграции и скачивание модели эмбеддингов, на слабой машине три-пять минут. Последняя команда самая недооценённая — она показывает, что контейнер получил на самом деле, а не что вы написали в compose.

Интерфейс не открывается: порты, фаервол и падающий контейнер

Внутри контейнера Open WebUI всегда слушает 8080, наружу его принято отдавать на 3000: -p 127.0.0.1:3000:8080. Запись -p 8080:3000 отработает без ошибок, только за портом никого не будет (ss -ltnp | grep 3000). Если порт занят, докер отвечает дословно: Bind for 0.0.0.0:3000 failed: port is already allocated.

Дальше ловушка, на которой обжигаются почти все. UFW не защищает опубликованные порты Docker. Пишете ufw deny 3000/tcp, видите правило в ufw status, а сервис открыт всему интернету: докер добавляет свои правила в цепочку DOCKER-USER, и трафик идёт мимо цепочек ufw (iptables -L DOCKER-USER -n -v). Решение не в борьбе с iptables: не публикуйте порт вообще — слушайте 127.0.0.1:3000, наружу отдавайте только 443 через nginx. Открытый Open WebUI сканеры находят за часы, и первый зашедший станет вашим администратором.

Отдельный симптом — Restarting (137) в выводе docker ps. Код 137 это SIGKILL: в девяти случаях из десяти процесс убило ядро за нехватку памяти, и проверяется это одной командой — docker inspect --format='{{.State.OOMKilled}} {{.State.ExitCode}}' open-webui. Ответ true 137 закрывает вопрос. Типовой случай — 2 ГБ на VPS, где рядом крутится Ollama с загруженной моделью.

Последняя причина зависшего старта — закрытый исходящий трафик: при первом запуске приложение тянет модель эмбеддингов sentence-transformers/all-MiniLM-L6-v2 с huggingface.co и упирается в:

OSError: We couldn't connect to 'https://huggingface.co' to load the files,
and couldn't find them in the cached files.

Лечится зеркалом HF_ENDPOINT=https://hf-mirror.com либо переводом эмбеддингов на локальный движок (RAG_EMBEDDING_ENGINE=ollama). Есть ещё OFFLINE_MODE=true, но он запрещает загрузку любых моделей — встроенный RAG после него не заработает.

Развернуть за пару минут

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

Развернуть Open WebUI

Пустой список моделей и «Server Connection Error»

Вход выполнен, а селектор моделей пуст или при отправке сообщения всплывает красное уведомление о проблеме соединения. В логах при этом:

aiohttp.client_exceptions.ClientConnectorError: Cannot connect to host
127.0.0.1:11434 ssl:default [Connect call failed ('127.0.0.1', 11434)]

Внутри контейнера 127.0.0.1 указывает на сам контейнер, поэтому Ollama на хосте по нему не найдётся никогда. Берём адрес docker-моста из ip -4 addr show docker0 | grep inet (обычно 172.17.0.1) и ставим OLLAMA_BASE_URL=http://172.17.0.1:11434.

Второе условие: Ollama по умолчанию слушает только петлю, ей нужен оверрайд systemctl edit ollama.service со строкой Environment="OLLAMA_HOST=0.0.0.0:11434". После перезапуска в ss -ltnp | grep 11434 должно появиться LISTEN 0 4096 *:11434.

Оговорка, которую мануалы пропускают: у Ollama нет авторизации вообще, поэтому наружу 11434 не публикуют, а в фаерволе открывают ровно на сеть докера. Связь изнутри контейнера удобно проверять питоном (curl в образе может отсутствовать): docker exec open-webui python -c "import urllib.request as u; print(u.urlopen('http://172.17.0.1:11434/api/tags').read()[:120])".

У внешних OpenAI-совместимых эндпоинтов свои грабли. Базовый URL обязан включать /v1: без суффикса получите 404 и пустой список. Адреса перечисляются в OPENAI_API_BASE_URLS через точку с запятой, и ключи в OPENAI_API_KEYS должны идти в том же порядке — рассинхрон даёт 401 при верных ключах. Если список моделей открывается по двадцать-тридцать секунд, виноват один мёртвый эндпоинт: в ветке 0.6.x лечится переменной AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST=10. И отдельный класс — 403 про неподдерживаемую страну: это не конфиг, а IP сервера, лечится только локацией.

Вход не работает: pending, 401 и потерянный админ

Первый зарегистрированный аккаунт становится администратором, все следующие получают роль из DEFAULT_USER_ROLE со значением по умолчанию pending. Поэтому коллега регистрируется и видит Account Activation Pending — Contact Admin for WebUI Access. Это не поломка: одобряйте людей в админ-панели (раздел Users) либо выставьте DEFAULT_USER_ROLE=user, а когда все свои зашли — закрывайте регистрацию через ENABLE_SIGNUP=false.

Второй симптом — «всех разлогинило, а клиенты по API получают 401». Виноват WEBUI_SECRET_KEY, которым подписываются JWT сессий: если он не задан явно, то генерируется при первом старте в /app/backend/data/.webui_secret_key. Пересоздали volume, переехали на другую машину, поменяли значение — все токены недействительны. Задайте ключ один раз через openssl rand -hex 32 и держите в бэкапе рядом с базой.

Третий случай, самый нервный: потерян пароль администратора, а почта для восстановления не настроена. Чинится в SQLite напрямую — хеш берём библиотекой из контейнера, базу правим на остановленном сервисе:

docker exec open-webui python -c "import bcrypt; print(bcrypt.hashpw(b'Пароль123', bcrypt.gensalt()).decode())"
docker stop open-webui
DB=/var/lib/docker/volumes/open-webui/_data/webui.db
sqlite3 "$DB" "UPDATE auth SET password='ХЕШ_2b12' WHERE email='admin@example.com';"
sqlite3 "$DB" "UPDATE user SET role='admin' WHERE email='admin@example.com';"
docker start open-webui

Четвёртый симптом — бесконечный цикл входа: пароль принят, страница мигает и снова просит логин. Так проявляется кука сессии с флагом Secure, которую браузер не хранит на обычном http — лечится доведённым до конца HTTPS и переменной WEBUI_URL=https://chat.example.com. И про WEBUI_AUTH=False с форумов: он снимает авторизацию полностью, каждый знающий адрес получает права админа.

Стриминг обрывается, чат не обновляется, приходит 524

Интерфейс использует два транспорта, и ломаются они по-разному: токены ответа идут потоком SSE, события — через socket.io по пути /ws/socket.io/. Ответ пришёл одним куском в конце: это SSE и буферизация в nginx. Чат «залипает» и оживает только после F5: упал WebSocket, и в консоли браузера лежит

WebSocket connection to 'wss://chat.example.com/ws/socket.io/?EIO=4&transport=websocket'
failed: Error during WebSocket handshake: Unexpected response code: 400

Секция nginx на оба случая:

location / {
    proxy_pass http://127.0.0.1:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_buffering off;
    proxy_read_timeout 600s;
    client_max_body_size 200m;
}

Применяем через nginx -t && systemctl reload nginx. Ровно 60 секунд до ошибки в логе — подпись дефолтного proxy_read_timeout, а client_max_body_size снимает 413 при загрузке крупных PDF. Если домен проксируется через Cloudflare в оранжевом режиме, помните про потолок в 100 секунд и ошибку 524 — для длинных генераций держите домен в режиме DNS-only.

Отдельная засада у тех, кто решил «ускорить» сервис воркерами: при UVICORN_WORKERS=4 события теряются — сообщение ушло одному воркеру, сокет пользователя висит на другом, ответ пишется в базу, но виден только после F5. Нужна общая шина: WEBSOCKET_MANAGER=redis и WEBSOCKET_REDIS_URL=redis://127.0.0.1:6379/1. Честно: команде из 5–20 человек воркеры не нужны вовсе.

Правки не применяются, диск кончился, обновление сломало базу

Самая обидная ошибка второй недели: правите переменную в compose.yaml, перезапускаете контейнер — и ничего не меняется. При первом запуске Open WebUI копирует часть настроек из окружения в таблицу config внутри базы, и дальше приоритет у базы. Что там реально лежит, покажет sqlite3 /var/lib/docker/volumes/open-webui/_data/webui.db "SELECT data FROM config ORDER BY id DESC LIMIT 1;" | python3 -m json.tool. Решения два: менять такие параметры в админ-панели либо выставить ENABLE_PERSISTENT_CONFIG=False, чтобы окружение было главнее — правда, тогда они перестают редактироваться из интерфейса.

Второе — диск. Смотрите не общий объём, а разбивку docker exec open-webui du -sh /app/backend/data/* | sort -h. Типичная картина там, где полгода работали с документами: webui.db — 1,4 МБ, cache — 340 МБ, uploads — 1,1 ГБ, vector_db — 1,6 ГБ. Векторный индекс сопоставим по объёму с исходниками, а сами исходники остаются лежать рядом в uploads: удаление документа из интерфейса не всегда вычищает файл с диска. Плюс логи докера, у json-file лимита по умолчанию нет: --log-opt max-size=50m --log-opt max-file=3.

Третье — database is locked: SQLite не любит параллельную запись, и на десятке активных пользователей это вылезает регулярно. Переезд делается переменной DATABASE_URL=postgresql://openwebui:ПАРОЛЬ@127.0.0.1:5432/openwebui, но штатного переноса данных из SQLite в Postgres в проекте нет — либо чистая база, либо community-скрипты. Решайте про СУБД на старте.

Четвёртое — обновления. Тег :main меняется под вами, и однажды после планового docker pull сервис не поднимется — фиксируйте версию, например ghcr.io/open-webui/open-webui:v0.6.18. Безопасный порядок:

docker stop open-webui
tar czf /var/backups/openwebui-$(date +%F).tgz -C /var/lib/docker/volumes/open-webui/_data .
docker pull ghcr.io/open-webui/open-webui:main
docker rm open-webui && docker run -d ...   # ваша обычная команда запуска

Главное про откат: миграции alembic едут только вперёд. Вернёте старый образ на уже мигрированную базу — получите alembic.util.exc.CommandError: Can't locate revision identified by 'a1b2c3d4e5f6' или ошибку SQLAlchemy про отсутствующую колонку. Откат — это всегда пара: старый тег образа плюс восстановленный из архива каталог данных. Поэтому не вешайте на Open WebUI автообновление вроде Watchtower.

Какой сервер брать под Open WebUI в MAATRIX

Сам Open WebUI — лёгкое веб-приложение: чат, история, роли, проксирование запросов. Тяжёлым он становится в двух местах: когда на той же машине считает модели Ollama и когда вы активно пользуетесь базой знаний.

СценарийvCPURAMДиск NVMe
Интерфейс к внешним API (OpenAI, Anthropic, свой LiteLLM)24 ГБ40 ГБ
Интерфейс плюс Ollama, модели до 8B48 ГБ80 ГБ
Команда, RAG, PostgreSQL рядом, модели до 14B816 ГБ160–200 ГБ

Минимум, на котором это честно работает — 2 vCPU, 4 ГБ, 40 ГБ, и только если модели считаются не здесь. Контейнер в простое держит 600–900 МБ RSS, после первого обращения к базе знаний — 1,2–1,5 ГБ. На двух гигабайтах вы получите тот самый Restarting (137) из второй секции.

Комфортный вариант — 8 vCPU и 16 ГБ: помещается всё, включая Ollama с моделью на 8–14 миллиардов параметров и PostgreSQL вместо SQLite. Диск кончается первым: 8B в квантовании Q4 занимает около 4,7 ГБ, 14B — порядка 9 ГБ, и три-четыре модели вместе с индексом съедают 80 ГБ.

Локация — Великобритания (Лондон). Open WebUI это интерактивный интерфейс, а не фоновый демон: задержка чувствуется на каждом действии — открытии чата, переключении модели, загрузке файла. Из Москвы до Лондона порядка 45–60 мс против 110–130 мс до Нью-Йорка. При этом британский IP спокойно принимают OpenAI, Anthropic и Google, так что 403 про неподдерживаемую страну не грозит. Франция — равноценная альтернатива для пользователей в ЕС, Нью-Йорк берут под сервисы для американских адресов, а российская локация оправдана, когда все модели локальные и 152-ФЗ важнее задержки.

Оплата — картами российских банков, по СБП, криптовалютой или токеном MAAT; зарубежная карта для сервера в Лондоне не нужна. Связка Ollama и Open WebUI разворачивается из каталога приложений, а установку с нуля мы разбирали в соседних статьях «Open WebUI на Ubuntu 24.04: пошаговая установка» и «Как установить и настроить Open WebUI на VPS». Сомневаетесь в конфигурации — опишите сценарий: сколько человек, какие модели, есть ли база знаний.

Развернуть за пару минут

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

Развернуть Open WebUI

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

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

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

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

Почему я изменил переменную окружения, а Open WebUI её игнорирует?

Часть настроек при первом старте копируется в таблицу config внутри базы, и дальше приоритет у неё. Меняйте такие параметры в админ-панели либо выставьте ENABLE_PERSISTENT_CONFIG=False.

Открыл 11434 наружу, чтобы Open WebUI видел Ollama. Это нормально?

Нет: у Ollama нет авторизации вообще, и публичный 11434 означает, что ваш процессор считает чужие запросы. Пусть она слушает 0.0.0.0 внутри машины, а фаервол пускает только сеть докера: ufw allow from 172.17.0.0/16 to any port 11434 proto tcp.

Можно ли откатиться на предыдущую версию, если обновление сломало сервис?

Только вместе с данными: миграции alembic необратимы, старый образ на новой схеме падает с Can't locate revision identified by .... Откат — это старый тег образа плюс каталог /app/backend/data из архива, снятого до обновления.

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

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