Jitsi Meet docker-compose for Coolify (stable-11248)
This commit is contained in:
122
README.md
122
README.md
@@ -1,78 +1,86 @@
|
||||
# crm-calls
|
||||
|
||||
Сервис звонков для CRM (Tvorymo Soft): Jitsi Meet на базе
|
||||
[docker-jitsi-meet](https://github.com/jitsi/docker-jitsi-meet) `stable-11248`
|
||||
(образы `ghcr.io/jitsi/{web,prosody,jicofo,jvb}`), разворачивается в Coolify
|
||||
(сервер storage) как docker-compose приложение.
|
||||
Jitsi Meet для Tvorymo CRM: https://crm-calls.tes.gd
|
||||
|
||||
- URL: https://crm-calls.tes.gd
|
||||
- Coolify: проект `crm-calls`, приложение `crm-calls` (uuid в `deploy.json`, он в .gitignore)
|
||||
Розгортання: Coolify (сервер `storage`, 192.168.50.73), застосунок `crm-calls`, build pack `dockercompose`,
|
||||
файл `docker-compose.yml`. Основа: офіційний [docker-jitsi-meet](https://github.com/jitsi/docker-jitsi-meet), образи `stable-11248`.
|
||||
|
||||
## Сеть
|
||||
## Сервіси
|
||||
|
||||
| Что | Порт | Путь |
|
||||
|---|---|---|
|
||||
| Веб, BOSH, XMPP-websocket | TCP 443 | VPS 46.101.119.200 → storage Traefik → `web:8000` |
|
||||
| Медиа JVB (звук/видео + bridge channel по SCTP) | UDP 10000 | напрямую на хост storage (192.168.50.73), мимо Traefik |
|
||||
| Сервіс | Що робить | Як доступний ззовні |
|
||||
|---------|-----------------------------------|---------------------|
|
||||
| web | nginx + веб-застосунок Jitsi | HTTPS 443 через Traefik (Coolify) → `web:8000` |
|
||||
| prosody | XMPP-сервер | лише `wss://crm-calls.tes.gd/xmpp-websocket` (проксі через web) |
|
||||
| jicofo | фокус конференцій | ззовні не доступний |
|
||||
| jvb | відеоміст (медіа) | **UDP 10000 напряму**, повз Traefik |
|
||||
|
||||
В текущих версиях Jitsi bridge channel идёт через SCTP data channel внутри
|
||||
медиа-соединения, отдельный colibri-websocket не нужен — достаточно 443 + UDP 10000.
|
||||
Colibri-websocket у цій версії Jitsi не використовується: канал «клієнт ↔ JVB» іде через SCTP
|
||||
усередині того самого медіа-з'єднання (UDP 10000). Тому через 443 ходять лише веб і XMPP.
|
||||
|
||||
### Media / UDP — внешняя зависимость
|
||||
## Змінні оточення (Coolify)
|
||||
|
||||
storage стоит за NAT Netia; снаружи сейчас доходят только TCP 80/443 через VPS.
|
||||
Пока UDP 10000 не проброшен, веб открывается и в комнату можно зайти, но звук/видео
|
||||
между участниками из интернета не пойдут (в офисной LAN — пойдут, через 192.168.50.73).
|
||||
Секрети задаються **лише** в env застосунку в Coolify, у репозиторії їх немає:
|
||||
|
||||
Варианты (делает админ сети):
|
||||
- `JICOFO_AUTH_PASSWORD` — пароль jicofo у prosody
|
||||
- `JVB_AUTH_PASSWORD` — пароль jvb у prosody
|
||||
|
||||
1. **Проброс на роутере Netia** `195.128.172.198:10000/udp → 192.168.50.73:10000/udp`.
|
||||
Затем `JVB_ADVERTISE_IPS=192.168.50.73,195.128.172.198`.
|
||||
2. **UDP-форвард через VPS** `46.101.119.200:10000/udp → storage:10000/udp`
|
||||
(по тому же туннелю, что и 80/443). Ответы должны уходить обратно через VPS
|
||||
(SNAT/MASQUERADE или туннель), иначе клиенты получат пакеты с IP Netia и ICE не сойдётся.
|
||||
`JVB_ADVERTISE_IPS=192.168.50.73,46.101.119.200` (значение по умолчанию).
|
||||
Необов'язкові (є значення за замовчуванням у compose):
|
||||
|
||||
Менять: Coolify → приложение → Environment Variables → `JVB_ADVERTISE_IPS` / `JVB_PORT` → Redeploy.
|
||||
При смене `JVB_PORT` проброс должен вести на тот же порт.
|
||||
- `PUBLIC_URL` (`https://crm-calls.tes.gd`)
|
||||
- `JVB_ADVERTISE_IPS` (`46.101.119.200,192.168.50.73`)
|
||||
- `TZ` (`Europe/Kyiv`), `DEFAULT_LANGUAGE` (`uk`), `JITSI_IMAGE_VERSION` (`stable-11248`)
|
||||
|
||||
Проверка с внешней машины после проброса: создать комнату с двух устройств из разных
|
||||
сетей; в `jvb` логах должно появиться `ICE connected`/`Selected pair`.
|
||||
## Мережа: що треба пробросити
|
||||
|
||||
### TURN (опционально)
|
||||
Публічна адреса `46.101.119.200`, сервер `storage` — `192.168.50.73` у внутрішній мережі.
|
||||
|
||||
В prosody уже прокинуты `TURN_HOST`, `TURN_PORT`, `TURN_TRANSPORT`, `TURNS_HOST`,
|
||||
`TURNS_PORT`, `TURN_CREDENTIALS` — достаточно поднять coturn (3478 udp/tcp, 5349 tls)
|
||||
и задать переменные. coturn требует тех же входящих портов, что сейчас закрыты,
|
||||
поэтому без админа сети он тоже не поможет — кроме варианта TURNS на 443 через
|
||||
SNI-маршрутизацию Traefik (отдельный хостнейм, TCP-роутер с TLS passthrough).
|
||||
| Звідки (зовні) | Куди | Протокол | Навіщо |
|
||||
|------------------------------|----------------------------|----------|--------|
|
||||
| `46.101.119.200:10000` | `192.168.50.73:10000` | **UDP** | медіа JVB (обов'язково) |
|
||||
| `46.101.119.200:80, 443` | `192.168.50.73:80, 443` | TCP | вже працює (Traefik) |
|
||||
|
||||
## Встраивание в crm-wiki / CRM (iframe)
|
||||
Також на самому `storage` має бути відкритий вхідний UDP 10000 (якщо там є ufw/iptables;
|
||||
порт, опублікований Docker, зазвичай проходить повз ufw).
|
||||
|
||||
- `CSP_HEADER` по умолчанию: `frame-ancestors 'self' https://wiki-crm.tes.gd https://*.tes.gd`
|
||||
(nginx в контейнере web). X-Frame-Options не выставляется.
|
||||
- На стороне родителя: `<iframe allow="camera; microphone; display-capture; autoplay; clipboard-write; fullscreen">`
|
||||
или `external_api.js` (`https://crm-calls.tes.gd/external_api.js`, `new JitsiMeetExternalAPI(...)`).
|
||||
Перевірка після прокидання (з машини поза мережею):
|
||||
|
||||
### JWT-авторизация (когда понадобится)
|
||||
|
||||
Переменные уже прокинуты в web/prosody/jicofo:
|
||||
|
||||
```
|
||||
ENABLE_AUTH=1
|
||||
AUTH_TYPE=jwt
|
||||
JWT_APP_ID=crm-calls
|
||||
JWT_APP_SECRET=<общий секрет HS256 с бэкендом CRM/wiki>
|
||||
JWT_ACCEPTED_ISSUERS=crm,crm-wiki
|
||||
JWT_ACCEPTED_AUDIENCES=crm-calls
|
||||
ENABLE_GUESTS=0 # 1 — пускать гостей без токена в уже созданные комнаты
|
||||
```sh
|
||||
# на storage:
|
||||
sudo tcpdump -ni any udp port 10000
|
||||
# ззовні:
|
||||
echo test | nc -u -w1 46.101.119.200 10000
|
||||
```
|
||||
|
||||
Бэкенд CRM подписывает токен (`iss`, `aud`, `sub=crm-calls.tes.gd` или `*`, `room`, `context.user`)
|
||||
и передаёт его в iframe (`?jwt=...` или `jwt` в `JitsiMeetExternalAPI`); токен можно
|
||||
получить родителем и передать через postMessage → JS в странице хоста создаёт API с ним.
|
||||
У tcpdump має з'явитися пакет. Під час дзвінка в `chrome://webrtc-internals` вибрана
|
||||
ICE-пара має бути з віддаленою адресою `46.101.119.200:10000`.
|
||||
|
||||
## Секреты
|
||||
Без UDP 10000 сторінка й кімната відкриваються, але дзвінок з 3+ учасниками (через JVB) не матиме
|
||||
звуку/відео. Дзвінок удвох може працювати в режимі P2P (напряму між браузерами через STUN),
|
||||
але не за суворим NAT/корпоративним файрволом — для цього потрібен TURN.
|
||||
|
||||
`JICOFO_AUTH_PASSWORD`, `JVB_AUTH_PASSWORD` задаются только в Coolify env vars (внутренние
|
||||
XMPP-пароли компонентов). Деплой-конфиг — `deploy.json` (не в git).
|
||||
## TURN (на майбутнє)
|
||||
|
||||
Потрібен для клієнтів, у яких UDP заблоковано (корпоративні мережі, частина мобільних операторів).
|
||||
|
||||
1. Додати сервіс `coturn` (наприклад `coturn/coturn`) у compose або окремим застосунком у Coolify,
|
||||
`network_mode: host` або опублікувати порти.
|
||||
2. Пробросити на роутері до `192.168.50.73`:
|
||||
- `3478` UDP і TCP (TURN/STUN),
|
||||
- `5349` TCP (TURNS/TLS) — або краще TURNS на 443 окремої IP/піддомену, бо 443 вже зайнятий Traefik,
|
||||
- діапазон relay-портів, напр. `49160-49200` UDP (задається в `min-port`/`max-port` coturn).
|
||||
3. coturn: `external-ip=46.101.119.200/192.168.50.73`, `realm=crm-calls.tes.gd`,
|
||||
`use-auth-secret`, `static-auth-secret=<секрет у Coolify env>`, TLS-сертифікат для домену
|
||||
TURN (напр. `turn.tes.gd`) для 5349.
|
||||
4. Jitsi: задати в env prosody `TURN_HOST=turn.tes.gd`, `TURN_PORT=3478`, `TURNS_HOST=turn.tes.gd`,
|
||||
`TURNS_PORT=5349`, `TURN_CREDENTIALS=<той самий секрет>`, `TURN_TRANSPORT=udp,tcp`
|
||||
(prosody через `mod_external_services` роздає клієнтам тимчасові TURN-облікові дані).
|
||||
|
||||
## Вбудовування (iframe) у вікі / CRM
|
||||
|
||||
- Jitsi nginx не ставить `X-Frame-Options`; framing задається через
|
||||
`Content-Security-Policy: frame-ancestors 'self' https://*.tes.gd https://test.units.tvorymo.com`
|
||||
(змінна `CSP_HEADER` у compose, сервіс `web`). Щоб додати домен — дописати його туди.
|
||||
- Вбудовувати через `https://crm-calls.tes.gd/external_api.js` (`JitsiMeetExternalAPI`), iframe має
|
||||
мати `allow="camera; microphone; display-capture; autoplay; clipboard-write; fullscreen"`.
|
||||
- Авторизація (postMessage → JWT) поки не налаштована: кімнати відкриті для всіх, хто знає URL.
|
||||
Для CRM планується `ENABLE_AUTH=1`, `AUTH_TYPE=jwt`, `JWT_APP_ID`, `JWT_APP_SECRET` (секрет — лише в Coolify).
|
||||
|
||||
Reference in New Issue
Block a user