localhost, использует учётные данные из compose.yaml и не терминирует TLS. Для сервера, смотрящего
в интернет, прочитайте Развёртывание и
Обратный прокси, прежде чем что-либо выставлять наружу.
Перед началом
Что делает каждый сервис
compose.yaml описывает семь сервисов. Порт на хост публикуют только api и web; PostgreSQL и
Valkey остаются во внутренней сети Compose.
У сервиса
migrate DSN для разработки
postgres://omniflow:omniflow@postgres:5432/omniflow?sslmode=disable жёстко зашит в команду, и
.env он не читает. Если вы меняете учётные данные базы данных, меняйте их и в compose.yaml,
иначе миграции будут применены не туда, куда смотрит приложение.Настройте установку
Вся конфигурация, принадлежащая проекту, — это переменные окружения с префиксомAPP_, читаемые
один раз при старте. Конфигурационного файла нет, горячей перезагрузки нет: изменение значения
означает перезапуск процесса, который его читает.
1
Скопируйте файл-пример
2
Сгенерируйте два секрета
APP_DATA_ENCRYPTION_KEY должен декодироваться ровно в 32 байта, иначе запуск падает с
APP_DATA_ENCRYPTION_KEY must be base64-encoded 32 bytes. Им запечатываются контактные данные,
TOTP-секреты, клиентские секреты OIDC, учётные данные провайдеров и короткоживущая cookie
процесса входа — потеря ключа означает потерю доступа ко всему этому.APP_OPERATOR_TOKEN — предъявительские учётные данные для всего префикса /v1/admin,
сравниваемые за постоянное время. Подойдёт любая случайная строка с высокой энтропией.3
Заполните значения, которые нужны процессам
Другие значения валидируются так же:
APP_DEFAULT_CURRENCY после приведения к верхнему регистру
должен совпадать с ^[A-Z]{3}$, APP_TELEGRAM_WEBHOOK_URL должен быть HTTPS, а
APP_TELEMETRY_ENDPOINT должен быть HTTPS-URL, пока телеметрия включена.4
Разрешите cookie по обычному HTTP для локального стека
true, и это правильно для всего, перед чем стоит TLS. При отключении
API пишет admin session cookie is not marked Secure; use this only for local development, и
это предупреждение точное: без Secure cookie сессии можно перехватить из любого
незашифрованного запроса к тому же хосту. Верните обе в true, прежде чем установка покинет
вашу машину.Поднимите стек
migrate запускается первым и завершается; api, bot и worker стартуют после его успешного
завершения и после того, как Valkey отчитается о здоровье. Затем запустите веб-приложение, которое
обслуживает и клиентский кабинет, и операторское рабочее место:
- API —
http://localhost:8080 - Клиентский кабинет —
http://localhost:3000 - Рабочее место оператора —
http://localhost:3000/admin
make dev — это первая команда без migrate в списке аргументов, make up — всё вместе с профилем
web, а make down останавливает всё. Полный перечень целей выдаёт make help.
Создайте первого владельца
В свежей установке нет ни одной учётной записи оператора, поэтому страница входа была бы тупиком. При старте, пока ни одного оператора не существует, API выпускает одноразовый токен настройки и пишет его в собственный лог на уровне предупреждения. Токен идёт в лог, а не в HTTP-ответ, потому что в этот момент никто не может аутентифицироваться, и эндпоинт, выдающий токен, выдал бы его любому спросившему.1
Прочитайте токен из лога API
POST /v1/panel/bootstrap навсегда отвечает 409 bootstrap_closed.2
Используйте его на /admin/setup
Откройте
http://localhost:3000/admin/setup. Форма запрашивает токен настройки, отображаемое
имя длиной 1–80 символов, адрес электронной почты и пароль длиной 12–256 символов. Требований к
составу пароля нет; единственное требование — длина, и форма в браузере в точности повторяет то,
что проверяет API.Открытие /admin/login на установке, которой всё ещё нужен первый владелец, автоматически
перенаправляет сюда, а эта страница перенаправляет обратно на экран входа в тот момент, когда
учётная запись появляется, — так что забытая вкладка не может остаться на форме, которую больше
нельзя отправить.Отказ конкретен: 422 weak_password для слишком короткого пароля, 409 email_in_use для уже
зарегистрированного адреса, 409 bootstrap_closed после того, как первичная настройка завершена.3
Войдите
Вас перенаправляет на
/admin/login. Введите адрес и пароль. У учётной записи ещё нет второго
фактора, поэтому вы попадаете на дашборд по адресу /admin.Вход отвечает одинаково на неверный пароль, неизвестный адрес и отключённую учётную запись —
все три случая дают 401 invalid_credentials, — поэтому эндпоинт нельзя использовать, чтобы
выяснить, за какими адресами закреплены учётные записи операторов. Частота ограничена десятью
попытками в минуту на адрес и тридцатью в минуту на IP клиента, а если Valkey недоступен,
проверка отказывает в доступе.Включите двухфакторную аутентификацию
Первый владелец обладает всеми правами доступа в установке, включая единственную роль, которая может создавать других операторов. Дайте этой учётной записи второй фактор, прежде чем делать ею что-либо ещё.1
Начните настройку
Откройте
/admin/security и нажмите Настроить двухфакторную. В ответе приходят TOTP-секрет
и URI otpauth://. Секрет показывается и текстом, и в QR-коде, потому что аутентификатор,
работающий на том же устройстве, не может отсканировать экран, на котором он сам находится.Подпись, которую покажет ваш аутентификатор, берётся из APP_ADMIN_TOTP_ISSUER, по умолчанию
равного Omniflow.2
Подтвердите первый код
Введите шестизначный код и отправьте его. Пока код не подтверждён, секрет хранится
неподтверждённым и не удовлетворяет ни одной проверке при входе, поэтому недоделанная настройка
никогда не может заблокировать вам доступ. Неверный код отвечает
422 invalid_code;
подтверждение без начала настройки отвечает 409 totp_not_started.3
Сохраните резервные коды
Подтверждение возвращает десять одноразовых резервных кодов. Они показываются один раз и больше
никогда — перевыпуск заменяет весь набор и обесценивает каждый неиспользованный код. Поле кода
при входе принимает 6–24 символа и является текстовым, а не числовым, потому что резервный код
содержит буквы.
Убедитесь, что всё работает
Живость и готовность отвечают на разные вопросы и намеренно вынесены в отдельные эндпоинты: процесс, который работает, но не может достучаться до PostgreSQL, следует убрать из балансировщика, а не перезапускать./healthz — тот же обработчик, что и /livez, оставленный для развёртываний, которые
уже его опрашивают.
200:
503 с "status": "degraded", а отказавшая проверка несёт
"error": "timeout" или "error": "unavailable" плюс счётчик consecutiveFailures. Эти два слова —
единственные существующие значения ошибки: ошибка pgx или HTTP регулярно содержит DSN, имя хоста или
учётные данные, поэтому проба сообщает классификацию вместо неё. Проба remnawave — это
аутентифицированный вызов, а значит, отозванный токен API проявится здесь как нездоровая
зависимость, а не как загадочный сбой выдачи доступа позже.
Какие пробы регистрирует каждый процесс, различается, и это важно:
Под учётной записью оператора та же информация доступна на
/admin в разделе Система → Состояние
(GET /v1/panel/overview/health, право доступа system.read) — вместе со здоровьем платёжных
провайдеров и провайдеров цифровых товаров, которое HTTP-проба не покрывает.
Что не работает на свежем клоне
Это текущие факты оmain, а не ошибки конфигурации. Прочитайте их, прежде чем заключить, что ваша
установка сломана.
- У долговечной очереди заданий нет схемы. Omniflow ставит фоновую работу в очередь через River,
но ни одна закоммиченная миграция не создаёт собственных таблиц River, и ничто в стеке не
запускает мигратор River. Поэтому на базе, мигрированной только через
docker compose up migrate,workerзавершается при старте с записьюstart River, а любой расчёт — который вставляет задание исполнения в той же транзакции, что и деньги, — откатывается. Покупка не может завершиться, пока не появится эта миграция. О том, где именно останавливается тестовая покупка, см. Ваша первая продажа, а о том, что очередь должна делать, — Задания и очереди. - Транзакционный outbox пишется и никогда не публикуется. Вставляются три темы,
published_atникто никогда не проставляет, и диспетчера не существует. Поэтому счётчики outbox на дашборде и вGET /v1/admin/outboxрастут навсегда,APP_RETENTION_OUTBOX_DAYSне удаляет ничего, а пункт внимания «отставание outbox» на/adminожидаем, а не диагностичен. - Провайдера трассировки нет. Код открывает спаны в HTTP, обновлениях Telegram, заданиях и SQL,
но ни один экспортёр не установлен и ни одна переменная
OTEL_*нигде в репозитории не читается. Установка стандартных переменных OpenTelemetry ничего не меняет; глобальный провайдер остаётся пустышкой. То, что установка на самом деле отдаёт, — это метрики и логи, см. Наблюдаемость. - Каждый бинарник сообщает
"version":"dev". Версия не проставляется при сборке нигде, включая выпущенные образы, поэтому/livez, диагностический пакет и heartbeat телеметрии одинаково говорятdev. - Разделы настроек в панели не конфигурируют рантайм. Сохранение раздела складывает документ; подключение к Remnawave, бот, группа операторов, политика обслуживания, телеметрия, резервные копии и платёжные адаптеры берутся из переменных окружения, прочитанных при старте. См. Настройки установки.
- Упавший процесс никто не перезапускает. Ни один основной сервис Compose не объявляет политику
restart:, поэтому завершившийся процесс остаётся лежать, пока кто-нибудь не заметит. Добавьте её всему, что должно работать долго. - У вложения к обращению, загруженного из браузера, нет тома.
APP_SUPPORT_ATTACHMENT_DIRпо умолчанию равен/var/lib/omniflow/support-attachmentsи читается иapi, иworker, ноcompose.yamlне монтирует туда том ни для одного из них. Файлы живут в записываемом слое контейнера, пока его не пересоберут, а воркер не может освободить место от файлов, которых не видит.
Дальнейшие шаги
Ваша первая продажа
Создайте тариф, назначьте цену версии, настройте провайдера, подключите бота и проведите тестовую
покупку.
Справочник по конфигурации
Каждая переменная, её значение по умолчанию, какой процесс её читает и что она меняет.
Развёртывание
Тома, теги образов, миграции, обновления и поддерживаемая топология.
Обратный прокси
TLS, ограничения на размер тела и то, как держать
/metrics и /readyz вне публичного хоста.Резервное копирование и восстановление
Включите шифрованные резервные копии до того, как появится что терять.
Анонимная телеметрия
Точный состав данных и единственная переменная, которая останавливает все запросы телеметрии.