От установки до первого звонка

Установленный стек ещё никому не звонит: в системе нет ни одного телефона. Эта страница доводит свежую инсталляцию до звонка с телефона на телефон и (если у вас есть свой транк) звонка наружу и снаружи. Каждый шаг заканчивается строкой «что должно быть видно»: если её нет, дальше идти бессмысленно — причина будет накапливаться.

Как поставить платформу, описано на главной странице витрины и в INSTALL.md, который лежит рядом с инсталляцией на диске. Здесь установка не повторяется. Из чего платформа состоит и как проходит звонок — общие сведения; частые проблемы, в том числе блокировка собственного адреса, — отдельная страница.

Почему именно звонок. Платформа обрабатывает обращения не только по телефону: текстовые каналы — мессенджеры и чаты — работают в том же ядре и видны в той же панели, доустанавливать для них нечего (аккаунт провайдера подключается в разделе «Чаты → Провайдеры чатов»). Но сквозную проверку быстрее всего даёт звонок: он разом поднимает SIP-фронт, медиа-тракт, оркестрацию, запись и историю обращений — то есть почти весь стек, на котором потом работают остальные каналы.

0. Что нужно до начала

Что Подробности
Сервер VM с публичным IP и установленной платформой. Требования к CPU/RAM/диску — раздел «Перед установкой» на главной витрины
Панель компонент ui (юнит web) — через неё смотрится результат. Что поднято — ./omniflow-ctl ps: в таблице должен быть юнит web
Софтфон Windows — MicroSIP; Linux, macOS, телефон — Linphone. Подойдёт любой SIP-клиент, поддерживающий UDP-регистрацию
Открытые порты Их открывает не платформа, а ваше облако или роутер

Минимум портов именно для этой страницы (полный список с пояснениями — в панели, раздел «Телефония → Подключение и система», блок «Что открыть снаружи»):

Порт Протокол Зачем
5060 udp + tcp регистрация и звонки телефонов
30000-30500 udp голос. Без диапазона звонок соединяется, но звука нет
443 tcp панель управления
5080 udp + tcp транки провайдеров — только для шага 3

Порт 5080 не публикуется автоматически на уровне облака: в списке firewall он стоит отдельной строкой именно потому, что его чаще всего забывают.

Что должно быть видно. ./omniflow-ctl verify — семь проверок подряд без [ FAIL ]:

./omniflow-ctl verify
  [ OK ]  контейнеры — N, одноразовые завершены с кодом 0
  [ OK ]  образы из реестра — все из registry.omniflow.ru
  [ OK ]  схема базы данных — актуальна
  [ OK ]  конфигурация SIP-фронта — …
  [ OK ]  панель — https://<ваш-домен>/ → 200
  [ OK ]  вход администратора — admin@system
  [ OK ]  здоровье сервисов — 6 сервисов, все живы
  [ OK ]  verify: выполнено

    →     Платформа установлена. Дальше: ./omniflow-ctl sipuser add <логин> --tenant <тенант> — завести первую SIP-точку (тенанты: ./omniflow-ctl tenant list)
  traceId: …

Число контейнеров зависит от набора установленных компонентов — сверять его с чужой инсталляцией не нужно. Красная строка здесь — это причина, а не симптом: чините её до первого звонка. Подробности даёт ./omniflow-ctl doctor, логи конкретного сервиса — ./omniflow-ctl logs <сервис> --since 10m.

Вход в панель: https://<ваш-домен>/, поля «Логин» — admin, «Пароль» — из установки, «Tenant» — оставьте system (подсказка под полем говорит то же самое).

1. Телефон звонит телефону

Самая полезная проверка: один звонок разом поднимает SIP-фронт, медиа, оркестрацию и запись.

1.1. Завести две линии

./omniflow-ctl sipuser add 101 --tenant system --comment "рабочее место 1"
./omniflow-ctl sipuser add 102 --tenant system --comment "рабочее место 2"

--tenant — обязателен: это организация, которой принадлежит линия, и одновременно её SIP-домен. На одиночной инсталляции организация одна — system. Чтобы не повторять флаг в каждой команде: export OMNIFLOW_CTL_TENANT=system.

