fix: cyrillic fonts, dev certs, page head, and ru-text typography (#67)

🤖 PR generated for branch `fix/cyrillic-fonts-dev-certs-and-page-head`.

### Changes Summary
- **Fonts**: Add Cyrillic glyph subsets for Lato, EB Garamond, and Fira
Code.
- **Dev**: Support remote Root CA and encrypted dev CA key in
`.env.dev`.
- **UI & Kits**: Add size variant to `Breadcrumbs` component and enlarge
`PageHead` breadcrumbs with tuned collapse scroll threshold.
- **ESLint**: Add `no-hanging-particles` i18n & markdown typography rule
with auto-fixer.
- **Content & i18n**: Apply `ru-text` editorial and typography polish
(em dashes, number ranges, «ё» restoration, non-breaking spaces) across
`services/www` and `services/docs`.
This commit is contained in:
deytenit authored and GitHub committed 2026-10-25 15:21:09 +03:00
1 parent c6487dc258
commit b3638f4d63
111 files changed
+2350 -1512

No files matched your search

@@ -1,43 +1,43 @@
---
title: 'Руководство по развёртыванию Matrix-сервера'
description: 'Разбор архитектуры и развёртывание Synapse, Coturn, LiveKit SFU и Native Matrix RTC'
title: 'Руководство по развёртыванию Matrix-сервера'
description: 'Разбор архитектуры и развёртывание Synapse, Coturn, LiveKit SFU и Native Matrix RTC'
createdDate: 2026-02-15
tags: ['self-hosting', 'guides', 'matrix']
---
Развёртывание полноценного стека связи Matrix не ограничивается запуском единого веб-сервера. Matrix представляет собой открытый децентрализованный протокол для безопасного сквозного шифрования сообщений и голосовой связи в реальном времени. Если для текстовых чатов достаточно базового homeserver и базы данных, то современные мультимедийные возможности — от личных WebRTC-звонков 1:1 до групповых видеоконференций — требуют специализированных медиа-релеев и мостов аутентификации.
Развёртывание полноценного стека связи Matrix не ограничивается запуском одного веб-сервера. Matrix — открытый децентрализованный протокол для голосовой связи и обмена сообщениями со сквозным шифрованием в реальном времени. Если для текстовых чатов достаточно базового homeserver и базы данных, то современные мультимедийные возможности — от личных WebRTC-звонков 1:1 до групповых видеоконференций — требуют специализированных медиарелеев и мостов аутентификации.
В этой статье подробно разбирается устройство и пошаговое развёртывание производственного стека Matrix на базе **Synapse**, **PostgreSQL**, **Coturn**, **LiveKit SFU** и **lk-jwt-service**.
В статье разберём устройство и пошаговое развёртывание стека Matrix для продакшена на базе **Synapse**, **PostgreSQL**, **Coturn**, **LiveKit SFU** и **lk-jwt-service**.
---
## Архитектура технического стека
Чтобы понять взаимодействие компонентов, разберем задачи каждого из пяти ключевых сервисов:
Чтобы понять взаимодействие компонентов, разберём задачи каждого из шести ключевых компонентов:
1. **Synapse**: Основной движок homeserver. Управляет аутентификацией пользователей, состоянием комнат, синхронизацией сообщений, обменом ключами сквозного шифрования (E2EE) и федерацией с другими серверами в глобальной сети Matrix.
2. **PostgreSQL**: Реляционная база данных для Synapse. Если для коротких локальных тестов Synapse допускает SQLite, то в продакшене PostgreSQL обязателен для обработки параллельных транзакций, индексации комнат и истории сообщений.
3. **Coturn (STUN/TURN)**: Сервер ретрансляции для обхода NAT. При звонке 1:1 устройства пытаются установить прямое peer-to-peer WebRTC-соединение. Если между участниками есть симметричный NAT или фаервол, Coturn выступает в роли ретранслятора, передавая зашифрованные аудио- и видеопакеты по протоколам UDP или TCP.
4. **LiveKit SFU**: Высокопроизводительный Selective Forwarding Unit. Соединение peer-to-peer становится неэффективным при групповых звонках от трех участников. LiveKit принимает видео/аудиопотоки от каждого спикера и перенаправляет их остальным участникам, существенно экономя исходящий интернет-трафик клиентов.
5. **lk-jwt-service**: Мост аутентификации для Element Call и Element X Native Matrix RTC (стандарты MSC4143 и MSC4186). Когда пользователь входит в групповой звонок в Element X, `lk-jwt-service` проверяет его сессию в Synapse и генерирует временный токен JWT для подключения к комнате LiveKit.
6. **Обратный прокси (Traefik / Nginx)**: Входной шлюз. Терминирует SSL-сертификаты, обрабатывает WebSocket-соединения для сигнализации LiveKit (`/livekit`), проставляет заголовки CORS для веб-клиентов и отдаёт файлы автообнаружения `.well-known`.
1. **Synapse**: Основной движок homeserver. Управляет аутентификацией пользователей, состоянием комнат, синхронизацией сообщений, обменом ключами сквозного шифрования (E2EE) и федерацией с другими серверами в глобальной сети Matrix.
2. **PostgreSQL**: Реляционная база данных для Synapse. Если для коротких локальных тестов Synapse допускает SQLite, то в продакшене PostgreSQL обязателен для обработки параллельных транзакций, индексации комнат и истории сообщений.
3. **Coturn (STUN/TURN)**: Сервер ретрансляции для обхода NAT. При звонке 1:1 устройства пытаются установить прямое peer-to-peer WebRTC-соединение. Если между участниками есть симметричный NAT или фаервол, Coturn служит ретранслятором и передаёт зашифрованные аудио- и видеопакеты по протоколам UDP или TCP.
4. **LiveKit SFU**: Высокопроизводительный Selective Forwarding Unit. Соединение peer-to-peer становится неэффективным при групповых звонках от трёх участников. LiveKit принимает аудио- и видеопотоки каждого спикера и пересылает их остальным участникам, существенно экономя исходящий интернет-трафик клиентов.
5. **lk-jwt-service**: Мост аутентификации для Element Call и Element X Native Matrix RTC (стандарты MSC4143 и MSC4186). Когда пользователь входит в групповой звонок в Element X, `lk-jwt-service` проверяет его сессию в Synapse и генерирует временный токен JWT для подключения к комнате LiveKit.
6. **Обратный прокси (Traefik / Nginx)**: Входной шлюз. Терминирует SSL-сертификаты, обрабатывает WebSocket-соединения для сигнализации LiveKit (`/livekit`), проставляет заголовки CORS для веб-клиентов и отдаёт файлы автообнаружения `.well-known`.
---
## 1. Инфраструктура Docker (docker-compose.yml)
Контейнеризация обеспечит изоляцию сервисов, правильный порядок их запуска и предсказуемую сетевую связность.
Контейнеризация обеспечит изоляцию сервисов, правильный порядок их запуска и предсказуемую сетевую связность.
В нашем файле compose для PostgreSQL настроена проверка готовности (`pg_isready`), чтобы Synapse не запускался до полного создания базы данных. Дополнительные сервисы, такие как Coturn, LiveKit и `lk-jwt-service`, используют сетевой режим `network_mode: "service:synapse"` или выделенные сети контейнеров, что пробрасывает порты WebRTC и STUN/TURN непосредственно на хост.
В конфигурации Compose для PostgreSQL настроена проверка готовности (`pg_isready`), чтобы Synapse не запускался до полной инициализации базы данных. Дополнительные сервисы, такие как Coturn, LiveKit и `lk-jwt-service`, используют сетевой режим `network_mode: "service:synapse"` или выделенные сети контейнеров, что пробрасывает порты WebRTC и STUN/TURN непосредственно на хост.
Для корректной передачи медиапотоков открываются следующие диапазона портов:
- **Порты 3478 и 5349 (TCP/UDP)**: Сигнализация Coturn STUN и TURN.
- **Диапазон 49152-49172 (UDP)**: Динамические каналы ретрансляции медиа Coturn.
- **Порт 7880 (TCP)**: HTTP-сигнализация и WebSockets в LiveKit.
- **Порт 7881 (TCP)**: Резервный TCP-порт для WebRTC в LiveKit.
- **Диапазон 50000-50020 (UDP)**: Каналы передаче медиа в LiveKit SFU.
Для корректной передачи медиапотоков открываются следующие диапазоны портов:
- **Порты 3478 и 5349 (TCP/UDP)**: Сигнализация Coturn STUN и TURN.
- **Диапазон 49152–49172 (UDP)**: Динамические каналы ретрансляции медиа Coturn.
- **Порт 7880 (TCP)**: HTTP-сигнализация и WebSockets в LiveKit.
- **Порт 7881 (TCP)**: Резервный TCP-порт для WebRTC в LiveKit.
- **Диапазон 50000–50020 (UDP)**: Каналы передачи медиа в LiveKit SFU.
Итоговый файл `docker-compose.yml` содержит следующую конфигурацию:
Итоговый файл `docker-compose.yml`:
```yaml
networks:
@@ -142,15 +142,15 @@ services:
## 2. Конфигурация Homeserver (homeserver.yaml)
Synapse использует `homeserver.yaml` для определения правил работы. Разберем ключевые блоки:
Synapse использует `homeserver.yaml` для определения правил работы. Разберём ключевые блоки:
- **Идентификация сервера (`server_name`)**: Определяет доменное имя вашего сервера и суффикс ID пользователей (например, `@user:matrix.example.com`). Изменение этого имени в будущем приведет к потере связей с другими серверами и поломке ID комнат.
- **Подключение к базе данных (`database`)**: Настраивает подключение к PostgreSQL через модуль `psycopg2`. Параметры `cp_min` и `cp_max` управляют пулом соединений при нагрузке.
- **Ротация медиафайлов (`media_retention`)**: Участники комнат регулярно отправляют фото и файлы. Параметр `remote_media_lifetime: 14d` регулярно удаляет кэш файлов с чужих серверов, сохраняя дисковое пространство (локальные файлы хранятся в течение года `local_media_lifetime: 365d`).
- **Интеграция VoIP (`turn_uris` и `turn_shared_secret`)**: Передает Synapse параметры Coturn. При звонке 1:1 Synapse с помощью `turn_shared_secret` генерирует временные логин и пароль для безопасного подключения к TURN-релею.
- **Native Matrix RTC (MSC4143 / MSC4186)**: Современные клиенты, такие как Element X и Element Call, используют спецификации MSC4143 (RTC Foci) и MSC4186 (LiveKit Call Authentication). Блок `extra_well_known_client_content` сообщает клиенту, что выпиской токенов для звонков занимается сервис `lk-jwt-service` по адресу `https://matrix.example.com/livekit/jwt`.
- **Идентификация сервера (`server_name`)**: Определяет доменное имя сервера и суффикс ID пользователей (например, `@user:matrix.example.com`). Изменение этого имени в будущем приведёт к потере связей с другими серверами и поломке ID комнат.
- **Подключение к базе данных (`database`)**: Настраивает подключение к PostgreSQL через модуль `psycopg2`. Параметры `cp_min` и `cp_max` управляют пулом соединений при нагрузке.
- **Ротация медиафайлов (`media_retention`)**: Участники комнат постоянно отправляют фото и файлы. Параметр `remote_media_lifetime: 14d` очищает кэш файлов с чужих серверов каждые 14 дней, экономя дисковое пространство (локальные файлы хранятся в течение года: `local_media_lifetime: 365d`).
- **Интеграция VoIP (`turn_uris` и `turn_shared_secret`)**: Передаёт Synapse параметры Coturn. При звонке 1:1 Synapse с помощью `turn_shared_secret` генерирует временные логин и пароль для безопасного подключения к TURN-релею.
- **Native Matrix RTC (MSC4143 / MSC4186)**: Современные клиенты, такие как Element X и Element Call, используют спецификации MSC4143 (RTC Foci) и MSC4186 (LiveKit Call Authentication). Блок `extra_well_known_client_content` сообщает клиенту, что выпиской токенов для звонков занимается сервис `lk-jwt-service` по адресу `https://matrix.example.com/livekit/jwt`.
Полный файл `homeserver.yaml` выглядит следующим образом:
Полный файл `homeserver.yaml`:
```yaml
# Идентификация сервера
@@ -227,12 +227,12 @@ report_stats: false
## 3. Конфигурация LiveKit SFU (livekit.yaml)
LiveKit распределяет медиапотоки участников групповых звонков. Основные директивы в `livekit.yaml`:
LiveKit распределяет медиапотоки участников групповых звонков. Основные директивы в `livekit.yaml`:
- **`bind_addresses` и `port`**: Задает служебный HTTP-порт и WebSockets на порту `7880`.
- **`rtc.use_external_ip: true`**: Важнейшая опция для облачных серверов за NAT. Указывает LiveKit определять публичный IP-адрес хоста (`--node-ip`) и передавать его подключающимся клиентам.
- **`rtc.port_range_start` и `rtc.port_range_end`**: Ограничивает диапазон динамических UDP-портов WebRTC от `50000` до `50020`.
- **`room.auto_create: true`**: Разрешает автоматическое создание комнат при получении валидного JWT-токена от `lk-jwt-service`.
- **`bind_addresses` и `port`**: Задаёт служебный HTTP-порт и WebSockets на порту `7880`.
- **`rtc.use_external_ip: true`**: Необходимая опция для серверов за NAT: указывает LiveKit определять публичный IP-адрес хоста (`--node-ip`) и передавать его подключающимся клиентам.
- **`rtc.port_range_start` и `rtc.port_range_end`**: Ограничивают диапазон динамических UDP-портов WebRTC: от `50000` до `50020`.
- **`room.auto_create: true`**: Разрешает автоматическое создание комнат при получении валидного JWT-токена от `lk-jwt-service`.
Конфигурационный файл `livekit.yaml`:
@@ -258,16 +258,16 @@ logging:
## 4. Конфигурация Coturn Relay (turnserver.conf)
Coturn обеспечивает ретрансляцию трафика для 1:1 звонков. Ключевые опции в `turnserver.conf`:
Coturn обеспечивает ретрансляцию трафика для звонков 1:1. Ключевые опции в `turnserver.conf`:
- **`listening-port=3478`**: Стандартный порт для приёма STUN/TURN запросов по UDP и TCP.
- **`external-ip`**: Задает публичный IP-адрес сервера для корректного формирования адресов ретрансляции.
- **`min-port` и `max-port`**: Ограничивает диапазоны динамических UDP-портов от `49152` до `49172`.
- **`use-auth-secret` и `static-auth-secret`**: Включает авторизацию по секрету, совпадающему с `turn_shared_secret` в `homeserver.yaml`.
- **`realm`**: Доменное имя сервера, необходимое для проверки HMAC-токенов.
- **`no-multicast-peers`**: Блокирует попытки использовать релей для сканирования внутренних адресов сети.
- **`listening-port=3478`**: Стандартный порт для приёма STUN/TURN-запросов по UDP и TCP.
- **`external-ip`**: Задаёт публичный IP-адрес сервера для корректного формирования адресов ретрансляции.
- **`min-port` и `max-port`**: Ограничивают диапазон динамических UDP-портов: от `49152` до `49172`.
- **`use-auth-secret` и `static-auth-secret`**: Включают авторизацию по секрету, совпадающему с `turn_shared_secret` в `homeserver.yaml`.
- **`realm`**: Доменное имя сервера, необходимое для проверки HMAC-токенов.
- **`no-multicast-peers`**: Блокирует попытки использовать релей для сканирования внутренних адресов сети.
Файл `turnserver.conf` формируется следующим образом:
Конфигурация `turnserver.conf`:
```conf
listening-port=3478
@@ -293,11 +293,11 @@ no-multicast-peers
---
## 5. Переменные окружения и генерация секретов (.env)
## 5. Переменные окружения и генерация секретов (.env)
Вынос паролей и ключей в переменные окружения предотвращает их попадание в конфигурационные файлы и репозитории.
Вынос паролей и ключей в переменные окружения предотвращает их попадание в конфигурационные файлы и репозитории.
Секреты `DB_PASSWORD`, `LK_SECRET` и `TURN_SECRET` должны быть устойчивыми криптографическими строками. Мы используем `openssl` для их генерации.
Секреты `DB_PASSWORD`, `LK_SECRET` и `TURN_SECRET` должны быть криптографически стойкими строками. Для их генерации подойдёт утилита `openssl`.
Шаблон файла `.env`:
@@ -318,7 +318,7 @@ LK_SECRET=YOUR_LIVEKIT_SECRET
TURN_SECRET=YOUR_TURN_SHARED_SECRET
```
Генерация секретов через OpenSSL:
Генерация секретов с помощью OpenSSL:
```bash
# Выполните для создания DB_PASSWORD, LK_SECRET и TURN_SECRET
@@ -327,15 +327,15 @@ openssl rand -hex 32
---
## 6. Обратный прокси и автообнаружение (.well-known)
## 6. Обратный прокси и автообнаружение (.well-known)
Обратный прокси перенаправляет внешние запросы к нужным сервисам и выполняет требования веб-клиентов:
Обратный прокси перенаправляет внешние запросы к нужным сервисам и выполняет требования веб-клиентов:
1. **Заголовки CORS**: Веб-клиенты Element Web и Element Call выполняют междоменные запросы. Прокси должен возвращать заголовки `Access-Control-Allow-*`.
2. **Проксирование WebSockets (`/livekit/`)**: Для работы LiveKit необходимо проксирование постоянных WebSocket-соединений (`Upgrade: $http_upgrade` и `Connection: "Upgrade"`).
3. **Автообнаружение (`/.well-known/matrix/client` и `/.well-known/matrix/server`)**: Клиенты Matrix запрашивают эти URL при входе, чтобы автоматически определить адрес сервера и сервиса LiveKit JWT без ввода специальных портов пользователем.
1. **Заголовки CORS**: Веб-клиенты Element Web и Element Call выполняют междоменные запросы. Прокси должен возвращать заголовки `Access-Control-Allow-*`.
2. **Проксирование WebSockets (`/livekit/`)**: Для работы LiveKit необходимо проксирование постоянных WebSocket-соединений (`Upgrade: $http_upgrade` и `Connection: "Upgrade"`).
3. **Автообнаружение (`/.well-known/matrix/client` и `/.well-known/matrix/server`)**: Клиенты Matrix запрашивают эти URL при входе, чтобы автоматически определить адрес сервера и сервиса LiveKit JWT без указания нестандартных портов вручную.
Ниже приведен готовый пример конфигурации **Nginx**:
Пример конфигурации **Nginx**:
```nginx
server {
@@ -396,11 +396,11 @@ server {
---
## 7. Создание аккаунтов и обслуживание
## 7. Создание аккаунтов и обслуживание
При отключенной публичной регистрации (`enable_registration: false`) новые аккаунты создаются вручную.
При отключённой публичной регистрации (`enable_registration: false`) новые аккаунты создаются вручную.
### Регистрация администратора через CLI
### Регистрация администратора через CLI
Выполните команду `register_new_matrix_user` внутри контейнера Synapse:
@@ -410,9 +410,9 @@ docker exec -it matrix-synapse register_new_matrix_user \
--user admin --password "SECURE_USER_PASSWORD" --admin
```
### Настройка SMTP для писем
### Настройка SMTP для писем
Для включения функции восстановления паролей и подтверждения почты добавьте блок `email` в `homeserver.yaml`:
Чтобы включить функцию восстановления паролей и подтверждения почты, добавьте блок `email` в `homeserver.yaml`:
```yaml
email: