惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cisco Talos Blog
Cisco Talos Blog
V
V2EX
C
Check Point Blog
GbyAI
GbyAI
D
Docker
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
B
Blog RSS Feed
H
Hackread – Cybersecurity News, Data Breaches, AI and More
N
Netflix TechBlog - Medium
T
Troy Hunt's Blog
博客园 - Franky
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Microsoft Security Blog
Microsoft Security Blog
P
Privacy & Cybersecurity Law Blog
WordPress大学
WordPress大学
The Cloudflare Blog
S
SegmentFault 最新的问题
Latest news
Latest news
Microsoft Azure Blog
Microsoft Azure Blog
P
Proofpoint News Feed
I
InfoQ
博客园 - 【当耐特】
NISL@THU
NISL@THU
A
About on SuperTechFans
T
Tailwind CSS Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
The Hacker News
The Hacker News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Scott Helme
Scott Helme
雷峰网
雷峰网
C
CXSECURITY Database RSS Feed - CXSecurity.com
Security Latest
Security Latest
V
Vulnerabilities – Threatpost
Security Archives - TechRepublic
Security Archives - TechRepublic
A
Arctic Wolf
Hacker News: Ask HN
Hacker News: Ask HN
N
News and Events Feed by Topic
IT之家
IT之家
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
aimingoo的专栏
aimingoo的专栏
T
Threat Research - Cisco Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
阮一峰的网络日志
阮一峰的网络日志
SecWiki News
SecWiki News
大猫的无限游戏
大猫的无限游戏
S
Security Affairs
The Register - Security
The Register - Security
www.infosecurity-magazine.com
www.infosecurity-magazine.com
L
LINUX DO - 热门话题
T
Tor Project blog

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Настраиваем Matrix сервер
nvbxak · 2026-04-26 · via Все публикации подряд на Хабре

Уровень сложностиПростой

Время на прочтение13 мин

Охват и читатели229

Туториал

Полное руководство по развёртыванию приватного Matrix-сервера с Google-аутентификацией, видеозвонками, Telegram и WhatsApp мостами.

💡 Matrix — это не просто очередной мессенджер, а открытый децентрализованный протокол. Это ваш собственный «Дом», где вы контролируете данные, а не Google или Meta. В этом руководстве я пошагово расскажу, как собрать из готовых компонентов свой идеальный чат-сервер: с авторизацией через Google, видеозвонками высокого качества, двусторонними мостами в Telegram и WhatsApp, а также с веб-интерфейсом. Инструкция рассчитана на новичков, но будет полезна и опытным администраторам

Никогда не писал статьи, особенно здесь, но попытавшись найти нормальную инструкцию для разворачивания сервера Matrix с Google-аутентификацией, видеозвонками мостом Telegram и WhatsApp понял, что они либо не подходят, либо не учитывают нюансы Google-аутентификации (например не все админские сайты подходят и клиенты), часть инструкций, даже на официальном сайте, указаны не верно. В данной статье я постарался максимально точно расписать очерёдность настройки различных модулей. Надеюсь данная инструкция будем вам полезна. Если будут вопросы пишите, чем смогу помогу.

Так же отвечу на возможный вопрос, для чего всё это нужно. Не для кого не секрет, что работа telegram в данный момент не отличается стабильностью. А данный сервер с мостом в telegram позволяет оставаться на связи даже во время работы белых списков (зависит от города).

В этом гайде мы соберём из готовых Docker-контейнеров полнофункциональный Matrix-сервер для семьи или небольшой компании, который включает:

  • 🔐 Вход через Google (а также поддержку обычных логинов/паролей);

  • 🎥 Видеозвонки на базе LiveKit (я их ещё тестирую, качество среднее, но работает);

  • 🔄 Двусторонние мосты в Telegram и WhatsApp (читайте и отвечайте на сообщения прямо из Matrix);

  • 🖥 Красивый веб-клиент Element Web на вашем домене;

  • ⚙️ Удобную админ-панель Ketesa для управления пользователями и комнатами.

Инструкция писалась для Debian 13, но подойдёт для любого дистрибутива Linux с Docker.


📋 Оглавление

  1. Требования к серверу и подготовка

  2. Структура проекта и переменные окружения

  3. Установка Synapse + PostgreSQL + Element Web

  4. Настройка Matrix Authentication Service (MAS) для входа через Google

  5. Разворачиваем видеозвонки с LiveKit

  6. Добавляем мосты в Telegram и WhatsApp

  7. Установка админ-панели Ketesa

  8. Настройка Nginx и SSL

  9. Запуск, создание администратора и авторизация

  10. Частые проблемы и их решения

1. Требования к серверу и подготовка

Минимальные требования:

Параметр

Значение

ОС

Debian 13

CPU

2–4 ядра

RAM

4–8 ГБ (рекомендуется 6+)

Диск

30–40 ГБ (если будете активно общаться лучше сразу выделить 100 ГБ)

Домен 1

matrix.ваш-домен.ru — основной домен

Домен 2

livekit.ваш-домен.ru — для видеозвонков

1.1 Подготовка системы

Подключаемся к серверу по SSH и выполняем базовые команды:

sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget git ufw pwgen

1.2 Установка Docker и Docker Compose

Устанавливаем Docker по официальному скрипту (это проще всего):

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER
newgrp docker

Устанавливаем плагин Docker Compose V2:

sudo apt install -y docker-compose-plugin

1.3 Настройка фаервола (UFW)

Открываем необходимые порты (можно сделать позже):

sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 3478/tcp
sudo ufw allow 3478/udp
sudo ufw allow 5349/tcp
sudo ufw allow 5349/udp
sudo ufw allow 7880/tcp
sudo ufw allow 7881/tcp
sudo ufw allow 50000:50200/udp
sudo ufw enable

1.4 Создание структуры папок

Все наши файлы будут лежать в /opt/matrix-synapse:

sudo mkdir -p /opt/matrix-synapse/{data,element-web,mautrix-telegram,mautrix-whatsapp,livekit,mas-config}
sudo chown -R $USER:$USER /opt/matrix-synapse
cd /opt/matrix-synapse

2. Структура проекта и переменные окружения

Чтобы не «засорять» конфиги паролями, создадим файл .env. Сгенерируйте значения командой pwgen -s 32 1.

nano .env
# Основные секреты Synapse
SYNAPSE_POSTGRES_PASSWORD=YOUR_POSTGRES_PASSWORD_HERE1
SYNAPSE_REGISTRATION_SHARED_SECRET=YOUR_REGISTRATION_SHARED_SECRET_HERE2
SYNAPSE_MACAROON_SECRET_KEY=YOUR_MACAROON_SECRET_HERE3
SYNAPSE_FORM_SECRET=YOUR_FORM_SECRET_HERE4
SYNAPSE_TURN_SHARED_SECRET=YOUR_TURN_SHARED_SECRET_HERE5

# MAS
MAS_POSTGRES_PASSWORD=YOUR_MAS_POSTGRES_PASSWORD_HERE6
MAS_SHARED_SECRET=YOUR_MAS_SHARED_SECRET_HERE7

# LiveKit
LIVEKIT_API_KEY=YOUR_LIVEKIT_API_KEY_HERE8
LIVEKIT_API_SECRET=YOUR_LIVEKIT_API_SECRET_HERE9

# Telegram Bridge
TELEGRAM_POSTGRES_PASSWORD=YOUR_TELEGRAM_POSTGRES_PASSWORD_HERE10

# WhatsApp Bridge
WHATSAPP_POSTGRES_PASSWORD=YOUR_WHATSAPP_POSTGRES_PASSWORD_HERE11

3. Установка Synapse + PostgreSQL + Element Web

Создаём главный файл оркестрации docker-compose.yml:

nano docker-compose.yml
📄 Полный docker-compose.yml (нажмите, чтобы развернуть)
services:
  # ==================== БАЗА ДАННЫХ SYNAPSE ====================
  postgres:
    image: postgres:15-alpine
    container_name: matrix_postgres
    restart: unless-stopped
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: synapse
      POSTGRES_USER: synapse
      POSTGRES_PASSWORD: ${SYNAPSE_POSTGRES_PASSWORD}
    networks:
      - matrix_network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U synapse"]
      interval: 10s
      timeout: 5s
      retries: 5

  # ==================== SYNAPSE ====================
  synapse:
    image: matrixdotorg/synapse:v1.151.0rc1
    container_name: matrix_synapse
    restart: unless-stopped
    volumes:
      - ./data:/data
      - ./logs:/var/log/synapse
    ports:
      - "8008:8008"
      - "9000:9000"
    environment:
      SYNAPSE_SERVER_NAME: matrix.ваш-домен.ru
      SYNAPSE_REPORT_STATS: "no"
    networks:
      - matrix_network
    depends_on:
      - postgres
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8008/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  # ==================== БАЗА ДАННЫХ MAS ====================
  matrix-auth-db:
    image: postgres:15-alpine
    container_name: matrix_auth_db
    restart: unless-stopped
    volumes:
      - ./matrix-auth-db:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: matrix_auth
      POSTGRES_USER: matrix_auth
      POSTGRES_PASSWORD: ${MAS_POSTGRES_PASSWORD}
    networks:
      - matrix_network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U matrix_auth"]
      interval: 10s
      timeout: 5s
      retries: 5

  # ==================== MATRIX AUTHENTICATION SERVICE (MAS) ====================
  matrix-auth:
    image: ghcr.io/element-hq/matrix-authentication-service:latest
    container_name: matrix_authentication_service
    restart: unless-stopped
    depends_on:
      matrix-auth-db:
        condition: service_healthy
      synapse:
        condition: service_started
    volumes:
      - ./mas-config:/config:ro
    environment:
      - MAS_CONFIG=/config/config.yaml
    networks:
      - matrix_network
    ports:
      - "127.0.0.1:8081:8080"

  # ==================== ELEMENT WEB ====================
  element-web:
    image: vectorim/element-web:latest
    container_name: element_web
    restart: unless-stopped
    volumes:
      - ./element-web/config.json:/app/config.json:ro
    ports:
      - "127.0.0.1:8765:80"
    networks:
      - matrix_network
    depends_on:
      - synapse

  # ==================== KETESA (АДМИН-ПАНЕЛЬ) ====================
  ketesa:
    container_name: ketesa
    hostname: ketesa
    build:
      context: https://github.com/etkecc/ketesa.git
      dockerfile: docker/Dockerfile.build
    ports:
      - "8181:8080"
    restart: unless-stopped
    networks:
      - matrix_network

  # ==================== БАЗА ДАННЫХ TELEGRAM ====================
  telegram-db:
    image: postgres:15-alpine
    container_name: telegram_db
    restart: unless-stopped
    volumes:
      - ./telegram-db:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: telegram
      POSTGRES_USER: telegram
      POSTGRES_PASSWORD: ${TELEGRAM_POSTGRES_PASSWORD}
    networks:
      - matrix_network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U telegram"]
      interval: 10s
      timeout: 5s
      retries: 5

  # ==================== TELEGRAM BRIDGE ====================
  telegram-bridge:
    image: dock.mau.dev/mautrix/telegram:latest
    container_name: telegram_bridge
    restart: unless-stopped
    volumes:
      - ./mautrix-telegram:/data
    environment:
      - UID=991
      - GID=991
    networks:
      - matrix_network
    ports:
      - "127.0.0.1:29317:29317"
    depends_on:
      telegram-db:
        condition: service_healthy
      synapse:
        condition: service_started

  # ==================== БАЗА ДАННЫХ WHATSAPP ====================
  whatsapp-db:
    image: postgres:15-alpine
    container_name: whatsapp_db
    restart: unless-stopped
    volumes:
      - ./whatsapp-db:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: whatsapp
      POSTGRES_USER: whatsapp
      POSTGRES_PASSWORD: ${WHATSAPP_POSTGRES_PASSWORD}
    networks:
      - matrix_network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U whatsapp"]
      interval: 10s
      timeout: 5s
      retries: 5

  # ==================== WHATSAPP BRIDGE ====================
  whatsapp-bridge:
    image: dock.mau.dev/mautrix/whatsapp:latest
    container_name: mautrix-whatsapp
    restart: unless-stopped
    volumes:
      - ./mautrix-whatsapp:/data
    environment:
      - UID=1337
      - GID=1337
    networks:
      - matrix_network
    depends_on:
      - synapse

  # ==================== LIVEKIT JWT SERVICE ====================
  livekit-jwt:
    image: ghcr.io/element-hq/lk-jwt-service:latest
    container_name: livekit-jwt
    restart: unless-stopped
    environment:
      - LIVEKIT_URL=wss://livekit.ваш-домен.ru
      - LIVEKIT_KEY=${LIVEKIT_API_KEY}
      - LIVEKIT_SECRET=${LIVEKIT_API_SECRET}
      - LIVEKIT_JWT_BIND=:8080
    ports:
      - "127.0.0.1:8088:8080"
    networks:
      - matrix_network

  # ==================== LIVEKIT SERVER ====================
  livekit:
    image: livekit/livekit-server:latest
    container_name: livekit
    command: --config /etc/livekit.yaml
    restart: unless-stopped
    volumes:
      - ./livekit/livekit.yaml:/etc/livekit.yaml:ro
    network_mode: host

networks:
  matrix_network:
    driver: bridge

3.1 Базовый конфиг Synapse (homeserver.yaml)

Генерируем первоначальный конфиг:

docker run -it --rm \
  -v /opt/matrix-synapse/data:/data \
  -e SYNAPSE_SERVER_NAME=matrix.ваш-домен.ru \
  -e SYNAPSE_REPORT_STATS=no \
  matrixdotorg/synapse:v1.151.0rc1 generate

Редактируем /opt/matrix-synapse/data/homeserver.yaml:

nano /opt/matrix-synapse/data/homeserver.yaml
📄 Ключевые изменения в homeserver.yaml
# База данных (указываем PostgreSQL вместо SQLite)
database:
  name: psycopg2
  args:
    user: synapse
    password: YOUR_SYNAPSE_POSTGRES_PASSWORD
    database: synapse
    host: postgres
    port: 5432

# Отключаем старую регистрацию (всё будет через MAS)
enable_registration: false

# Включаем поддержку Matrix Authentication Service (MAS)
matrix_authentication_service:
  enabled: true
  endpoint: http://matrix-auth:8080
  secret: "YOUR_MAS_SHARED_SECRET"
  allow_appservice_registration: true

# Настройки TURN/STUN (для звонков)
turn_uris:
  - "turn:matrix.ваш-домен.ru:3478?transport=udp"
  - "turns:matrix.ваш-домен.ru:5349?transport=tcp"
turn_shared_secret: "YOUR_TURN_SHARED_SECRET"

# Экспериментальные фичи для видеозвонков (обязательно!)
experimental_features:
  msc3266_enabled: true
  msc4222_enabled: true
  msc4140_enabled: true
  msc4143_enabled: true

# Интеграция с LiveKit
livekit_jwt_sso:
  enabled: true
  livekit_jwt_sso_url: "https://matrix.ваш-домен.ru/livekit/jwt/token"
  livekit_key: "YOUR_LIVEKIT_API_KEY"
  livekit_secret: "YOUR_LIVEKIT_API_SECRET"

# Подключение мостов (appservices)
app_service_config_files:
  - "/data/telegram-registration.yaml"
  - "/data/whatsapp-registration.yaml"

3.2 Конфиг веб-клиента Element Web

