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

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

MAATRIX

Unleash — open-source платформа управления feature flags: включаете и выключаете функции в проде без деплоя, гоняете A/B-тесты, откатываете фичу одним кликом, если что-то пошло не так. Self-hosted версия на своём сервере избавляет от лимитов SaaS-тарифов и держит данные о ваших флагах и пользователях у вас. Но именно самостоятельный хостинг рождает свой набор проблем: от отказа подключения к базе до тихо замолчавших SDK, которые перестали получать обновления. Ниже — разбор самых частых ошибок и как их чинить.

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

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

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

Не стартует: ошибка подключения к PostgreSQL

Unleash хранит все данные — флаги, стратегии, окружения, пользователей — в PostgreSQL, и без рабочего подключения к базе сервис просто не поднимется. В логах контейнера это выглядит так:

error: connect ECONNREFUSED 127.0.0.1:5432

или

error: password authentication failed for user "unleash_user"

Первая причина почти всегда banальна: приложение и база в разных контейнерах Docker Compose, а в DATABASE_URL указан localhost вместо имени сервиса. Внутри docker-сети localhost — это сам контейнер Unleash, а не соседний с Postgres. Проверьте переменные окружения:

environment:
  DATABASE_URL: postgres://unleash_user:пароль@db:5432/unleash
  DATABASE_SSL: "false"

Здесь db — имя сервиса Postgres из того же docker-compose.yml, а не localhost и не IP хоста. Если база живёт отдельно на внешнем сервере, DATABASE_SSL часто нужно включить ("true"), иначе получите отказ уже на этапе TLS-рукопожатия.

Вторая частая причина — база ещё не готова, когда стартует Unleash: контейнер Postgres поднимается на пару секунд дольше, а Unleash пытается подключиться сразу и падает. Добавьте depends_on с условием healthcheck, а не просто порядок запуска:

depends_on:
  db:
    condition: service_healthy

Если ошибка про пароль, а не про соединение — значит роль в Postgres создана с другим паролем или базы unleash вообще не существует. Зайдите внутрь контейнера базы и проверьте вручную:

docker exec -it unleash-db psql -U postgres -c "\l"
docker exec -it unleash-db psql -U postgres -c "\du"

Общие принципы диагностики самой PostgreSQL — в статье про частые ошибки PostgreSQL на сервере: там разобраны connection refused, too many connections и проблемы с правами, которые случаются и здесь, просто под капотом Unleash.

После установки не получается зайти в админку

Свежий self-hosted Unleash при первом запуске создаёт дефолтного администратора: логин admin, пароль unleash4all. Частая ошибка — пробовать зайти этими данными на инстансе, который уже кто-то настраивал раньше, или наоборот — ожидать другого пароля на чистой установке. Проверьте версию и первый запуск логов:

docker logs unleash | grep -i "admin"

Если вход всё равно не проходит с дефолтными данными на действительно новой инсталляции, причина обычно в переменной INIT_ADMIN_API_TOKENS или AUTH_TYPE, которые переопределяют штатное поведение. Если вы задали AUTH_TYPE=oidc или AUTH_TYPE=saml, форма логина по паролю просто не появится — Unleash ждёт SSO-редиректа, а не логин/пароль. Проверьте, какой тип аутентификации реально сконфигурирован:

docker exec -it unleash env | grep AUTH

Ещё одна ловушка: после первого входа Unleash требует сразу сменить пароль администратора. Если сессия обрывается на этом шаге — часто виноват прокси перед приложением, который режет cookie или не пробрасывает Set-Cookie из-за несовпадения домена в secure/sameSite атрибутах. Задайте явно правильный публичный URL:

environment:
  UNLEASH_URL: "https://flags.example.com"

Без корректного UNLEASH_URL Unleash генерирует ссылки и cookie для внутреннего адреса контейнера, и браузер их просто отбрасывает как невалидные для текущего домена.

Нужен сервер под эту задачу?

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

Арендовать сервер

Клиентские SDK не видят изменения флагов

Самая раздражающая категория проблем: в админке флаг включён, а приложение как будто не в курсе. Причин обычно три, и разбирать их нужно по порядку.

Первая — перепутан тип API-токена. У Unleash их два: client token (*:client.секрет) для бэкенд-SDK и frontend token (*:frontend.секрет) для клиентского SDK в браузере или мобильном приложении. Если backend-SDK подключить с frontend-токеном, запросы будут падать с 401, и в логах SDK это часто выглядит как молчаливая тишина, а не явная ошибка:

Unleash SDK: 401 Unauthorized fetching feature toggles

Проверьте тип токена в админке (Settings → API access) и сверьте с тем, что реально стоит в переменной окружения приложения.

Вторая причина — флаг создан не в том окружении. Unleash по умолчанию разделяет development, staging, production, и включение флага в development никак не влияет на production, даже если это один и тот же проект. SDK всегда запрашивает конкретное окружение через заголовок, который проставляется автоматически из токена — но токен как раз и привязан к окружению при создании. Пересоздайте токен под нужное окружение, если ошиблись при первой настройке.

Третья — SDK инициализирован раньше, чем успел получить первый ответ, и приложение читает состояние флага до завершения start(). Для Node.js SDK правильный паттерн:

const { initialize } = require('unleash-client');

const unleash = initialize({
  url: 'https://flags.example.com/api/',
  appName: 'my-app',
  customHeaders: { Authorization: 'ваш-client-токен' },
});

unleash.on('synchronized', () => {
  // теперь isEnabled() отдаёт актуальные данные
});

Без ожидания события synchronized (или ready) первые запросы к isEnabled() могут вернуть дефолтное значение флага, а не то, что реально стоит на сервере.

Обрывы соединения и зависший UI за reverse proxy

Unleash использует Server-Sent Events (SSE) для доставки обновлений в реальном времени в админку и для потоковой синхронизации у Unleash Edge. Если между браузером и Unleash стоит nginx или другой прокси с настройками по умолчанию, соединение будет обрываться каждые 60 секунд, а UI — терять связь и показывать «переподключение». Для nginx нужно явно отключить буферизацию и увеличить таймаут именно для этого location:

location /api/admin/features-events {
    proxy_pass http://unleash:4242;
    proxy_http_version 1.1;
    proxy_set_header Connection '';
    proxy_buffering off;
    proxy_cache off;
    proxy_read_timeout 3600s;
}

location / {
    proxy_pass http://unleash:4242;
    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;
}

Если у вас Traefik, аналогичная проблема решается через таймауты в transport — без этого длинные SSE-соединения тоже будут резаться реверс-прокси раньше, чем клиент сам решит переподключиться. Общие приёмы настройки nginx как reverse proxy для Docker-приложений разобраны в статье про частые ошибки nginx как reverse proxy — принципы с буферизацией и таймаутами там применимы один в один. Если вместо обрывов вы видите 504 Gateway Timeout на медленных запросах к API Unleash, это отдельная и более общая история — она разобрана в статье про 504 Gateway Timeout в nginx.

CORS-ошибки во frontend SDK

Когда флаги запрашиваются напрямую из браузера через @unleash/proxy-client-react или похожий frontend SDK, а не через ваш собственный бэкенд, браузер шлёт CORS-preflight запрос — и по умолчанию Unleash его отклоняет для незнакомых доменов. В консоли браузера это видно как:

Access to fetch at 'https://flags.example.com/api/frontend'
from origin 'https://app.example.com' has been blocked by CORS policy

Решение — явно перечислить разрешённые origin в конфиге Unleash (переменная UNLEASH_FRONTEND_API_ORIGINS в новых версиях, или через настройки Frontend API в UI на более старых):

environment:
  UNLEASH_FRONTEND_API_ORIGINS: "https://app.example.com,https://staging.example.com"

Звёздочка * работает, но открывает Frontend API любому источнику — приемлемо для внутренних дашбордов за VPN, но не для публичного продакшена: frontend-токен всё же даёт доступ на чтение всех флагов конкретного окружения. Для высоконагруженных публичных фронтендов Unleash рекомендует ставить перед основным сервером лёгкий Unleash Edge — он кэширует флаги локально и снимает нагрузку с центрального инстанса, заодно упрощая CORS, потому что запросы идут на ваш же домен.

Миграции падают при обновлении версии

При обновлении образа Unleash на новую мажорную версию автоматические миграции базы иногда падают с ошибками вида relation "..." already exists или migration table is locked. Обычно это значит, что предыдущий запуск миграции был прерван на середине — например, контейнер перезапустили руками во время старта. Первое, что нужно сделать перед любым обновлением — снять бэкап базы:

docker exec unleash-db pg_dump -U unleash_user unleash > unleash_backup_$(date +%F).sql

Если миграция зависла на блокировке, посмотрите активные соединения к базе и завершите то, что держит лок:

SELECT pid, state, query FROM pg_stat_activity WHERE datname = 'unleash';
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'unleash' AND state = 'idle in transaction';

Если ошибка про уже существующую таблицу — значит миграция частично прошла раньше. В большинстве случаев безопаснее не редактировать таблицу миграций вручную, а восстановить базу из бэкапа, снятого до обновления, и повторить апгрейд с чистого состояния. Не пропускайте промежуточные мажорные версии при апгрейде через несколько релизов сразу — Unleash, как и многие проекты с миграциями схемы, рассчитан на последовательные обновления, а не на прыжок через две-три версии разом. Общие принципы безопасного обновления сервисов в Docker Compose — в статье про частые ошибки Docker Compose для продакшена.

Нужен сервер под эту задачу?

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

Арендовать сервер

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

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

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

Обязательно ли использовать именно PostgreSQL?

Да, self-hosted Unleash поддерживает только PostgreSQL как хранилище данных — MySQL, SQLite и другие базы официально не поддерживаются. Минимальная рекомендуемая версия — PostgreSQL 12+, на практике удобнее ставить актуальную LTS-версию, например 16 или 17.

Сколько ресурсов нужно серверу под Unleash?

Для небольшой и средней команды достаточно 1-2 vCPU и 2 ГБ RAM под сам Unleash плюс отдельные ресурсы под PostgreSQL — сервис лёгкий, основная нагрузка приходится на базу при большом числе запросов от SDK. Для высокой частоты опроса (polling) десятков сервисов лучше переходить на потоковый режим или ставить Unleash Edge, чтобы не долбить центральный инстанс.

Чем polling отличается от streaming в SDK и что выбрать?

По умолчанию клиентские SDK опрашивают сервер раз в 10-15 секунд (polling) — это надёжно, но создаёт постоянную фоновую нагрузку. Streaming через SSE снижает задержку обновления флага почти до реального времени и меньше нагружает сервер на большом числе клиентов, но требует, чтобы прокси перед Unleash корректно пропускал долгие соединения — см. раздел про SSE выше.

Можно ли восстановить удалённый по ошибке флаг?

Если включена soft-delete архивация (по умолчанию она есть), удалённые флаги на время попадают в архив в разделе Archive и их можно восстановить оттуда. Если флаг уже вычищен из архива или прошло много времени, единственный путь — восстановление из бэкапа базы PostgreSQL.

Нужен ли Unleash Edge для небольшого проекта?

Нет, для одного-двух приложений с умеренной нагрузкой хватает прямого подключения SDK к основному инстансу Unleash. Edge имеет смысл добавлять, когда флаги запрашивают десятки сервисов или тысячи фронтенд-клиентов одновременно и вы хотите снять эту нагрузку с центральной базы.

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

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

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