Введение в круг понятий. UNIX/Linux  
  Мессенджеры - пока заметки про развёртывание Synapse, Element и т.п.  


Эти материалы являются объектом авторского права и защищены законами РФ и международными соглашениями о защите авторских прав. Перед использованием материалов вы обязаны принять условия лицензионного договора на использование этих материалов, или же вы не имеете права использовать настоящие материалы

Авторская площадка "Наши орбиты" состоит из ряда тематических подразделов, являющихся моими лабораторными дневниками, содержащими записи за разное, иногда продолжительно отличающееся, время. Эти материалы призваны рассказать о прошедшем опыте, они никого ни к чему не призывают и совершенно не обязательно могут быть применимы кем-то ещё. Это только лишь истории о прошлом


01. Обзор содержимого


Исторически первый работавший вариант
Делаем сервер "для себя" из репозитррия Аль Linux p.11. Малая группа, самоподписанный сертификат
Как включить федерацию - первый подход
Как окончательно включить федерацию
Первый "обзор поляны" Element Call из кустов неведения
Теоретическая картина мира с Element Call
Пример практического конфигурирования Element Call

02. Исторически первый работавший вариант

Мессенджеры, которые мы можем сконфигурировать для себя, вошли в нашу жизнь давно. В первую очередь это, конечно, Jabber (XMPP). Который замечательно заменил централизованную "аську", но тут же уступил тем централизованным сервисам, которые предоставляли аудио и видеосвязь. Ну не умеет джаббер в VoIP по нормальному. Долгое время альтернатив не было, пока не появился стандарт Matrix, который так и не стал стандартом де юре, но стали им фактически. А также эталонные реализации сервера matrix - Synapse, и клиента - Element. А также ряда других клиентов и серверов. Сбоку к этому майнстримовому решению подползают и различные федерированные сервисы, типа Мастодонта, Плеромы и т.п., но здесь хватит сил расписать только опыты по развёртывапнию Matrix

1. развёрнут пакет синапса из репозитария

2. сразу не стартовал, конфиг файл скопировал, пробовал по полученным ошибкам через pip обновлять компоненты Питона - не взлетело

3. пошёл в утилиты, сгенерировал все файлы и стартовал сервер, после чего добавил имена в DNS и пересоздал файлы конфигурации, сервер взлетел

---
/usr/lib/matrix-synapse/generate_config --config-dir /etc/synapse --data-dir /opt/synapse \
   --server-name [FQDN_нашего_сервера] --report-stats yes --generate-secrets > /etc/synapse/homeserver.yaml
/usr/lib/matrix-synapse/generate_log_config -o /etc/synapse/log_config.yaml -f /opt/synapse/my_logfile.log
/usr/lib/matrix-synapse/generate_signing_key.py -o /etc/synapse/[FQDN_нашего_сервера].signing.key
/usr/lib/matrix-synapse/generate_log_config -o /etc/synapse/[FQDN_нашего_сервера].log.config -f /opt/synapse/my_logfile.log
/usr/lib/matrix-synapse/synctl start /etc/synapse/homeserver.yaml
/usr/lib/matrix-synapse/register_new_matrix_user -u admin1 -a -c /etc/synapse/homeserver.yaml http://[FQDN_нашего_сервера]:8008
/usr/lib/matrix-synapse/register_new_matrix_user -u test1 --no-admin -c /etc/synapse/homeserver.yaml http://[FQDN_нашего_сервера]:8008
/usr/lib/matrix-synapse/register_new_matrix_user -u test2 --no-admin -c /etc/synapse/homeserver.yaml http://[FQDN_нашего_сервера]:8008
---

4. попробовал мобильных клиентов - не взлетело. Элемент вообще смотрит только в сторону матрикса, а флафи не видит сервера

5. развернул WEB клиента Элемент - он позволил подключиться к матриксу, но локальный сервер не видит, а точнее говорит, что недоверенный сертификат. Здесь притормозили, по результату настроили работу сервера matrix через nginx

6. для чего сделали самоподписанный сертификат

---
echo -e "
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = %%DOMAIN%%
DNS.2 = *.%%DOMAIN%%" > v3.ext

#!/bin/bash
# генерячим корневой
openssl genrsa -out rootCA.key 2048 ; openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 9999 -out rootCA.pem
# генерячим обычный
if [ -z "$1" ]; then   echo "имя_скрипта FQDN_сертификата" ; exit; fi
if [ -f device.key ]; then KEY_OPT="-key" ; else KEY_OPT="-keyout" ; fi

DOMAIN=$1
COMMON_NAME=${2:-$1}
SUBJECT="/C=RU/ST=Moscow/L=Moscow/O=MXT/CN=$COMMON_NAME"
NUM_OF_DAYS=9999

