Установка Matrix
Полный гайд: Matrix Synapse + PostgreSQL + Element + Synapse-Admin в Docker Compose
- 1. Введение
- 2. Требования к серверу
- 3. Установка Docker и Docker Compose
- 4. Подготовка структуры директорий и переменных окружения
- 5. Создание файла docker-compose.yml
- 6. Настройка базы данных PostgreSQL
- 7. Конфигурация Synapse (homeserver.yaml)
- 8. Настройка клиентской части и админ-панели
- 9. Конфигурация Nginx
- 10. Получение SSL-сертификатов
- 11. Запуск сервисов
- 12. Создание пользователей через консоль
- 13. Автоматическое обновление сертификатов
- 14. Управление и обслуживание
- 15. Проверка работоспособности
Введение
Протокол 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/data:/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:/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}
- ADMIN_DOMAIN=${ADMIN_DOMAIN}
- SECRET_KEY=${MACAROON_SECRET} # или любой другой случайный ключ (openssl rand -hex 32)
- SKEY=${REGISTRATION_SECRET}
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: "/conf/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;
}
location /_synapse/admin {
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;
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).
Отметим, что создавать пользователей также можно через административную панель Matrix, после того как будет запущен сервис.
Автоматическое обновление сертификатов
Добавим скрипт в 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