Что должно быть видно (пароль печатается один раз — сохраните его):

  тенант: system (из --tenant)
  точка 101 создана (домен system)
  [ OK ]  sipuser add: выполнено

    →     Софтфон: сервер 203.0.113.10:5060 (UDP), домен system, логин 101, пароль ••••••••
    →     Регистрация: ./omniflow-ctl sipuser list --online
  traceId: …

На месте •••••••• команда печатает настоящий пароль — здесь он скрыт, потому что страница публичная. Адрес и порт у вас будут свои: подставляется EXTERNAL_IP из .env инсталляции.

Если пароль потерян — не заводите точку заново: ./omniflow-ctl sipuser password 101 выдаёт новый, а в панели («Телефония → SIP-пользователи», карандаш в строке) поле «Пароль» показывает текущий. Без панели текущий пароль печатает ./omniflow-ctl sipuser show 101 --tenant system --reveal.

То же самое делается в панели: «Телефония → SIP-пользователи» → «Добавить», поля «Логин (username)», «Номер телефона», «Пароль». Цель точки по умолчанию — «Все контуры», менять её на одиночной инсталляции не нужно.

1.2. Подключить софтфоны

В софтфоне заполняются три вещи из подсказки выше:

Поле софтфона Что вписывать
Сервер / SIP Server / Domain Proxy внешний IP платформы и порт 5060, транспорт UDP
Домен / Domain / Realm код организации — при установке по умолчанию system
Логин и пароль 101 и выданный пароль

Домен — не адрес сервера. Платформа проверяет подлинность пароля по паре «логин + домен», и домен здесь равен коду организации, которой принадлежит линия. Вписали туда IP или значение SIP_DOMAIN из .env — пароль перестанет сходиться, и телефон получит 403 при верном пароле. Домен каждой линии виден в панели в таблице «Телефония → SIP-пользователи» — отдельной колонкой рядом с логином.

Что должно быть видно. Оба софтфона показывают успешную регистрацию, и платформа это подтверждает:

./omniflow-ctl sipuser list --online
  101              system           online  рабочее место 1
  102              system           online  рабочее место 2

В панели то же самое — колонка «Регистрация» у обеих строк показывает контур, на котором телефон зарегистрирован. Серая метка «Offline» (телефон не дошёл или не прошёл проверку пароля) и прочерк «—» (настройка линии ещё не применена ни на одном контуре) — переходите к разделу 3.1, звонить пока нечему.

1.3. Позвонить

Наберите 102 с первого софтфона. Маршрут для этого заводить не нужно: номер, совпадающий с логином зарегистрированной линии, платформа набирает напрямую.

Что должно быть видно — в панели, раздел «История звонков»:

Состояние самих сервисов — раздел «Здоровье сервисов» или ./omniflow-ctl status: у каждого сервиса должен быть хотя бы один живой экземпляр.

2. Звонок наружу и снаружи (опционально)

Этот шаг нужен, только если у вас есть свой SIP-транк у оператора связи. Без транка платформа полностью работоспособна внутри — шаг можно пропустить и вернуться к нему позже.

2.1. Завести транк

Панель: «Телефония → Транки» → «Добавить». «Тип подключения» — то, как провайдер вас узнаёт:

Тип Когда Что заполняется
Регистрация (uac_reg) провайдер выдал логин и пароль «Сервер», «SIP-домен», «Логин», «Пароль»; при необходимости «Дополнительно → Realm»
По IP (без пароля) провайдер узнаёт вас по адресу сервера «IP провайдера» (только адрес, не имя) и при необходимости «Порт (для исходящих, nexthop)»

Транк с регистрацией заводится только в панели. В справке ./omniflow-ctl help есть форма trunk add --type registration … — не пользуйтесь ею: она передаёт только реквизиты авторизации и не заполняет локальные логин и домен, без которых платформа не проецирует транк в таблицу регистраций. Транк при этом создастся, ошибки не будет, а статус навсегда останется UNKNOWN — REGISTER просто не уйдёт. Для транка «по IP» консольная команда подходит полностью:

./omniflow-ctl trunk add --type ip --name "Провайдер" --code provider --host 203.0.113.50

Поле «Realm» нужно, когда провайдер запрашивает авторизацию не тем доменом, который вы указали (так делают, например, крупные операторские платформы). Неверный realm — гарантированный 403, сколько бы раз вы ни проверяли пароль.

2.2. Дождаться регистрации

./omniflow-ctl trunk status provider
Статус в консоли Как подписан в панели Что означает
AUTH_DONE «OK» в таблице транков, «Зарегистрирован» в карточке провайдер принял регистрацию
AUTH_SENT «Регистрация…» / «Ожидание ответа» запрос отправлен, ответа пока нет — подождите
FAILED «FAIL» / «Ошибка регистрации» отказ: realm, пароль, DNS или недоступность провайдера. Текст причины — в поле err
UNKNOWN «N/A» / «Неизвестно» данных о регистрации нет. Нормально для транка «по IP»; для транка с регистрацией — признак того, что REGISTER не отправляется

Команда возвращает код выхода 1, если транк в FAILED или не готов принимать входящие, — это удобно в скриптах. В панели это та же величина, но подписана она короче — соответствие в таблице выше. Искать на экране слова AUTH_DONE или UNKNOWN бесполезно.

Зелёный статус ещё не значит «до вас дозвонятся». AUTH_DONE говорит только то, что провайдер принял регистрацию; какой адрес он при этом запомнил, видно лишь по реальному входящему звонку. Проверка одна — позвонить в обе стороны.

2.3. Исходящее правило

Панель: «Телефония → Маршрутизация» → «Добавить», направление «Исходящие», действие «Транк», «Цель действия» — код транка. При действии «Транк» появляется обязательное поле «SBC-контур» — выберите контур, на котором живёт транк.

Паттерны описывают ваш план набора: «To-паттерн (набранный номер)» 8XXXXXXXXXX означает «восьмёрка и десять любых цифр» (X = любая цифра). Если провайдер ждёт номер в другом формате, приведите его полем «Модификация To»: T в нём — исходный номер, то есть 8T добавит восьмёрку спереди.

Что должно быть видно. Звонок с 101 на внешний номер проходит, а в «Истории звонков» появляется строка с направлением «Исх», заполненной колонкой «Транк» и ненулевым «Разговор».

2.4. Входящий номер

./omniflow-ctl route add --did 74950000000 --to sipuser:101

Что должно быть видно:

  маршрут 74950000000 → sipuser:101 создан (id …, контур …)
  [ OK ]  route add: выполнено

    →     Проверить резолв: ./omniflow-ctl bus req q.callroute.test '{"direction":"inbound","fromNumber":"79990000000","toNumber":"74950000000"}'
  traceId: …

Номер в --did должен совпадать с тем, что провайдер реально присылает в вызове, — цифра в цифру. Если он шлёт номер в другом формате (с +, без кода города, с префиксом), правило не совпадёт, и в журнале звонка появится факт «Маршрут не найден». Команда bus req q.callroute.test из подсказки проверяет это без реального звонка.

Позвоните на свой номер снаружи — должен зазвонить софтфон 101, а в «Истории звонков» появиться строка с направлением «Вх».

3. Если не работает

Порядок разбора всегда один: ./omniflow-ctl doctor (полная диагностика установки) → ./omniflow-ctl status (что поднято и живо) → ./omniflow-ctl logs <сервис> --since 10m → панель. Не начинайте с логов: большинство отказов первого дня — это закрытый порт или неверный домен, и они видны раньше.

Блокировка адреса защитой от перебора паролей — признаки, точная проверка в панели и консоли, снятие — разобрана на странице частые проблемы.

3.1. Телефон не регистрируется

