Установка Matrix
Полный гайд: Matrix Synapse + PostgreSQL + Element + Synapse-Admin в Docker Compose
Содержание
Введение
Протокол Matrix стал стандартом для организации безопасных коммуникаций с поддержкой сквозного шифрования. В этой статье мы рассмотрим развертывание полного стека сервисов (сервер Synapse, база данных PostgreSQL, веб-клиент Element и панель администратора) в изолированной среде Docker.
Использование Docker Compose позволяет описать всю инфраструктуру в одном файле конфигурации, что упрощает развертывание, обновление и перенос сервера между хостинг-провайдерами.
Требования к серверу
Для установки потребуется VDS или выделенный сервер со следующими характеристиками:
-
ОС: Ubuntu 22.04 или 24.04 LTS.
-
Домен: Зарегистрированное доменное имя.
-
DNS-записи: Необходимо настроить A-записи для трех поддоменов, указывающих на IP-адрес сервера:
matrix.sitename.ru(для API сервера)element.sitename.ru(для веб-клиента)matrix-admin.sitename.ru(для панели управления)
-
Порты: В фаерволе должны быть открыты порты 80, 443, 8448 (TCP) и 3478, 5349 (UDP/TCP для голосовых звонков).
Вместо
sitename.ruиспользуйте имя вашего сайта
Установка Docker и Docker Compose
Обновим пакеты системы и установим Docker Engine вместе с плагином Compose.
apt update && apt upgrade -y
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
apt install docker-compose-plugin -y
docker --version
docker compose version
Подготовка структуры директорий и переменных окружения
Создадим корневую директорию для проекта и подпапки для конфигураций каждого сервиса.
mkdir -p /opt/matrix-stack/{synapse,element,synapse-admin,postgres,coturn,nginx,certs}
cd /opt/matrix-stack
Для безопасности работы сервисов необходимо сгенерировать случайные секретные ключи. Создадим файл .env, в котором будут храниться пароли и доменные имена.
REGISTRATION_SECRET=$(openssl rand -hex 32)
TURN_SECRET=$(openssl rand -hex 32)
POSTGRES_PASSWORD=$(openssl rand -hex 32)
MACAROON_SECRET=$(openssl rand -hex 32)
cat > .env << EOF
DOMAIN=matrix.sitename.ru
ELEMENT_DOMAIN=element.sitename.ru
ADMIN_DOMAIN=matrix-admin.sitename.ru
POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
REGISTRATION_SECRET=${REGISTRATION_SECRET}
TURN_SECRET=${TURN_SECRET}
MACAROON_SECRET=${MACAROON_SECRET}
EOF
chmod 600 .env
source .env
Важно: Сохраните файл
.envв надежном месте. Потеря секретных ключей сделает невозможным восстановление доступа к существующим аккаунтам при переустановке сервера.
Создание файла docker-compose.yml
В корневой директории создадим файл docker-compose.yml. Он описывает все необходимые контейнеры, сети и тома.
services:
postgres:
image: postgres:15-alpine
container_name: matrix-postgres
restart: unless-stopped
environment:
POSTGRES_USER: matrix
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: postgres
volumes:
- ./postgres//var/lib/postgresql/data
- ./postgres/init:/docker-entrypoint-initdb.d:ro
networks:
- matrix-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U matrix -d matrix"]
interval: 10s
timeout: 5s
retries: 5
synapse:
image: ghcr.io/matrix-org/synapse:latest
container_name: matrix-synapse
user: "0:0"
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
- SYNAPSE_SERVER_NAME=${DOMAIN}
- SYNAPSE_REPORT_STATS=no
- SYNAPSE_CONFIG_PATH=/conf/homeserver.yaml
volumes:
- ./synapse//data
- ./synapse/config:/conf
- ./synapse/media:/media
networks:
- matrix-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8008/_matrix/client/versions"]
interval: 30s
timeout: 10s
retries: 3
element:
image: docker.io/vectorim/element-web:latest
container_name: matrix-element
restart: unless-stopped
volumes:
- ./element/config.json:/app/config.json:ro
networks:
- matrix-network
depends_on:
- synapse
synapse-admin:
image: docker.io/awesometechnologies/synapse-admin:latest
container_name: matrix-synapse-admin
restart: unless-stopped
environment:
- REACT_APP_SERVER=https://${DOMAIN}
networks:
- matrix-network
depends_on:
- synapse
coturn:
image: docker.io/coturn/coturn:latest
container_name: matrix-coturn
restart: unless-stopped
network_mode: host
volumes:
- ./coturn/turnserver.conf:/etc/turnserver.conf:ro
command: -c /etc/turnserver.conf
depends_on:
- synapse
nginx:
image: docker.io/nginx:alpine
container_name: matrix-nginx
restart: unless-stopped
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./certs:/etc/letsencrypt:ro
- ./certs/webroot:/var/www/certbot:ro
ports:
- "80:80"
- "443:443"
- "8448:8448"
networks:
- matrix-network
depends_on:
- synapse
- element
- synapse-admin
networks:
matrix-network:
driver: bridge
Настройка базы данных PostgreSQL
Synapse требует специфической кодировки базы данных. Создадим скрипт инициализации, который выполнится при первом запуске контейнера PostgreSQL.
mkdir -p postgres/init
cat > postgres/init/01-create-matrix-db.sql << EOF
DROP DATABASE IF EXISTS matrix;
CREATE DATABASE matrix WITH OWNER matrix ENCODING 'UTF8' LC_COLLATE='C' LC_CTYPE='C' TEMPLATE=template0;
EOF
Подготовим директорию для данных Synapse и установим корректные права доступа:
mkdir -p synapse/{config,data,media}
chmod -R 777 synapse
Конфигурация Synapse (homeserver.yaml)
Основной конфигурационный файл сервера. В нем прописываются параметры подключения к БД, пути к медиафайлам, настройки шифрования и TURN-сервера.
cat > synapse/config/homeserver.yaml << EOF
server_name: "${DOMAIN}"
pid_file: /data/homeserver.pid
report_stats: false
listeners:
- port: 8008
tls: false
type: http
x_forwarded: true
bind_addresses: ['0.0.0.0']
resources:
- names: [client, federation]
compress: false
- port: 8448
tls: false
type: http
x_forwarded: true
bind_addresses: ['0.0.0.0']
resources:
- names: [federation]
compress: false
database:
name: psycopg2
args:
user: matrix
password: ${POSTGRES_PASSWORD}
database: matrix
host: postgres
port: 5432
cp_min: 5
cp_max: 10
log_config: "/config/log.config"
media_store_path: /media
uploads_path: /media/uploads
signing_key_path: "/data/${DOMAIN}.signing.key"
trusted_key_servers:
- server_name: "matrix.org"
max_upload_size: 100M
enable_registration: false
registration_shared_secret: "${REGISTRATION_SECRET}"
turn_uris:
- "turn:${DOMAIN}:3478?transport=udp"
- "turn:${DOMAIN}:3478?transport=tcp"
turn_shared_secret: "${TURN_SECRET}"
turn_user_lifetime: 86400000
admin_users:
- "@admin:${DOMAIN}"
enable_federation: false
federation_port: 8448
macaroon_secret_key: "${MACAROON_SECRET}"
EOF
Также создадим файл конфигурации логирования:
cat > synapse/config/log.config << 'EOF'
version: 1
formatters:
precise:
format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s'
handlers:
console:
class: logging.StreamHandler
formatter: precise
level: INFO
file:
class: logging.handlers.RotatingFileHandler
formatter: precise
level: INFO
filename: /data/homeserver.log
maxBytes: 104857600
backupCount: 10
loggers:
synapse.storage.SQL:
level: WARNING
root:
level: INFO
handlers: [console, file]
disable_existing_loggers: false
EOF
chmod 644 synapse/config/log.config
Настройка клиентской части и админ-панели
Element Web
Файл config.json указывает клиенту адрес сервера для подключения.
cat > element/config.json << EOF
{
"default_server_config": {
"m.homeserver": {
"base_url": "https://${DOMAIN}",
"server_name": "${DOMAIN}"
}
},
"disable_custom_urls": true,
"disable_guests": true,
"disable_login_language_selector": false,
"disable_3pid_login": true,
"brand": "Element",
"default_theme": "light",
"show_labs_settings": false,
"features": {},
"default_federate": false
}
EOF
Coturn (TURN-сервер)
Необходим для прохождения NAT при голосовых и видеозвонках.
cat > coturn/turnserver.conf << EOF
listening-port=3478
tls-listening-port=5349
fingerprint
use-auth-secret
static-auth-secret=${TURN_SECRET}
realm=${DOMAIN}
user-quota=100
total-quota=1200
no-tcp-relay
syslog
no-multicast-peers
no-loopback-peer
EOF
Конфигурация Nginx
Nginx будет выступать в роли обратного прокси, распределять трафик между сервисами и обрабатывать SSL-сертификаты.
Создадим основной конфиг nginx.conf:
mkdir -p nginx/conf.d
cat > nginx/nginx.conf << 'EOF'
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
EOF
Создадим конфигурацию виртуальных хостов matrix.conf:
cat > nginx/conf.d/matrix.conf << EOF
# Редирект HTTP на HTTPS
server {
listen 80;
server_name ${DOMAIN} ${ELEMENT_DOMAIN};
return 301 https://\$host\$request_uri;
}
# Matrix Synapse API
server {
listen 443 ssl http2;
server_name ${DOMAIN};
ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem;
location ^~ /.well-known/acme-challenge/ {
root /var/www/certbot;
default_type "text/plain";
}
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location ~ ^(/|/_matrix|/_synapse/client) {
proxy_pass http://synapse:8008;
proxy_set_header X-Forwarded-For \$remote_addr;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_set_header Host \$host;
client_max_body_size 100M;
proxy_http_version 1.1;
}
}
# Порт федерации
server {
listen 8448 ssl http2;
server_name ${DOMAIN};
ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem;
location / {
proxy_pass http://synapse:8008;
proxy_set_header X-Forwarded-For \$remote_addr;
proxy_set_header Host \$host;
}
}
# Element Web
server {
listen 443 ssl http2;
server_name ${ELEMENT_DOMAIN};
ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem;
location ^~ /.well-known/acme-challenge/ {
root /var/www/certbot;
default_type "text/plain";
}
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
location / {
proxy_pass http://element:80;
proxy_set_header X-Forwarded-For \$remote_addr;
proxy_set_header Host \$host;
}
}
# Synapse Admin
server {
listen 443 ssl http2;
server_name ${ADMIN_DOMAIN};
location ^~ /.well-known/acme-challenge/ {
root /var/www/certbot;
default_type "text/plain";
}
ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem;
location / {
# Рекомендуется ограничить доступ по IP
# allow 1.2.3.4;
# deny all;
proxy_pass http://synapse-admin:80;
proxy_set_header X-Forwarded-For \$remote_addr;
proxy_set_header Host \$host;
}
}
EOF
Получение SSL-сертификатов
Для работы HTTPS необходимы сертификаты. Используем Certbot в режиме standalone. Перед запуском убедитесь, что порт 80 свободен (если запущен другой веб-сервер, его нужно временно остановить).
docker run --rm -it \
-v ./certs:/etc/letsencrypt \
-p 80:80 \
certbot/certbot certonly \
--standalone \
-d ${DOMAIN} \
-d ${ELEMENT_DOMAIN} \
-d ${ADMIN_DOMAIN} \
--email your@email.com \
--agree-tos \
--non-interactive
Запуск сервисов
Сначала запустим базу данных для инициализации, затем поднимем весь стек.
docker compose up -d postgres
sleep 30
docker compose up -d
Проверим статус контейнеров:
docker compose ps
Можно отследить логи Synapse для контроля процесса запуска:
docker compose logs -f synapse
Создание пользователей через консоль
После настройки сервера возникает необходимость добавления новых участников. Это можно сделать двумя способами: создать обычного пользователя или сразу наделить его правами администратора.
Создание обычного пользователя
Для регистрации стандартного аккаунта используется утилита register_new_matrix_user. Ключ -a (admin) в этом случае не указывается.
Выполните команду внутри контейнера Synapse:
docker exec -it matrix-synapse register_new_matrix_user \
-c /conf/homeserver.yaml \
http://localhost:8008 \
-u username \
-p secure_password
Где:
-
username— желаемое имя пользователя (без домена, напримерivan). -
secure_password— пароль для входа.
Пример:
docker exec -it matrix-synapse register_new_matrix_user \
-c /conf/homeserver.yaml \
http://localhost:8008 \
-u ivanov \
-p Str0ngP@ssw0rd
В ответ система выдаст подтверждение создания пользователя и его полный MXID (например, @ivanov:matrix.sitename.ru). Этот пользователь сможет войти через веб-клиент Element, но не будет иметь доступа к панели администрирования.
Примечание: Если в файле
homeserver.yamlпараметрenable_registrationустановлен вfalse(что рекомендуется для безопасности после первоначальной настройки), регистрация новых пользователей возможна только через эту консольную команду или панель администратора. Веб-форма регистрации в клиенте будет недоступна.
Создание пользователя с правами администратора
Если необходимо создать нового администратора, используется та же команда, но с добавлением флага -a:
docker exec -it matrix-synapse register_new_matrix_user \
-c /conf/homeserver.yaml \
http://localhost:8008 \
-u admin_name \
-p secure_password \
-a
Флаг -a автоматически добавляет созданного пользователя в список admin_users и наделяет полными правами управления сервером через Synapse-Admin.
Интерактивный режим
Если не указывать логин и пароль в аргументах команды, утилита запустится в интерактивном режиме и запросит данные пошагово:
docker exec -it matrix-synapse register_new_matrix_user \
-c /conf/homeserver.yaml \
http://localhost:8008
Система последовательно запросит:
-
Username (имя пользователя).
-
Password (пароль).
-
Confirm password (подтверждение пароля).
-
Make admin [y/N] (сделать администратором: да/нет).
Этот способ удобен, чтобы избежать передачи паролей через историю команд оболочки (history).
Автоматическое обновление сертификатов
Добавим скрипт в cron для регулярного продления сертификатов Let’s Encrypt.
cat > /etc/cron.daily/certbot-renew << 'EOF'
#!/bin/bash
cd /opt/matrix-stack
docker run --rm \
-v ./certs:/etc/letsencrypt \
-v ./certs/webroot:/var/www/certbot \
certbot/certbot certonly \
--webroot -w /var/www/certbot \
-d ${DOMAIN} -d ${ELEMENT_DOMAIN} -d ${ADMIN_DOMAIN} \
--email your@email.com --agree-tos --non-interactive
docker compose restart nginx
EOF
chmod +x /etc/cron.daily/certbot-renew
Управление и обслуживание
Основные команды для управления стеком:
-
Остановка:
docker compose down -
Перезапуск:
docker compose restart -
Обновление образов:
docker compose pull && docker compose up -d -
Просмотр логов:
docker compose logs -f [имя_сервиса]
Для резервного копирования данных достаточно архивировать тома с данными:
tar -czf matrix-backup-$(date +%Y%m%d).tar.gz \
postgres/data synapse/data synapse/media certs
Проверка работоспособности
Убедитесь, что сервисы доступны по следующим адресам:
| Сервис | URL | Порт |
|---|---|---|
| Element Web | https://element.sitename.ru |
443 |
| Matrix API | https://matrix.sitename.ru |
443 |
| Synapse Admin | https://matrix-admin.sitename.ru |
443 |
| Federation | matrix.sitename.ru |
8448 |
Источником для данного руководства послужили материалы с сайта habr.ru