# Техническая информация о работе туннеля VPS

Эксплуатационное руководство для DevOps: что где работает, как держится туннель, как обновляются бинарники, как синхронизируются сессии и логи.

## 1. Зачем это нужно

Демоны мессенджеров (**WhatsApp = `chatsd`**, **Telegram = `tgd`**, **MAX = `maxd`**) держат постоянное соединение с серверами WhatsApp/Telegram. В сетях с DPI это соединение глушится. Поэтому демоны переносятся на **VPS в "чистой" локации**, а сама MikoPBX остается "мозгом": `gnatsd`, лицензия, 1С-интеграция, телефония и супервизор работают как раньше.

Связь между PBX и VPS - один исходящий **SSH-туннель**. Оператор включает вынос тремя тумблерами в веб-интерфейсе модуля (отдельно WhatsApp / Telegram / MAX) и указывает адрес VPS + SSH-ключ. Дальше все происходит автоматически: провижининг, поднятие туннеля, миграция сессий, зеркалирование и сбор логов.

!!!primary Главный принцип
Туннель и маршрутизация полностью скрыты внутри стека. Ни 1С, ни `gnatsd`, ни клиенты ничего не знают о VPS - для них все выглядит так, будто демон работает локально. Никаких новых портов наружу не открывается: VPS инициирует _входящие_ соединения не сам - это PBX ходит к нему по SSH.
!!!

## 2. Общая схема

<img class="img-zoomable"  
src="/assets/root-guides/transferring_to_vps/transferring_to_vps_10.png"
data-original="/assets/root-guides/transferring_to_vps/transferring_to_vps_10.png"
srcset="/assets/root-guides/transferring_to_vps/transferring_to_vps_10.png 1x, /assets/root-guides/transferring_to_vps/transferring_to_vps_10.png 2x"
alt="МИКО: Схема связи АТС с VPS"
/>

## 3. Что где работает

| Компонент | Где | Назначение |
| --- | --- | --- |
| `gnatsd-cti` (NATS `:4222` + HTTP-шлюз/лицензия `:8222`) | PBX | Шина сообщений и единственная точка входа 1С. **Никогда не переносится.** |
| `monitord` (local) | PBX | Супервизор всего стека + маршрутизатор каналов. **Владеет SSH-туннелем** (см. раздел 4). |
| `amid`, `crmd`, `authd`, `proxyd`, `speechd` | PBX | AMI, 1С-CRM, авторизация, прокси, распознавание речи. Не переносятся. |
| `chatsd` / `tgd` / `maxd` | PBX или VPS | Демоны мессенджеров. Уезжают на VPS по тумблеру (поканально-посервисно). Пока тумблер OFF - работают локально. |
| `monitord` (remote, "тонкий") | VPS | Запускает/перезапускает демоны на VPS, отдает их статус и проксирует `/chats/*`. Стартует с `daemons=[]`, слушает **только loopback** (`127.0.0.1:8225`). |
| `WorkerRemoteTunnel` (PHP-воркер) | PBX | Провижининг VPS, запуск remote-monitord, зеркало сессий, сбор логов, авто-failback. **Сам туннель не держит** - этим занят `monitord`. |

Лицензия (feature 42) выдается `gnatsd` на PBX. На VPS демоны получают ее через туннель - поэтому **standalone на VPS они не работают**, им всегда нужен живой туннель к PBX.

## 4. Туннелирование трафика

SSH-туннель **устанавливает и держит `monitord` на стороне PBX** (встроенный `ssh.Client` с авто-реконнектом и keepalive). Параметры подключения PHP-модуль рендерит в блок `ssh_tunnel` внутри `monitord.json` - при любой регенерации конфига туннель сохраняется. Прежняя схема с отдельным процессом `ssh -N` в PHP-воркере **больше не используется.**

Транспорт - обычный SSH на **порт 22** (настраивается полем `remote_ssh_port`), аутентификация - **приватным ключом**. Поверх одного соединения работают **три фиксированных форварда** - их число не зависит от количества каналов:

| Форвард | Направление | Зачем |
| --- | --- | --- |
| `-R 4222`<br/>reverse | VPS loopback -> PBX | На VPS `127.0.0.1:4222` ведет на **NATS PBX**. Демоны - NATS-клиенты, сами дозваниваются до шины. Через NATS идут пинги `monitord` и live-фид событий. |
| `-R 8222`<br/>reverse | VPS loopback -> PBX | На VPS `127.0.0.1:8222` ведет на **HTTP-шлюз/лицензию PBX**. Закрывает "вшитый" в демоны адрес проверки лицензии `127.0.0.1:8222` (feature 42). |
| `-L 8226`<br/>local | PBX -> VPS:8225 | На PBX `127.0.0.1:8226` ведет на **manager.api удаленного monitord** (его `:8225`). По нему local-monitord проксирует `/chats/*` и собирает статус каналов с VPS. |

!!!info Динамические порты каналов не туннелируются по отдельности
Каждый канал на VPS получает свой порт (`8228`, `8229`, ...). Их проксирует _внутри себя_ удаленный `monitord`, поэтому при добавлении/удалении каналов **топология туннеля не меняется** - это всегда те же 3 форварда.
!!!

### Путь запроса 1С к удаленному каналу

```text
1С -> gnatsd :8222 -> monitord local :8225 -> форвард -L :8226 -> VPS monitord :8225 -> демон на VPS :8228 -> WhatsApp/TG/MAX
```

Для 1С путь неотличим от локального: она по-прежнему обращается только к `:8222`. Решение "локально или на VPS" `monitord` принимает по метке `location` канала.

## 5. Справочник портов

| Порт | Хост | Доступность | Что это |
| --- | --- | --- | --- |
| `22` | VPS | входящий SSH (только от PBX) | Транспорт туннеля. Настраивается (`remote_ssh_port`). |
| `4222` | PBX | loopback + reverse-форвард | NATS / шина сообщений. |
| `8222` | PBX | открыт в firewall (вход 1С) + reverse-форвард | HTTP-шлюз `gnatsd` + лицензия. **Единственная точка входа 1С.** |
| `8225` | PBX и VPS | только loopback | `manager.api` монитора (статус, маршрутизация, `/chats/*`). На VPS забинден на `127.0.0.1` - наружу не торчит. |
| `8226` | PBX | только loopback | Local-форвард на `:8225` удаленного `monitord`. **Наличие LISTEN на 8226 = туннель сконфигурирован.** |
| `8228+` | VPS | внутри VPS | Динамические порты каналов. Проксируются remote-monitord, отдельных форвардов не требуют. |

## 6. Обновление бинарников на VPS

Бинарники на VPS - **те же linux/amd64-файлы, что и на PBX** (пересборки нет). Провижининг кладет их в `{base}/bin/` (где `{base}` = `remote_bin_dir`, по умолчанию `/opt/mikopbx-cti`) вместе со сгенерированными конфигами в `{base}/conf/`.

### Как обновление "доезжает" до VPS

- В `{base}/bin/.version` хранится **штамп версии модуля**, развернутой на VPS.
- При апгрейде модуля локальные бинарники заменяются. Воркер сравнивает локальную версию со штампом на VPS; **при расхождении - принудительный re-push** (без расхождения сверяется только размер файла, лишний трафик не гоняется).
- Заливка идет **через temp-файл + rename** - чтобы перезапись работающего бинарника не уперлась в `ETXTBSY`.
- После того как новые бинарники легли, затронутые демоны на VPS **перезапускаются** (полный рестарт remote-monitord либо `pkill` конкретных дочерних) - иначе на VPS продолжил бы крутиться старый код.
- Штамп `.version` пишется **только после полного успешного провижининга** - если апгрейд оборвался посередине, на следующем тике он повторится.

!!!info Почему не rsync
Перенос файлов сделан через `scp`/tar-over-ssh намеренно: чтобы не поднимать минимальную требуемую версию ядра MikoPBX (`rsync` есть не везде).
!!!

## 7. Синхронизация сессий (авторизация)

Вся авторизация мессенджера лежит в **файлах сессии** и **переживает перенос между хостами и смену IP/гео без повторной авторизации** (проверено round-trip-тестом):

| Сервис | Файл авторизации | Каталог |
| --- | --- | --- |
| WhatsApp | `<area>-whatsappSession.db` (SQLite) | `{base}/db/chats/` |
| Telegram | `<area>-tgSession.json` | `{base}/db/tg/` |
| MAX | `<area>-max_session.json` | `{base}/db/max/` |

### Миграция (по тумблеру)

При включении/выключении выноса сессия копируется в нужную сторону:

```text
стоп источника -> tar-over-ssh пофайлово по area (<area>-*) + сверка sha256 -> старт приемника -> флип метки location
```