nano element-web/config.json
{
    "default_server_config": {
        "m.homeserver": {
            "base_url": "https://matrix.ваш-домен.ru",
            "server_name": "matrix.ваш-домен.ru"
        }
    },
    "disable_custom_urls": false,
    "disable_guests": true,
    "brand": "Чат ваш-домен.ru",
    "default_theme": "dark",
    "room_directory": {
        "servers": ["matrix.ваш-домен.ru"]
    },
    "livekit_service_url": "wss://matrix.ваш-домен.ru/rtc"
}

4. Настройка Matrix Authentication Service (MAS) для входа через Google

MAS — это сервис от Element, который берёт на себя управление пользователями и аутентификацию (в том числе через Google OAuth 2.0).

4.1 Конфигурация MAS

nano mas-config/config.yaml
http:
  public_base: "https://matrix.ваш-домен.ru"
  issuer: "https://matrix.ваш-домен.ru"
  listeners:
    - name: web
      resources:
        - name: discovery
        - name: human
        - name: oauth
        - name: compat
        - name: graphql
        - name: assets
      binds:
        - address: '0.0.0.0'
          port: 8080
    - name: internal
      resources:
        - name: health
      binds:
        - host: localhost
          port: 8081

database:
  uri: "postgresql://matrix_auth:YOUR_MAS_POSTGRES_PASSWORD@matrix-auth-db/matrix_auth"

secrets:
  encryption: "YOUR_ENCRYPTION_KEY"  # openssl rand -hex 32

matrix:
  kind: synapse
  homeserver: matrix.ваш-домен.ru
  secret: "YOUR_MAS_SHARED_SECRET"
  endpoint: "http://synapse:8008"

upstream_oauth2:
  providers:
    - id: 01HFS6S2SVAR7Y7QYMZJ53ZAGZ  # Уникальный ULID
      human_name: Google
      brand_name: "google"
      issuer: "https://accounts.google.com"
      token_endpoint_auth_method: "client_secret_post"
      client_id: "YOUR_GOOGLE_CLIENT_ID"
      client_secret: "YOUR_GOOGLE_CLIENT_SECRET"
      scope: "openid profile email"
      claims_imports:
        localpart:
          action: ignore
        displayname:
          action: suggest
          template: "{{ user.name }}"
        email:
          action: suggest
          template: "{{ user.email }}"

registration:
  enabled: true

4.2 Получение ключей Google OAuth 2.0

  1. Перейдите в Google Cloud Console.

  2. Создайте проект и включите People API.

  3. В разделе «Учетные данные» создайте OAuth Client ID типа «Веб-приложение».

  4. В поле «Authorized redirect URIs» добавьте: https://matrix.ваш-домен.ru/upstream/callback/01HFS6S2SVAR7Y7QYMZJ53ZAGZ

  5. Скопируйте Client ID и Client Secret в конфиг выше.

5. Разворачиваем видеозвонки с LiveKit

LiveKit — это современный Selective Forwarding Unit (SFU), обеспечивающий качественные групповые видеозвонки.

5.1 Конфиг LiveKit

nano livekit/livekit.yaml
port: 7880
bind_addresses:
  - '0.0.0.0'
rtc:
  tcp_port: 7881
  port_range_start: 50000
  port_range_end: 50200
  use_external_ip: true
room:
  auto_create: true
turn:
  enabled: true
  domain: livekit.ваш-домен.ru
  udp_port: 3478
  tls_port: 5349
  external_tls: true
keys:
  "YOUR_LIVEKIT_API_KEY": "YOUR_LIVEKIT_API_SECRET"

5.2 JWT-сервис уже добавлен в docker-compose.yml

Он необходим для выдачи временных токенов доступа к комнатам видеозвонков.

6. Добавляем мосты в Telegram и WhatsApp

Мосты позволяют читать и отправлять сообщения из Matrix в Telegram и WhatsApp.

6.1 Telegram Bridge

  1. Получите API-ключи на my.telegram.org/apps. (там есть нюанс с ошибкой при создании ключей, пишет просто "Ошибка", проблема известная и гуглится, мне помогло вход с мобильного интернета, с телефона)

  2. Создайте бота в Telegram через @BotFather и получите bot_token.

Создайте конфиг:

nano mautrix-telegram/config.yaml
network:
    api_id: YOUR_TELEGRAM_API_ID
    api_hash: "YOUR_TELEGRAM_API_HASH"
    device_info:
        lang_code: ru
        system_lang_code: ru

homeserver:
    address: http://synapse:8008
    domain: matrix.ваш-домен.ru

appservice:
    address: http://telegram-bridge:29317
    hostname: 0.0.0.0
    port: 29317
    database: postgres://telegram:YOUR_TELEGRAM_POSTGRES_PASSWORD@telegram-db/telegram?sslmode=disable
    bot:
        username: telegram_bot
        displayname: Telegram Bridge Bot

bridge:
    permissions:
        "matrix.ваш-домен.ru": user
        "@YOUR_USERNAME:matrix.ваш-домен.ru": admin

encryption:
    allow: true
    default: true
    msc4190: true
    self_sign: true

Генерация регистрации:

docker run --rm -v /opt/matrix-synapse/mautrix-telegram:/data dock.mau.dev/mautrix/telegram:latest
cp /opt/matrix-synapse/mautrix-telegram/registration.yaml /opt/matrix-synapse/data/telegram-registration.yaml

6.2 WhatsApp Bridge

Создайте конфиг:

nano mautrix-whatsapp/config.yaml
homeserver:
    address: http://synapse:8008
    domain: matrix.ваш-домен.ru

appservice:
    address: http://whatsapp-bridge:29318
    hostname: 0.0.0.0
    port: 29318
    database: postgres://whatsapp:YOUR_WHATSAPP_POSTGRES_PASSWORD@whatsapp-db/whatsapp?sslmode=disable
    bot:
        username: whatsappbot
        displayname: WhatsApp Bridge Bot

bridge:
    permissions:
        "matrix.ваш-домен.ru": user
        "@YOUR_USERNAME:matrix.ваш-домен.ru": admin

encryption:
    allow: true
    default: true
    msc4190: true
    self_sign: true

Генерация регистрации:

docker run --rm -v /opt/matrix-synapse/mautrix-whatsapp:/data dock.mau.dev/mautrix/whatsapp:latest
cp /opt/matrix-synapse/mautrix-whatsapp/registration.yaml /opt/matrix-synapse/data/whatsapp-registration.yaml

7. Установка админ-панели Ketesa

Ketesa — современная админ-панель для Matrix. В docker-compose.yml она уже добавлена. Настройка доступа через Nginx будет в следующем разделе.

8. Настройка Nginx и SSL

Устанавливаем Nginx и Certbot:

sudo apt install -y nginx certbot python3-certbot-nginx

Получаем сертификаты:

sudo certbot certonly --nginx -d matrix.ваш-домен.ru -d livekit.ваш-домен.ru

Создаём конфиг Nginx:

sudo nano /etc/nginx/sites-available/matrix
📄 Полный конфиг Nginx (нажмите, чтобы развернуть)
# Редирект HTTP -> HTTPS
server {
    listen 80;
    listen [::]:80;
    server_name matrix.YOUR_DOMAIN.ru;
    location ^~ /.well-known/acme-challenge/ {
        root /var/www/html;
    }
    location / {
        return 301 https://$host$request_uri;
    }
}

