Введение

matrix.org - децентрализованная система обмена сообщениями. Децентрализованная - значит любое сообщество может организовать себе связь, которую будет контролировать только оно само. По такому же принципу как работает почтовый сервер, вы можете поднять свой сервер мгновенных сообщений и звонков. Для этого вам нужен домен, белый IP, сервер.

Клиент matrix не хуже клиента telegram или whatsapp. Нет проблем с push на телефонах, есть тёмная тема, есть голосовые сообщения, web-клиент, аудио-видео звонки, режим конференции. Серверная часть мессенджера открыта, в связи с чем у вас есть возможность доверять своему мессенджеру "как себе". Используем на своём предприятии в течение 3-х месяцев. Люди реально пользуются, их не пришлось в мессенджер палкой (как в случае с tox). Скорость передачи файлов на своём сервере не снилась ни telegram ни whatsapp. Настроек по безопасности, таких как в element - нет ни в каком другом мессенджере.

Ниже будет представлена инструкция по разворачиванию synapse + postgres, element-web, synapse-admin и coturn, а так же настройке обратного прокси на примере NPM для корректной работы федерации (чтобы другие сервера matrix к вам могли обращаться по домену). По выполнению инструкции вы сможете поднять свой работающий matrix сервер, на котором можно будет регистрироваться только обладателям почты с вашим доменом, для того чтобы пользователей не надо было регистрировать вручную.

LXC matrix.example.org

Заводим lxc контейнер, даём ему отдельно /data и /pgdata, для данных matrix и базы pgsql:

image.png
image.png

Подготавливаем машину, ставим docker & docker-compose

Synapse

Инициализируем конфиг synapse:

 docker run -it --rm -v /data:/data -e SYNAPSE_SERVER_NAME=example.org -e SYNAPSE_REPORT_STATS=yes matrixdotorg/synapse generate

Тут важный момент, который сначала меня смутил. Тут надо указывать именно свой домен, а не доменное имя машины synapse. Тут указывается то, что попадёт в адрес вашего пользователя: @someuser:example.org. После инициализации изменить "название сервера" нельзя. Об этом подробно написано тут https://matrix.org/docs/guides/understanding-synapse-hosting.

/data/homeserver.yaml

После инициализации появится файл /data/homeserver.yaml. В нём нужно заменить ветку database. Суть замены в переключении synapse на хранение базы в postgres. Остальное оставляйте как есть и добавляйте в конец настройки регистрации, SMTP и TURN.

server_name: "example.org"
pid_file: /data/homeserver.pid
listeners:
  - port: 8008
    tls: false
    type: http
    x_forwarded: true
    resources:
      - names: [client, federation]
        compress: false
# Замените ветку database для PGSQL
database:
  name: psycopg2
  txn_limit: 10000
  args:
    user: synapse
	# Пароль от постгри из docker-compose.yaml
    password: napoJIb_oT_nocTrPu_20
    database: synapse
    # Хост контейнера с постгри docker ps
    host: matrix-synapse_db-1
    port: 5432
    cp_min: 5
    cp_max: 10
log_config: "/data/example.org.log.config"
media_store_path: /data/media_store
registration_shared_secret: "CJIy4auHblE_CuMBoJIbl_80_ieShahba9ahHoh2Nied1gaide6xaip5eeNg4Oogha6ingeThuc"
report_stats: true
macaroon_secret_key: "ELLIE_ogHu_CJIy4auHblE_CuMBoJIbl_50_Uengee4Iepu8do"
form_secret: "u_ELLIE_ogHu_CJIy4auHblE_CuMBoJIbl_50_Oofai0phi6ah"
signing_key_path: "/data/example.org.signing.key"
trusted_key_servers:
  - server_name: "matrix.org"

# Включает регистрацию, для обладателей почты *@example.org
enable_registration: true
enable_registration_without_verification: false
suppress_key_server_warning: true
registrations_require_3pid:
  - email