**Жесткое правило:** один и тот же канал **никогда** не запускается одновременно на обеих сторонах - это разлогинило бы сессию.

### Теплое зеркало (постоянно)

Пока канал на VPS, воркер **периодически копирует сессию VPS -> PBX**. Локальная копия всегда наготове.

Зачем: если VPS внезапно пропал, авторизация **не теряется** - ее свежая копия уже лежит на PBX, и сервис можно поднять локально без повторного сканирования QR.

## 8. Синхронизация логов

Демоны на VPS пишут логи в `{base}/logs/<service>/` - локально на PBX их не видно, и штатный просмотр **System -> Logs** их бы не показал. Поэтому воркер **инкрементально подкачивает** их на PBX.

- **Инкрементально по offset** - тянется только "хвост" файла (новые байты), а не весь лог. Экономия трафика через туннель.
- **Куда:** `logDir/ModuleCTIClient/<service>-<host>/`, где `<host>` - это `remote_host` (IP/имя VPS, очищенное до `[A-Za-z0-9._-]`). Отдельная папка с именем хоста **исключает коллизию** с локальным логом того же сервиса и сразу показывает источник.
- **Условие закачки:** канал реально на VPS (`side == remote`) **и** туннель `connected`. Каденция ~60 с (реже, чем зеркало сессий).
- **Видимость "бесплатно":** System -> Logs сканирует `logDir` рекурсивно, поэтому подкачанные файлы появляются в списке и доступны на просмотр/скачивание **без доработки ядра**.
- Локальный накопительный файл ротируется по размеру; штатная 7-дневная чистка убирает старье.

## 9. Поведение при потере VPS

| Что отказало | Что происходит |
| --- | --- |
| VPS / туннель недоступны | **Локальная телефония, CRM и не-вынесенные мессенджеры не страдают.** По вынесенным каналам приостанавливаются и отправка, и прием (data-plane идет по HTTP через туннель): исходящие из 1С падают по таймауту. |
| Входящие сообщения во время простоя | Не теряются: WhatsApp/Telegram держат бэклог у себя; демон на VPS вытянет пропущенное после реконнекта, 1С увидит это при следующем поллинге. |
| Данные авторизации | В безопасности - теплое зеркало (раздел 7) держит свежую копию сессии на PBX. |
| Долгий простой VPS | Предусмотрен авто-failback на локаль по таймауту (`remote_failback_after_sec`, по умолчанию 7200 с) - поднимает сервис из локальной копии сессии. **Часть фенсинга - owner-lock на VPS - на момент написания дорабатывается.** |

!!!warning Не делать ручной "фейловер", пока VPS жив
Запуск того же канала на PBX при работающем канале на VPS = две живые сессии = разлогин. Переключение на локаль - это **осознанный хэндовер при доступном VPS** (через тумблер/миграцию), а не аварийное действие.
!!!

## 10. Эксплуатация и диагностика

### Проверки на PBX

```bash
# Жив ли супервизор (он же - владелец туннеля)
pgrep -a monitord

# Статус туннеля (configured/connected/last_ok_ts/attempts)
curl -s http://127.0.0.1:8225/manager.api/tunnel/status

# Local-форвард на удаленный monitord должен слушать - признак, что туннель сконфигурирован
ss -tlnp | grep 127.0.0.1:8226

# Сводный статус всех каналов (как его видит 1С): local + remote вместе
curl -s http://127.0.0.1:8222/manager.api/status
```

### Как выглядит "здоровый" туннель

```json
{
  "result": {
    "configured": true,
    "connected": true,
    "state": "connected",
    "last_ok_ts": 1781677831,
    "last_error": "",
    "attempts": 1
  }
}
```

### На что смотреть при разборе инцидента

- `connected:false` + растущий `attempts` -> SSH до VPS не встает: проверить сеть/firewall до VPS `:22`, ключ, что VPS жив.
- Туннель `connected`, но канал в `error` -> демон на VPS падает: смотреть подкачанный лог `logDir/ModuleCTIClient/<service>-<host>/` (System -> Logs).
- Канал в состоянии `qrcode` -> нужна (повторная) авторизация: QR доступен прямо в UI модуля.
- После апгрейда модуля канал на старом поведении -> проверить, что `{base}/bin/.version` на VPS совпал с версией модуля (иначе re-push не прошел - см. раздел 6).