openssl req -new -newkey rsa:2048 -sha256 -nodes $KEY_OPT device.key -subj "$SUBJECT" -out device.csr
cat v3.ext | sed s/%%DOMAIN%%/$COMMON_NAME/g > /tmp/__v3.ext
openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days $NUM_OF_DAYS -sha256 -extfile /tmp/__v3.ext

mv device.csr $DOMAIN.csr
cp device.crt $DOMAIN.crt

# remove temp file
rm -f device.crt;
---

7. и добавили модуль сайта матрикса в конфигурации nginx

---
server {
    listen 443 ssl http2;
    listen 8448 ssl default_server;

    server_name [FQDN_нашего_сервера] ;

    access_log /var/log/nginx/matrix_access.log;
    error_log /var/log/nginx/matrix_error.log;

    ssl_certificate /var/letencrypt/hands/[FQDN_нашего_сервера].crt;
    ssl_certificate_key /var/letencrypt/hands/device.key;

    location / {
        proxy_pass http://127.0.0.1:8008;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

этим самым обернули http:8008 в https:443
---

8. По результату клиент всё равно выперндривается, что homeserver устарел. Методом подбора определились, что версия v1.11.1 работает корректно, и более старые 10, а вот v1.11.34 - уже не работает с нуля, но работает по v1.11.39 если ключи созданы в 10 релизе клиента. В v1.11.40 заявлена совместимость с matrix 1.1 Вероятно старый synapse от Alt более стар. Более того, внутри локальной сети работают и голосовые звонки, но всё работает только после приёма сертификата самого домашнего сервера матрикс - он самоподписанный и просто так не принимается. на этом остановились второй раз статьи: - хабр - https://tavda.net/matrix - про самоподписанный обновил память https://habr.com/ru/articles/352722/

9. Далее работа продолжена 20. Настроено ещё одно имя, ресолвящееся в Инетах - mtx, и проведена настройка основного сервера Apace на обратное проксирование запросов с этого имени на сервер Матрик. Подороге пришлось настроить сертификаты для домена mtx... настройка не давалась долго, пришлось переконфигурировать сервер на более корректную работу с виртуальными хостами, настроить прямой проброс без двойного https, но самая важная причина некорректной работы проброса - в закрытых сетевим фильтром возможностях проброса, из за чего сервер переводил запросы не по конфигурации виртуального хоста, а на дефолтный путь

В результате получена и работает следующая конфигурация проброса

---

    ServerName [FQDN_нашего_сервера]:443

    ServerAdmin webmaster@[FQDN_нашего_сервера]
    ErrorLog logs/[FQDN_нашего_сервера]-error_log
    TransferLog logs/[FQDN_нашего_сервера]-access_log

    ProxyPreserveHost On
    ProxyPass "/" "http://192.168.0.209:8008/"
    ProxyPassReverse "/" "http://192.168.0.209:8008/"

    SSLEngine on
    SSLCertificateFile /etc/httpd/conf.d/mtx_certs/[FQDN_нашего_сервера].crt
    SSLCertificateKeyFile /etc/httpd/conf.d/mtx_certs/[FQDN_нашего_сервера].key
#SSLCACertificateFile /etc/httpd/conf.d/mtx_certs/rootCA.pem

    SSLProtocol all -SSLv2 -SSLv3
    SSLCipherSuite HIGH:3DES:!aNULL:!MD5:!SEED:!IDEA
    
        SSLOptions +StdEnvVars
    
    BrowserMatch "MSIE [2-5]" \
             nokeepalive ssl-unclean-shutdown \
             downgrade-1.0 force-response-1.0
    CustomLog logs/[FQDN_нашего_сервера]-ssl_request_log \
              "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"




    ServerName [FQDN_нашего_сервера]:80

    ServerAdmin webmaster@[FQDN_нашего_сервера]
    ErrorLog logs/[FQDN_нашего_сервера]-error_log
    TransferLog logs/[FQDN_нашего_сервера]-access_log

    ProxyPreserveHost On
    ProxyPass "/" "http://192.168.0.209:8008/"
    ProxyPassReverse "/" "http://192.168.0.209:8008/"


---

10. Далее проверена работа между клиентами - звонки без TURN возможны только внутри одной сети, и даже с включением его, т.к. он от другого домашнего серверак - не фурычит. Особенностью является то, что на телефоне WEB не отдаёт микрофон хрому, а камеру - Firefox'у. Также нужно каждый раз подтверждать сертификаты клиента и сервера в браузерах

--- здесь завершён первый работающий вариант ---

03. Cервер и клиент "для себя" из ALT Linux 11. Самоподписанный сертификат

Примечательно, что для каждой версии сервера Synapse и клиентов есть свои рабочие и нерабочие варианты комбинаций. Например комбинация сервера и WEB клиента из репозитария АЛЬТ 11 версии прекрасно работают с текстом практически из коробки, но не пробрасывают звук даже в локальной сети. Возможно их нужно как то по особенному готовить. Но для находящейся в репозитарии версии Синаспа в качестве клиентов, в т.ч. со звуком, у меня заработали WEB кльент версии v1.11.109 c GiotHUB для рабочей станции под управлением Linux, и Черепаха (SchildiChat) актуальной версии для Андроида. А вот ElementX отказался работать с голосовыми и видеозвонками, выдав некое сообщение, которое может и дало бы нужный функционал, после сурпулёзного изучения документации на эту ошибку и настройку, но из коробки не взлетело. Старый Element вообще не позволял выбрать другой домашний сервер, на чем эксперименты с ним и закончились при подходе к 10 версии репозитария АЛЬТов. Также не заработал FluffyChat под Android

Установка и базовое конфигурирование тут не сильно отличаются. Сначала устанавливаем пакеты и настраиваем сам синапс:

---
apt-get install matrix-synapse element-web coturn

/usr/bin/generate_config --config-dir /etc/synapse --data-dir /opt/synapse --server-name [FQDN_нашего_сервера] \
  --report-stats yes --generate-secrets > /etc/synapse/homeserver.yaml
/usr/bin/generate_signing_key -o /etc/synapse/[FQDN_нашего_сервера].signing.key
/usr/bin/generate_log_config -o /etc/synapse/[FQDN_нашего_сервера].log.config -f /opt/synapse/[FQDN_нашего_сервера]_logfile.log
/usr/bin/synctl start /etc/synapse/homeserver.yaml

# https будет сделан через локальный NGNX, через него же /.well-known/matrix/client
/usr/bin/register_new_matrix_user -u admin -p pwadmin -a -c /etc/synapse/homeserver.yaml http://127.0.0.1:8008
/usr/bin/register_new_matrix_user -u user1 -p pwuser1 --no-admin -c /etc/synapse/homeserver.yaml http://127.0.0.1:8008
/usr/bin/register_new_matrix_user -u user2 -p pwuser2 --no-admin -c /etc/synapse/homeserver.yaml http://127.0.0.1:8008
/usr/bin/register_new_matrix_user -u user3 -p pwuser3 --no-admin -c /etc/synapse/homeserver.yaml http://127.0.0.1:8008
/usr/bin/register_new_matrix_user -u user4 -p pwuser4 --no-admin -c /etc/synapse/homeserver.yaml http://127.0.0.1:8008
---

Далее настраиваем NGINX. Сертификаты выпускаются также, как в разделе про 10 платформу выше. Кроме этого нужно настроить DNS для внешних и внутренних зон, и настроить проброс портов 443, 8448 на сервер из внешнего мира. Конфиг NGINX примерно такой:

---
server {
    listen 192.168.0.209:443 ssl ;
    http2 on ;
    listen 192.168.0.209:8448 ssl default_server ;
    server_name [FQDN_нашего_сервера] ;
    access_log /var/log/nginx/matrix_access.log;
    error_log /var/log/nginx/matrix_error.log;

    ssl_certificate /etc/synapse/conf_cert/FIRST_[FQDN_нашего_сервера]/[FQDN_нашего_сервера].crt;
    ssl_certificate_key /etc/synapse/conf_cert/FIRST_[FQDN_нашего_сервера]/[FQDN_нашего_сервера].key;

    location / {
        proxy_pass http://127.0.0.1:8008;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;
    }

    location /.well-known/matrix/client {
        return 200 '{"m.homeserver": {"base_url": "https://[FQDN_нашего_сервера]"}}';
        default_type application/json;
        add_header Access-Control-Allow-Origin *;
    }
}
---

Для работы с текстовыми из локальной сети и интернет этого достаточно. А вот голосовые и видеозвонки в этой точке работают только в локальной сети. В этом месте мы настраиваем coturn

---
# проброс портов - normally 3478 & 5349 for TCP & UDP TURN traffic, 49152-65535 UDP relay
# файл /etc/coturn/turnserver.conf
use-auth-secret
static-auth-secret=[ключ сделан утилитой pwgen -s 64 1]
realm=[FQDN_нашего_сервера]

syslog
no-tcp-relay

denied-peer-ip=10.0.0.0-10.255.255.255
denied-peer-ip=192.168.0.0-192.168.255.255
denied-peer-ip=172.16.0.0-172.31.255.255

allowed-peer-ip=192.168.0.209

user-quota=16
total-quota=1200

external-ip=35.27.45.67
listening-ip=192.168.0.209

cert=/etc/synapse/conf_cert/[FQDN_нашего_сервера]/rootCA.pem
pkey=/etc/synapse/conf_cert/[FQDN_нашего_сервера]/[FQDN_нашего_сервера].key

---

Файл конфигурации самого синапса /etc/synapse/homeserver.yaml приобретает вид ниже. Теперь работает и из за NAT голос и видео

---
# файл /etc/synapse/homeserver.yaml
turn_uris: [ "turn:[FQDN_нашего_сервера]?transport=udp", "turn:[FQDN_нашего_сервера]?transport=tcp" ]
turn_shared_secret: "секрет из опции static-auth-secret файла /etc/coturn/turnserver.conf"
turn_user_lifetime: 86400000
turn_allow_guests: false
server_name: "[FQDN_нашего_сервера]"
pid_file: /opt/synapse/homeserver.pid
listeners:
  - port: 8008
    tls: false
    type: http
    x_forwarded: true
    bind_addresses: ['127.0.0.1','192.168.0.209']
    resources:
      - names: [client]
        compress: false
database:
  name: sqlite3
  args:
    database: /opt/synapse/homeserver.db
log_config: "/etc/synapse/[FQDN_нашего_сервера].log.config"
media_store_path: /opt/synapse/media_store
registration_shared_secret: "соответствующее значение, сгенерированное начальной командой генерации конфига"
report_stats: true
macaroon_secret_key: "соответствующее значение, сгенерированное начальной командой генерации конфига"
form_secret: "соответствующее значение, сгенерированное начальной командой генерации конфига"
signing_key_path: "/etc/synapse/[FQDN_нашего_сервера]signing.key"
trusted_key_servers:
  - server_name: "[FQDN_нашего_сервера]"
---

--- здесь завершён вполне работающий вариант для личного использования без федерации с самоподпиcанными сертификатами ---

04. Как включить федерацию - первый подход к снаряду

На начало работы с включением федерации сервер развёрнут и работает в конфигурации
- отдельная виртуалка, на которой Synapse, Coturn и Element
- nginx как обёртка, сертификаты самоподписаные пока, их приходится добавлять в браузеры
- по поводу этого всего размещены заметки на своей WEB площадке
- по основным учёткам сохранены данные для восстановления ключей

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

- для Android текущие версии Element и SchildiChat с F-DROID вполне работают с нашим сервером, спрашивая - доверять ли самоподписанному сертификату. При этом большое видео отправить нельзя, но маленькое можно. это лимит сообщения
- для десктопного SchildiChat ругалось на сертификаты до момента размещения корневого самоподписанного сертификата издателя в /etc/pki/ca-trust/source/anchors и отработки команды update-ca-trust , после чего сертификат появился в /etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt, и шилдик взлетел
- для настройки федерации актуализировали блоки .well-known в nginx, общий конфиг имеет вид:

---
server {
    listen IP_виртуалки:443 ssl ;
    http2 on ;
    listen IP_виртуалки:8448 ssl default_server ;
    server_name FQDN_сервера ;
    access_log /var/log/nginx/[FQDN_нашего_сервера]_access.log;
    error_log /var/log/nginx/[FQDN_нашего_сервера].ru_error.log;
    ssl_certificate /etc/synapse/conf_cert/[FQDN_нашего_сервера]/[FQDN_нашего_сервера].crt;
    ssl_certificate_key /etc/synapse/conf_cert/[FQDN_нашего_сервера]/[FQDN_нашего_сервера].key;
    location / {
        proxy_pass http://127.0.0.1:8008;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;
#        proxy_set_header X-Forwarded-For $remote_addr;
    }

    location /.well-known/matrix/client {
                return 200 '{"m.homeserver": {"base_url": "https://[FQDN_нашего_сервера]"}}';
                default_type application/json;
                add_header Access-Control-Allow-Origin *;
                }

    location /.well-known/matrix/server {
                return 200 '{"m.server": "[FQDN_нашего_сервера]:443"}';
                default_type application/json;
                add_header Access-Control-Allow-Origin *;
                }
    }
---

- для настройки федерации создали SRV запись в DNS
- для тестирования федерации создали учётку @user:converser.eu, и вот тут и уперлись в самоподпиванные сертификаты, о чем детально рассказала утилита тестирования федерации/ Которую нашли в статьях, и размещенную по адресу https://federationtester.mtrnord.blog/ выводы запланированы временные сертификаты от LetEncrypts для тестирования

05. Как включить федерацию - второй подход к снаряду

1. получен общепризнаваемый сертификат Lets Encrypt: apg-get install certbot ; certbot certonly --manual ; указать домен. Далее по ссылке создать файл с ключом в своём домене - будут созданы сертификаты на 90 дней. Перенести их /etc/letsencrypt на нужный сервер и перенастроить nginx

2. донастроена федерация, для этого в конфиге строка "- names: [client]" заменена на "- names: [client, federation]". Кроме этого добавлены опции: matrix_synapse_federation_enabled: true и matrix_synapse_federation_port_enabled: true. После рестарта сервера стали отдаваться подстроки федерации, прошла проверка https://federationtester.mtrnord.blog/, включилась связь с matrix.org ... на этом базовая настройка федерации завершена

--- здесь завершена базовая настройка федерации ---

06. Настройка Element CALL - "осматриваем поле", готовимся понять

[01] на сайте https://github.com/element-hq/element-call сказано, что используется некий "live kit", и нужен сервис авторизации. Там есть и дока https://github.com/element-hq/element-call/blob/livekit/docs/README.md В том числе обращаем внимание MatrixRTC backend (according to MSC4143) is announced by the Matrix site's .well-known/matrix/client file and discovered via the org.matrix.msc4143.rtc_foci key, e.g.:

---
"org.matrix.msc4143.rtc_foci": [
    {
        "type": "livekit",
        "livekit_service_url": "https://matrix-rtc.example.com/livekit/jwt"
    },
]
---

[02] но потом при отправке в доку selfhosted https://github.com/element-hq/element-call/blob/livekit/docs/self-hosting.md сказано, что надо только включить в конфигурацию сервера опции ИЗ ДОКИ, но потом сказано, что должно быть там еще

---
experimental_features:
  # MSC3266: Room summary API. Used for knocking over federation
  msc3266_enabled: true
  # MSC4222 needed for syncv2 state_after. This allow clients to
  # correctly track the state of the room.
  msc4222_enabled: true

# The maximum allowed duration by which sent events can be delayed, as
# per MSC4140.
max_event_delay_duration: 24h

rc_message:
  # This needs to match at least e2ee key sharing frequency plus a bit of headroom
  # Note key sharing events are bursty
  per_second: 0.5
  burst_count: 30

rc_delayed_event_mgmt:
  # This needs to match at least the heart-beat frequency plus a bit of headroom
  # Currently the heart-beat is every 5 seconds which translates into a rate of 0.2s
  per_second: 1
  burst_count: 20
---

[03] некий "live kit" - это система работы с WebRTC - https://github.com/livekit/livekit. Она пишут основана на реализации WEB RTC от Pion https://github.com/pion/webrtc. Её сервер можно скачать как указано на сайте - вы получаете один бинарник, но исходники тоже есть. Кроме этого сервера live kit рекомендуют скачать к нему клиента https://github.com/livekit/livekit-cli. Я скачал, там можно управлять руками, но для нашей цели наверно это просто добавочный инструмент. Сам сервер можно в минималке запустить с ключом --dev, к этой штуке есть и документация https://docs.livekit.io/. Пример конфига лежит там же https://github.com/livekit/livekit/blob/master/config-sample.yaml, рекомендуют сразу выключать автоматическое создание комнат

---
room:
  auto_create: false
---

[04] собственно сервер авторизации - он тут https://github.com/element-hq/lk-jwt-service. Сказано как его скачать, если не докер

---
wget https://github.com/element-hq/lk-jwt-service/releases/latest/download/lk-jwt-service_linux_amd64
chmod +x lk-jwt-service_linux_amd64
Run locally:
LIVEKIT_URL="ws://somewhere" LIVEKIT_KEY=devkey LIVEKIT_SECRET=secret LIVEKIT_FULL_ACCESS_HOMESERVERS=example.com ./lk-jwt-service_linux_amd64
---

Для него рекомендуют такую конфигурацию NGINX, и не забыть well-known/matrix/client

---
server {
    listen 80;
    server_name matrix-rtc.domain.tld;

    # Redirect HTTP → HTTPS
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name matrix-rtc.domain.tld;

    # TLS certificate paths (replace with your own)
    ssl_certificate     /etc/ssl/certs/matrix-rtc.crt;
    ssl_certificate_key /etc/ssl/private/matrix-rtc.key;

    # TLS settings (minimal)
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location /livekit/jwt/ {
        proxy_pass http://localhost:8080/;
        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;
    }
}
---

.well-known/matrix/client For proper MatrixRTC functionality, you need to configure your site's. The following key must be included in https://domain.tld/.well-known/matrix/client:

---
"org.matrix.msc4143.rtc_foci": [
    {
        "type": "livekit",
        "livekit_service_url": "https://matrix-rtc.domain.tld/livekit/jwt"
    }
]
---

думаю себе, что и сам поддомен lk-jwt и велл-кновн нада вешать на основной сайт с его сертификатами, а сам сервис будет от слушать отдельный порт, например, 8080. также думаю себе, что сам live kits должен быть стартован с некими ключами и проброшен в инет напрямую. Но может он работает через lk-jwk, надо изучить. Остановлено до появления ресурса

--- здесь завершен начальный обзор поляны перед включением Element Call ---

07. Кубики системы Matrix - теоретические выводы

После "изучения поляны" по Element Call сделаны следующие выводы:

- в настоящий момент Element Call - это надстройка над сервером Synapse, реализующая альтернативный механизм обработки VoIP, однако через стэк WebRTC, как и ранее. Просто отдельный механизм работы, не в сервере, а поднимаемый рядом. Механизм, а точнее целый engine, называется LiveKIT, вроде как с открытым кодом, лежащим на Житхабе. Этот LivEKIT предоставляется и для самостоятельного размещения у себя, и в виде облачного сервиса за деньги видимо. Нам интересен вариант для себя. Документация там обширная, но с непривычки, да и потом, не очевидная

сам этот LiveKIT при локальном размещении на вашем сервере конфигурируется - со своим белым IP, в т.ч. со своими портами TCP для управления и диапазоном портов UDP для потока медиа. Также ему нужны сервера STUN и TURN, чтобы "сводить" клиентов за разными сетевыми фильтрами. Если не указать сервер STUN, используется некий буржуйский, что нам в условиях блокировок и желания иметь свою инфраструктуру - не надо, а TURN у него есть свой встроенный. Но т.к. мы при развёртывании сервера Synapse ещё до всякого Element Call развертывали для проброса звонков COTURN, умеющий и STUP, и TURN - его очевидно и надо использовать

- для совместной работы LiveKIT с сервером Synapse нужен посредник, ещё один сервис LK_JWT, занимающийся сквозной авторизацией, по цепочке сервер матрикс -> авторизационный механизм> - машина VoIP LiveKIT. Сервис механизма авторизации LK_JWT также, как LiveKIT лежит на житхабе, также есть исходники и скомпилированный бинарник, и есть документация с неочевидными моментами - приходится искать варианты. Сервис авторизации также имеет свою конфигурацию, в том числе включает разделяемую пару ключей, настроенных в LiveKIT для взаимодействия с ним. Его порты мы не пробрасываем наружу в белый IP, а просто отдаём через обёртку NGINX (или иного WEB сервера) как поддомены домена сервера Matrix

Итог. Таким образом складывается целостное решение из следующих кубиков:

-- 01 -- базовая конфигурация. Совсем базовая. Сам сервер протокола Matrix, например Synapse, который развёрнут у вас на серверах внутри и просто слушает локальный нешифрованный порт

-- 02 -- базовая конфигурация. Совсем базовая. Сервер WEB, при всей любви к Apache здесь мне показался более простым NgiNX, хотя работало у меня и на Apache в первых экспериментах. WEB сервер нужен как обратный прокси с шифрованием - он смотрит наружу по портам 443 для всех, плюс 8448 для федерации, ему скармливается сертификат домена, и запросы снаружи он пробрасывает на ваш нешифрованный порт сервера Matrix. Также он отдаёт поддомены с .well-known информацией

Данные о конфигурации _сервиса_ Matrix для DNS домена все получают из SRV записи для домена в вашей DNS зоне, и из подкаталогов [FQDN_имя_сервера/домена]/.well-known/matrix/client и [FQDN_имя_сервера/домена]/.well-known/matrix/server. Для конфигурирования одачи информации из подразделов сайта очевидно используется WEB сервер

Для общения в текстовом режиме для себя с самоподписанным сертификатом этих кубиков достаточно. Если нужна федерация - она требует честного сертификата, который может проверяться другими серверами федерации, но включается просто, это описано более ранних в разделах. Все требуемые для этого программные пакеты есть в составе репозитария Альт 11 платформы

-- 03 -- базовая конфигурация. Добавляем голос и видео. Для работы голоса и видео в локальной сети больше ничего не нужно - они зарабоатют из коробки. Но т.к. клиенты могут быть за разными серевыми фильтрами, а то и множественными - требуется развернуть сервер TURN/STUN. Он есть в составе репозитария того же Альта. Это сервис COTURN, он обменивается с сервером Matrix с защитой разделяемым ключом, и его настройка также описана в более ранних разделах здесь. У него есть пару управляющих номеров портов TCP/UDP и пул UDP портов для проброса медиапотоков с клиентов. Все они описаны в конфигурационном файле сервер, и всех их нужно пробросить на сервер с выбранного вами для этого функционала белого IP

После конфигурирования COTURN и добавления нескольких строчек в конфигурацию сервера matrix - голосовые и видеозвонки работают по всему миру. По крайней мере на момент написания этих строк

-- 04 -- небазовая сейчас конфигурация. Element CALL - отдельная машина видеозвонков через стэк WebRTC под названием LiveKIT. Качается с Житхаба, настраивается с пробросом своих портов, а также настраивается на использование сервера STUN/TURN. Сам сервис также отдаётся не только через проброшенные порты белого IP, но и пробросом порта управления запущнного сервиса LivKIT через поддомены WEB сервера [FQDN_имя_сервера/домена]/livekit/sfu/

-- 05 -- сервис авторизации LK_JWT, являющийся посредником между сервисами Matrix и LiveKIT. Имеет разделяемую с сервисом LiveKIT пару ключей, стартует и слушает локальный порт, а во внешний мир отдаётся пробросом порта управления запущнного сервиса LK_JWT через поддомен WEB сервера [FQDN_имя_сервера/домена]/livekit/jwt/

Насколько я понимаю, пакетов для старта Element Call в репозитарии Альтов в настоящее время нет, это всего два сервиса, которые в виде релизных бинарников качаются сейчас с Житхаба. Для чего нужен Element Call вообще, если основной функционал работает и так ? Судя по новому поколению клиентов для Андроид (Element X) от Matrix Foundation и дочерних (Shildi Chat Nxt), которые делают видеозвонки только через Element Call, парни в matrix Foundation или решили в будущем резко упростить код сервиса, или же его разумно оптимизировать. Что там на первом месте - лень, или принятый в Unix подход разделять функциональные кубики - неясно. Думаю, что текущей реализации хватит надолго - лет на десять, но полезно смотреть в сторону тенденций. И, если тенденция в том, чтобы вынести WebRTC машину в отдельный код - лучше научиться это делать

08. Практическое конфигурирование с Element Call

01. Скачиваем и устанавливаем LiveKIT

---
mkdir /opt/livekit
INSTALL_PATH=/opt/livekit
curl -sSL https://get.livekit.io | bash
---

02. Конфигурируем LiveKIT

---
echo > /opt/livekit/livekit_config.yaml
# содержимое конфигурационного файла
port: 7880
rtc:
  port_range_start: 20000
  port_range_end: 22000
  tcp_port: 7881
  use_external_ip: true
  node_ip: [наш_белый_IP]
  stun_servers:
     - [FQDN_нашего_сервера]:3478
  turn_servers:
     - host: [FQDN_нашего_сервера]
       port: 5349
       protocol: tls
       secret: "<здесь_разделяемый_ключ_нашего_TURN_сервера>"
       ttl: 14400 # seconds
keys:
  key_api_1234567890123456789012345678901234567890: secret_1234567890123456789012345678901234567890
logging:
   level: debug
room:
   auto_create: false
---

03. Проброс портов LiveKIT

---
белый_IP:tcp:7880-7881 -> локальный_IP_сервера:tcp:7880-7881
белый_IP:udp:20000-22000 -> локальный_IP_сервера:udp:20000-22000
---

04. Стартуем LiveKIT

---
echo > /opt/livekit/start_livekit.sh
# содержимое файла
#!/bin/bash
LOG_FILE=/opt/livekit/livekit_server.log
exec 7>&1
exec 8>&2
exec 1>>$LOG_FILE ;
exec 2>&1 ;
# эти две переменные возможно избыточны
export LIVEKIT_API_KEY=key_api_1234567890123456789012345678901234567890
export LIVEKIT_API_SECRET=secret_1234567890123456789012345678901234567890
/opt/livekit/livekit-server --config /opt/livekit/livekit_config.yaml &
---

05. Скачиваем и устанавливаем LK_JWT

---
cd /opt/livekit
wget https://github.com/element-hq/lk-jwt-service/releases/latest/download/lk-jwt-service_linux_amd64
chmod 755 lk-jwt-service_linux_amd64
---

06. Конфигурируем и стартуем LK_JWT

---
echo > /opt/livekit/start_livekit.sh
# содержимое файла
#!/bin/bash
LOG_FILE=/opt/livekit/lk_jwt.log
exec 7>&1
exec 8>&2
exec 1>>$LOG_FILE ;
exec 2>&1 ;
# это параметр подсмотрен внизу здесь - https://github.com/element-hq/lk-jwt-service/blob/main/README.md
export LIVEKIT_URL="wss://[FQDN_нашего_сервера]/livekit/sfu"
export LIVEKIT_API_KEY=key_api_1234567890123456789012345678901234567890
export LIVEKIT_API_SECRET=secret_1234567890123456789012345678901234567890
export LIVEKIT_KEY=key_api_1234567890123456789012345678901234567890
export LIVEKIT_SECRET=secret_1234567890123456789012345678901234567890
#export LIVEKIT_FULL_ACCESS_HOMESERVERS=[FQDN_нашего_сервера]
export LIVEKIT_FULL_ACCESS_HOMESERVERS=*
/opt/livekit/lk-jwt-service_linux_amd64 &
---

06. Доконфигурируем WEB сервер. Здесь будет приведено полное содержание файла конфигурации, с выделением цветом вновь добавленного

---
server {
    listen 192.168.0.209:443 ssl ;
    http2 on ;
    listen 192.168.0.209:8448 ssl default_server ;
    server_name [FQDN_нашего_сервера] ;

    access_log /var/log/nginx/[FQDN_нашего_сервера]_access.log;
    error_log /var/log/nginx/[FQDN_нашего_сервера]_error.log;
    ssl_certificate /etc/letsencrypt/live/[FQDN_нашего_сервера]/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/[FQDN_нашего_сервера]/privkey.pem;

# проброс на нешифрованный порт сервера Matrix
    location / {
        proxy_pass http://127.0.0.1:8008;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;
    }

# этот блок возвращает в формате JOSN нужный телефонным клиентам ответ,
# а также подблок org.matrix.msc4143.rtc_foci для Element Call из https://github.com/element-hq/element-call/blob/livekit/docs/self-hosting.md#Prerequisites
    location /.well-known/matrix/client {
             return 200 '{"m.homeserver": {"base_url": "https://[FQDN_нашего_сервера]"},
                          "org.matrix.msc4143.rtc_foci": [ {"type": "livekit", "livekit_service_url": "https://[FQDN_нашего_сервера]/livekit/jwt"}]}';
             default_type application/json;
             add_header Access-Control-Allow-Origin *;
# а также дополнения к подблоку org.matrix.msc4143.rtc_foci для Element Call из https://github.com/element-hq/element-call/blob/livekit/docs/self-hosting.md#Prerequisites
# может потребуется включить
             add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
             add_header Access-Control-Allow-Headers "X-Requested-With, Content-Type, Authorization";
             }

    location /.well-known/matrix/server {
             return 200 '{"m.server": "[FQDN_нашего_сервера]:443"}';
             default_type application/json;
             add_header Access-Control-Allow-Origin *;
             }
# в том числе из https://github.com/element-hq/element-call/blob/livekit/docs/self-hosting.md#Prerequisites
    location ^~ /livekit/jwt/ {
             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;
.
             # MatrixRTC Authorization Service running at port 8080
             proxy_pass http://localhost:8080/;
             }

    location ^~ /livekit/sfu/ {
             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;

             proxy_send_timeout 120;
             proxy_read_timeout 120;
             proxy_buffering off;

             proxy_set_header Accept-Encoding gzip;
             proxy_set_header Upgrade $http_upgrade;
             proxy_set_header Connection "upgrade";

             # LiveKit SFU websocket connection running at port 7880
             proxy_pass http://localhost:7880/;
             }
    }
---

07. Доконфигурируем файл конфигурации сервера Matrix. Любопытно, что к этому моменту Element Call заработал с Element WEB на ПК и Element X на Андроиде. Однако работа эта не стабильна, в условиях блокировок не совсем понятны причины, нужно разбираться, а также в соответствии с документацией с конфигурационный файл сервера matrix нужно бы добавить следующий блок:

---
experimental_features:
  # MSC3266: Room summary API. Used for knocking over federation
  msc3266_enabled: true
  # MSC4222 needed for syncv2 state_after. This allow clients to
  # correctly track the state of the room.
  msc4222_enabled: true

# The maximum allowed duration by which sent events can be delayed, as
# per MSC4140.
max_event_delay_duration: 24h

rc_message:
  # This needs to match at least e2ee key sharing frequency plus a bit of headroom
  # Note key sharing events are bursty
  per_second: 0.5
  burst_count: 30

rc_delayed_event_mgmt:
  # This needs to match at least the heart-beat frequency plus a bit of headroom
  # Currently the heart-beat is every 5 seconds which translates into a rate of 0.2s
  per_second: 1
  burst_count: 20
---

--- здесь завершен обзор практической конфигурации Element Call ---

Нужно сказать, при при настроенном расширении Element Call клиенты с его поддержкой работают между собой, и клиенты без его поддержки, как и до настройки, работают между собой. Но вот клиент с поддержкой Element Call и без поддержки, только с нативным VoIP от Synapse - друг с другом не дружат. Гораздо неприятнее то, что технология Element Call не работает, если ваш телефон получает мобильный интернет от одного оператора связи, и работает, когда получает мобильный интернет от другого. При этом штатный исконный VoIP

Белонин С.С. (С)

(даты последующих модификаций не фиксируются)


 
        
   
    Нравится     

(C) Белонин С.С., 2000-2026. Дата последней модификации страницы:2026-03-18 22:27:09