# Основной сервер
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name matrix.YOUR_DOMAIN.ru;

    ssl_certificate     /etc/letsencrypt/live/matrix.YOUR_DOMAIN.ru/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/matrix.YOUR_DOMAIN.ru/privkey.pem;

    client_max_body_size 50M;
    proxy_read_timeout 600s;

    # Element Web
    location / {
        proxy_pass http://127.0.0.1:8765/;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        add_header X-Frame-Options SAMEORIGIN;
    }

    # Well-known для клиентов
    location = /.well-known/matrix/client {
        default_type application/json;
        add_header Access-Control-Allow-Origin * always;
        return 200 '{
            "m.homeserver": {"base_url": "https://matrix.YOUR_DOMAIN.ru"},
            "org.matrix.msc4143.rtc_foci": [{"type": "livekit", "livekit_service_url": "https://matrix.YOUR_DOMAIN.ru/livekit/jwt"}]
        }';
    }

    # Прокси для MAS (авторизация, OAuth2)
    location ~ ^/(oauth2|authorize|login|callback|account|graphql|upstream) {
        proxy_pass http://127.0.0.1:8081;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # Прокси для LiveKit JWT
    location /livekit/jwt/ {
        proxy_pass http://127.0.0.1:8088/;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # API Synapse
    location ~ ^(/_matrix|/_synapse/client|/_synapse/admin|/_synapse/mas) {
        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-Forwarded-Proto $scheme;
    }
}

# Сервер для LiveKit
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name livekit.YOUR_DOMAIN.ru;

    ssl_certificate     /etc/letsencrypt/live/livekit.YOUR_DOMAIN.ru/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/livekit.YOUR_DOMAIN.ru/privkey.pem;

    location / {
        proxy_pass http://localhost:7880;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Активируем конфиг и перезагружаем Nginx:

sudo ln -s /etc/nginx/sites-available/matrix /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

9. Запуск, создание администратора и авторизация

Запускаем все сервисы:

cd /opt/matrix-synapse
docker compose up -d

Создаём первого пользователя-администратора:

docker exec -it matrix_synapse register_new_matrix_user -c /data/homeserver.yaml -u admin -p YOUR_PASSWORD --admin

Теперь откройте в браузере https://matrix.ваш-домен.ru. Вы увидите страницу входа Element Web. Вы можете войти:

  • Через Google (кнопка «Continue with Google»);

  • Как администратор с логином admin и паролем, который вы задали.

9.1. Настройка Telegram Bridge

  1. В Element найдите бота @telegram_bot:matrix.YOUR_DOMAIN.ru

  2. Отправьте ему команду login phone (вход через QR код не заработал)

  3. Введите код авторизации присланный в Telegram

9.2. Настройка WhatsApp Bridge

  1. Найдите бота @whatsappbot:matrix.YOUR_DOMAIN.ru

  2. Отправьте ему команду login

  3. Отсканируйте QR-код через WhatsApp на телефоне

10. Частые проблемы и их решения

⚠️ Ошибка The as_token was not accepted (мост не запускается)

Решение: Перегенерируйте registration.yaml для соответствующего моста и перезапустите Synapse (docker compose restart synapse). Убедитесь, что путь к файлу регистрации прописан в app_service_config_files в homeserver.yaml.

⚠️ Ошибка M_FORBIDDEN: Application service cannot masquerade as this user

Решение: Пользователь бота (например, @telegram_bot:...) не создан в Synapse. Создайте его вручную через register_new_matrix_user или через SQL.

⚠️ Ошибка 429 Too Many Requests

Решение: Подождите 30–60 секунд — ограничение снимется автоматически. Если проблема повторяется часто, увеличьте лимиты в homeserver.yaml (параметры rc_message, rc_joins).

⚠️ Видеозвонки работают только в одну сторону или не работают совсем

Решение:
1. Убедитесь, что порт 7880 и диапазон 50000-50200/udp открыты в UFW.
2. Проверьте, что в livekit.yaml правильно указан external_ip (ваш реальный IP сервера).
3. Убедитесь, что клиент (Element) имеет доступ к wss://livekit.ваш-домен.ru (проверьте через консоль браузера).

⚠️ Мост Telegram не отвечает на команды

Решение: Проверьте логи моста: docker compose logs telegram-bridge. Убедитесь, что в конфиге указаны верные api_id, api_hash и bot_token. Бот должен быть создан в Telegram и не заблокирован.


Заключение

Поздравляю! Вы стали полноправным хозяином своей коммуникационной инфраструктуры. Ваш сервер поддерживает видеозвонки, удобный вход через Google и интеграцию с популярными мессенджерами. Все компоненты упакованы в Docker, что упрощает резервное копирование перенос и обновление.

Полезные ссылки:


Удачи в настройке! 🚀