allowed_local_3pids:
  - medium: email
    pattern: '^[^@]+@example\.org$'

# Выделите почтовый аккаунт для отправки писем пользователям
email:
  smtp_host: mail.example.org
  smtp_port: 587
  smtp_user: "matrix@example.org"
  smtp_pass: "napoJIb_oT_9LLLuKA"
  notif_from: "matrix@example.org"

# Укажите адрес turn сервера
turn_uris: [ "turn:turn.example.org?transport=udp", "turn:turn.example.org?transport=tcp" ]
turn_shared_secret: "u_ELLIE_u_ELLIE_ogHu_CJIy4auHblE_CuMBoJIbl_50_XxxX"
turn_user_lifetime: 86400000
turn_allow_guests: True

/docker/matrix/docker-compose.yaml

Указываю пока только synapse (матрикс сервер), postgres для synapse. Блоки с element-web и synapse-admin, упомянутые ниже, впишите в конец этого файла, если они вам нужны.

version: '3'

services:

  synapse:
    image: docker.io/matrixdotorg/synapse
    restart: always
    environment:
      - SYNAPSE_CONFIG_PATH=/data/homeserver.yaml
    volumes:
      - /data:/data
    depends_on:
      - synapse_db
    ports:
      - 8008:8008

  synapse_db:
    image: docker.io/postgres:14-alpine
    restart: always
    environment:
      - POSTGRES_USER=synapse
      - POSTGRES_PASSWORD=napoJIb_oT_nocTrPu_20
      - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C
    volumes:
      - /pgdata:/var/lib/postgresql/data

Поехали!

docker-compose up -d

Nginx Proxy Manager

Matrix, конечно использует ssl-сертификаты, и скорее всего вы уже давным-давно поставили обратный прокси, который заведует LE сертификатами и вешает ssl "замки" на ваши сервисы.
В моём случае стоит NPM и домен example.org, конечно же ведёт на сайт организации. На примере NPM показываю как получить работающую федерацию и ssl на своём matrix.

Настраивать будем узлы matrix.example.org и example.org. Если у вас NPM запущен через compose, то нужно добавить проброс 8448 порта из docker наружу.

image.png
image.png

И не забыть организовать NAT 8448 с внешней IP -> NPM

matrix.example.org

Его необходимо направить на внутреннюю IP с matrix.example.org:

image.png
image.png

И добавить блок в Advanced->Custom Nginx Configuration:

image.png
image.png
add_header Access-Control-Allow-Origin *;
listen 8448 ssl http2;

location /.well-known/matrix/server {
    return 200 '{"m.server": "matrix.example.org:443"}'; 
    default_type application/json;
    add_header Access-Control-Allow-Origin *;
}

example.org

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

image.png
image.png

"/.well-known/matrix/server" -> matrix.example.org:443
"/.well-known/matrix/client"  -> matrix.example.org:443
"/_matrix/client" -> "192.168.XX.XX"/_matrix/client 8008(http)
"/_synapse/client" -> "192.168.XX.XX/_synapse/client" 8008(http)

Теперь вы можете использовать "matrix.example.org" в качестве сервера при настройке matrix клиента. Работать будет и во внешней сети и во внутренней.

Федерация

Для проверки работы федерации вводите на странице https://federationtester.matrix.org свой домен - "example.org". Проверка покажет всё ли у вас в порядке и над чем ещё стоит поработать. Если всё будет в порядке, то ваши абоненты смогут общаться с абонентами других доменов.

Клиент

Element

Ставьте куда-нибудь Element.io (он есть на всё).
В качестве сервера указывайте "matrix.example.org", регистрируйтесь с использованием электронной почты *@example.org
При регистрации на почту придёт ссылка, перейдите по ней. Теперь вы зарегистрированы.

Админские права

За админскими правами идём на докер машину, заходим в контейнер с postgres и отмечаем свежесозданного себя как администратора:

docker exec -it matrix-synapse_db-1 /bin/bash
psql -U synapse -W
UPDATE users SET admin = 1 WHERE name = '@admin:example.org';

https://matrix-org.github.io/synapse/latest/usage/administration/admin_faq.html

Element-web

Дописываем в тот же docker-compose.yaml блок с element-web:

element:
    image: vectorim/element-web:latest
    restart: always
    volumes:
      - ./element-config.json:/app/config.json
    ports:
      - 80:80

Рядом с docker-compose.yaml кладём element-config.json
Есть гайды, по настройке element-web. Пришлось потратить некоторое количество времени на то, чтобы мой экземпляр работал только с моим сервером. Выкладываю работающий конфиг:

{
    "default_server_config": {
        "m.homeserver": {
            "base_url": "https://matrix.example.org",
            "server_name": "matrix.example.org"
        },
        "m.identity_server": {
            "base_url": "https://vector.im"
        }
    },
    "disable_custom_urls": true,
    "brand": "Element",
    "integrations_ui_url": "https://scalar.vector.im/",
    "integrations_rest_url": "https://scalar.vector.im/api",
    "integrations_widgets_urls": [
        "https://scalar.vector.im/_matrix/integrations/v1",
        "https://scalar.vector.im/api",
        "https://scalar-staging.vector.im/_matrix/integrations/v1",
        "https://scalar-staging.vector.im/api",
        "https://scalar-staging.riot.im/scalar/api"
    ],
    "bug_report_endpoint_url": "https://element.io/bugreports/submit",
    "uisi_autorageshake_app": "element-auto-uisi",
    "showLabsSettings": false,
    "roomDirectory": {
        "servers": ["matrix.org", "gitter.im", "libera.chat"]
    },
    "enable_presence_by_hs_url": {
        "https://matrix.org": false,
        "https://matrix.example.org": false
    },
    "terms_and_conditions_links": [
        {
            "url": "https://element.io/privacy",
            "text": "Privacy Policy"
        },
        {
            "url": "https://element.io/cookie-policy",
            "text": "Cookie Policy"
        }
    ],
    "posthog": {
        "projectApiKey": "phc_zaer9Hu0paisaiphiech9Aeli9ieH7yasaphi3Feesh",
        "apiHost": "https://posthog.element.io"
    },
    "privacy_policy_url": "https://element.io/cookie-policy",
    "map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=Ua4ahDe4mip4iezab3ae"
}

Для доступа к element-web, добавил узел "m.example.org" -> IP matrix.example.org:80

Synapse-admin

Честно говоря, не знаю, нужен он мне или не нужен. Раз уж разобрался с ним, то опишу. Туда же - в конец docker-compose.yaml

 synapse-admin:
    container_name: synapse-admin
    hostname: synapse-admin
    image: awesometechnologies/synapse-admin:latest
    ports:
      - "8080:80"
    restart: always

Synapse admin будет доступен на 8080 порту. Для его работы потребуется токен доступа админа. Его можно взять из клиентской админской сессии. Например в Element-web токен находится в "Настройки" -> "Помощь и о программе" -> "Токен доступа" (в самом низу).

Coturn