Симптом Причина Проверка Что должно быть видно
«Registration failed» или таймаут, в панели точка offline Закрыт 5060 на периметре — в облаке или на роутере Панель: «Подключение и система» → «Что открыть снаружи», а ниже — блок «Проверки». Пометка «снаружи» у проверок периметра не ошибка: сервер физически не может проверить, доходит ли до него трафик После открытия порта ./omniflow-ctl sipuser list --online показывает точку как online
403 при заведомо верном пароле В софтфоне в поле домена/realm вписан адрес сервера вместо кода организации Панель: «Телефония → SIP-пользователи», колонка с доменом точки В софтфоне домен = код организации (по умолчанию system), после чего регистрация проходит
Регистрация то появляется, то пропадает; звонки рвутся EXTERNAL_IP в .env не тот адрес, по которому вас видят снаружи ./omniflow-ctl doctor — шаг сверки внешнего адреса с фактическим Значение совпадает с фактическим внешним адресом; расхождение доктор называет прямо
Телефон «умер» молча: запросы уходят, ответа нет вовсе — и у соседних телефонов той же сети тоже Сработала защита от перебора паролей: пять неверных паролей с одного адреса — и он блокируется без ответа. Классический источник — один забытый аппарат со старым паролем ./omniflow-ctl logs kamailio --since 10m; панель: «Телефония → Безопасность» В панели видна блокировка вашего адреса и кнопка её снятия; в логе — строки о неверном пароле и о бане адреса. Блокировка снимается и сама — через 5 минут после её установки, и повторные попытки софтфона её не продлевают; вернулась снова — ищите аппарат со старым паролем, снимать её вручную бессмысленно: повторяющиеся серии платформа отдаёт сетевому фильтру, и он закрывает адрес уже на час

3.2. Звонок идёт, звука нет

Симптом Причина Проверка Что должно быть видно
Ответили, тишина в обе стороны, обрыв примерно через 30 секунд Закрыт диапазон 30000-30500/udp Панель: «Подключение и система» → «Что открыть снаружи» Диапазон открыт в облаке; после этого «Разговор» в истории звонков перестаёт быть нулевым
Сигнализация в порядке, «Разговор» 0–1 с при статусе «Отвечен» Медиа-прокси держит устаревший внешний адрес: он фиксируется в момент запуска контейнера и не меняется от рестарта Сравните EXTERNAL_IP в .env с аргументами запущенного контейнера медиа-прокси После ./omniflow-ctl restart rtpe-1 (контейнер пересоздаётся и перечитывает .env) адреса совпадают, разговор слышен
«Пришёл 200 OK, значит звонок прошёл» Ложный вывод: сигнализация и голос идут разными путями Всегда смотрите колонку «Разговор» в истории звонков, а не факт ответа Разговор длится столько же, сколько вы говорили

3.3. Транк не поднимается

Симптом Причина Проверка Что должно быть видно
FAILED, в err — «Нет успешного REGISTER» Неверный realm, пароль, DNS-имя провайдера или он недоступен ./omniflow-ctl trunk status <код>, затем ./omniflow-ctl logs kamailio --since 10m Статус переходит в AUTH_DONE; в логе исчезают отказы авторизации
В логе «realms do not match» и 403 Провайдер запрашивает авторизацию другим realm, чем указан в транке Поле «Дополнительно → Realm» в карточке транка После указания realm провайдера — AUTH_DONE
UNKNOWN часами, при этом ошибок нет, входящие «готовы» Для транка с регистрацией это значит, что REGISTER не отправляется — чаще всего не заполнены поля локальной регистрации (шаг 2.1) Откройте карточку транка в панели и проверьте «Логин» и «SIP-домен» Статус меняется на AUTH_SENT, затем AUTH_DONE
Провайдер шлёт звонок, а на платформе не происходит ничего — даже отказа На транковом порту неопознанный источник отбрасывается молча, без ответа Убедитесь, что 5080 открыт и что адрес провайдера совпадает с тем, что указан в транке Входящий появляется в «Истории звонков» с направлением «Вх»
Входящий дошёл, но никуда не поехал Нет подходящего правила: номер в вызове не совпадает с --did Журнал звонка в карточке и ./omniflow-ctl bus req q.callroute.test … из подсказки шага 2.4 В журнале вместо «Маршрут не найден» — «Маршрут», и звонит нужная линия

Что приложить к обращению

Если разбор не помог, соберите три вещи: вывод ./omniflow-ctl status (версия и состав), вывод ./omniflow-ctl doctor и идентификатор проблемного звонка. Идентификатор печатается последней строкой (traceId: …) у команд, работающих с платформой, а в панели он виден в карточке звонка в режиме «Подробно» — строки «Chain:» и «Trace:» с кнопкой копирования. По одному этому идентификатору звонок разбирается целиком. Обращаться — по тому же контакту, по которому вы получили доступ к реестру образов.