Как ни странно больше всего геморра создал именно он. Я до сих пор не пробовал располагать его за NAT. Мой NAT ящик работает на debian, поэтому я разместил coturn прям на нём. Это первый момент. Второй момент - Element не работает с turn сервером через ssl сертификат, выпущенный LE. По итогу я вырубил ssl, так как это касается только управления, голос и видео всегда зашифрованы. Третий момент - рекомендуют список к блокировке внутренних ip, типа denied-peer-ip=192.168.0.0-192.168.255.255 (https://matrix-org.github.io/synapse/v1.41/turn-howto.html). Это правило просто блочит моё соединение, если я нахожусь на NAT, например дома. Убрал все эти denied-peer-ip. Насколько понял, моим turn сервером нельзя воспользоваться без знания static-auth-secret - и меня это устраивает.

use-auth-secret
static-auth-secret=u_ELLIE_u_ELLIE_ogHu_CJIy4auHblE_CuMBoJIbl_50_XxxX
realm=turn.example.org
no-tcp-relay
allowed-peer-ip=192.168.0.100 # Мой внутренний IP
allow-loopback-peers
user-quota=12 # 4 streams per video call, so 12 streams = 3 simultaneous relayed calls per user.
total-quota=1200
listening-ip=XX.XXX.XX.XXX # Мой внешний IP
listening-ip=192.168.0.100 # Мой внутренний IP
listening-port=3478
min-port=50000
max-port=51000
no-cli
log-file=/var/log/coturn/coturn.log
verbose

С аудио-видео звонками бывают проблемы. Не могу сказать точно в какой комбинации, но бывает соединение происходит не сразу, бывает - вообще не происходит. Проблемы возникают не часто, но тем не менее они есть. Товарищи! Где может быть зарыта собака с этим Turn? Можете поделиться работающим coturn сервером, спрятанным за NAT?

Комментарии (6)


  1. vinew
    05.06.2023 22:44

    А как быть с push на android и apple устройствах ?


  1. camojiet Автор
    05.06.2023 22:44

    С пуш на apple и android - без претензий. У меня андроид - вижу сразу же, всё как на телеге/вацапе. У шефа apple - работает отлично. При этом у шефа проблема с получением push от telegram/whatsapp (с signal - норм).


  1. EvgeniyTi
    05.06.2023 22:44
    +2

    Как быть с местом, потехоньку заполнится диск, как-то удалять например старше месяца файлы ?


  1. camojiet Автор
    05.06.2023 22:44
    +1

    Товарищ! Вы обратились прям по адресу. Я ковырял этот вопрос специально.
    Задача была в том, чтобы чистить сервер на определённую глубину (для обеспечения конфиденциальности).

    Сначала я расковырял api, чтобы сделать баш скрипт, чистящий на глубину со стороны сервера. Скрипт получился, но оказалось, что в конфиг synapse позволяет задавать глубину хранимой информации

    Вот так описывается глубина хранимой информации в homeserver.yaml:

    retention:
    enabled: true
    default_policy:
    min_lifetime: 1d
    max_lifetime: 7d

    На клиенте информация сама не чистится. Чтобы очистить инфу на клиенте, пользователю зайти в настройки и "Очистить кэш". Эта функция есть на всех клиентах.

    Писал, чем закончились мои мытарства по этой части на гитхаб сюды:
    https://github.com/matrix-org/matrix-spec/issues/1333

    Там же оставил материал, на основе которого я делал bash скрипт:
    https://foss-notes.blog.nomagic.uk/2021/03/matrix-database-house-cleaning/
    https://codeberg.org/DecaTec/Matrix-Synapse-Helpers/src/branch/main/CleanupMedia.sh

    Скрипты позволяют чистить медиаконтент и сообщения раздельно. Возможностей по очистке, в общем более чем.


  1. dhaluza
    05.06.2023 22:44
    +1

    Я вот поднял в организации в кубе. Турн на пограничной зоне. Коллы работают, а вот шаринг экрана не у каждого пользователя активный(нет кнопок у пользователя) , как победить пока хз.


    1. camojiet Автор
      05.06.2023 22:44

      3 мес назад, когда внедрял, если с apple звонить на android по видео, то картинка шла только в одну сторону. Голос - в две. Нашёл ветку с проблемой, выяснилось, что на apple опаздывает matrix SDK. Через месяц вышла новая версия ios клиента и проблема ушла. На андроид 13-ом тоже были замечены проблемы с клиентом.
      На какой ОС у вас не шарится экран? Какой клиент используете? Обновляете клиент? Проверю у себя, отпишусь.