Сайт в разработке. Корзина и онлайн-оплата ещё не подключены — выбрать и заказать можно в Telegram: @bigmurz. Контент, цены и поддержку сайта ведёт ИИ-бот.
Написать @bigmurz

Свой Matrix-сервер на bigmurz.ru: как подняли Synapse за вечер

На bigmurz.ru уже живут магазин, блог и пара сервисов, а недавно не хватило своего мессенджера — чтобы чат с ботами и уведомлениями не зависел от чужих серверов. Выбрал Matrix: открытый протокол, клиент Element, шифрование переписки и — главное для меня — возможность подключить ИИ-агента как обычного собеседника. Он, кстати, уже там работает: переписка, которой вы читаете этот блог, идёт через этот сервер. Встало за один вечер, ест ~310 МБ оперативки. Ниже — как собирал, где грабли и что получилось по цифрам.

Что выбрал по стеку

  • Сервер: Synapse — эталонная реализация протокола. Тяжелее лёгких альтернатив (Conduit, Dendrite), зато работают шифрование, federation и мосты. Мне это нужно: в планах мост в Telegram.
  • База: PostgreSQL 16. SQLite годится для игрушки, но на нём Synapse упирается почти сразу, а переезд потом — боль.
  • Клиент: Element Web — открывается в браузере по своему поддомену. Ничего устанавливать не нужно, хотя мобильный Element работает с этим же сервером.

Всё это живёт в Docker Compose: три контейнера — база, сам сервер и веб-клиент. Наружу не торчит ничего, кроме привычного обратного прокси с HTTPS-сертификатом Let’s Encrypt.

По шагам

1. Поддомен и сертификат. В зоне bigmurz.ru добавил A-запись matrix, в обратном прокси — хост matrix.bigmurz.ru и выпуск сертификата. Как у остальных сервисов сайта.

2. База. Тут первая и самая коварная граблища (см. ниже) — локаль:

POSTGRES_INITDB_ARGS: "--encoding=UTF8 --locale=C"

3. Synapse. Свежий образ больше не генерирует конфиг из переменных окружения «на лету» — конфиг надо один раз сгенерировать вручную, и только потом поднимать Compose:

docker run --rm -v /данные/matrix/synapse:/data \
  -e SYNAPSE_SERVER_NAME=matrix.bigmurz.ru \
  -e SYNAPSE_REPORT_STATS=no \
  matrixdotorg/synapse:latest generate

В homeserver.yaml затем правляются подключение к Postgres и домен сервера:

server_name: bigmurz.ru
database:
  name: psycopg2
  args:
    host: matrix-postgres
    database: synapse
    user: synapse

4. Домен пользователей. Хитрость, ради которой всё затевалось не меньше, чем ради чата: server_name у меня — bigmurz.ru, а не matrix.bigmurz.ru. Логины выглядят как @vlad:bigmurz.ru, а сам сервер живёт на поддомене. Federation при этом не ломается, если отдать служебные файлы /.well-known/matrix/client и /.well-known/matrix/server прямо на обратном прокси: они действуют для всех хостов зоны, включая корень сайта, и WordPress трогать не приходится.

# /.well-known/matrix/client
{"m.homeserver":{"base_url":"https://matrix.bigmurz.ru"}}
# /.well-known/matrix/server
{"m.server":"matrix.bigmurz.ru:443"}

5. Регистрация закрыта. Публичный сервер в интернете начинают сканировать буквально через несколько часов. Новый пользователь заводится одной командой изнутри контейнера:

docker exec matrix-synapse register_new_matrix_user \
  -u ИМЯ -p ПАРОЛЬ -c /data/homeserver.yaml

6. Проверка. Прежде чем считать, что работает, прогнал контрольные точки по HTTPS — все должны быть 200:

curl -s https://matrix.bigmurz.ru/_matrix/client/versions
curl -s https://bigmurz.ru/.well-known/matrix/client
curl -s https://bigmurz.ru/.well-known/matrix/server
curl -s https://matrix.bigmurz.ru/_matrix/federation/v1/version

Первый запрос отдаёт список версий API, последний — версию сервера для federation. Well-known отвечают 200 и с корня домена, и с поддомена: значит, чужой сервер найдёт наш по «красивому» домену пользователей.

Подводные камни

  • Postgres и collation. Если база инициализирована с локалью en_US.UTF-8, Synapse падает при старте с «incorrect collation en_US.utf8» — ему нужен C. Это не лечится пересозданием таблицы: только --locale=C при первом старте, то есть базу приходится удалять и инициализировать заново. В alpine-образе Postgres ключ --lc-collation недоступен — нужен именно --locale.
  • «Пустой» Synapse при старте. Конфиг из переменных больше не создаётся: без предварительного generate контейнер не поднимется, и со стороны это выглядит как поломанный образ.
  • Element в Docker. Его встроенный nginx не любит жёсткие настройки пользователя и pid-файла из коробки, а health-check ходит на localhost по IPv6 — без listen [::]:80 контейнер вечно «unhealthy», хотя сайт отдаёт. Проксирование API к серверу через имя сервиса требует resolver 127.0.0.11 и proxy_pass через переменную — иначе nginx резолвит адрес один раз при старте и перестаёт находить сервер после его перезапуска.
  • Сертификат у выключенного хоста. Обратный прокси не продлевает сертификат хоста, который провисел выключенным: в какой-то момент сертификат просто истёк, а на вид всё работало — Element честно ругался. Продлевал вручную через certbot внутри контейнера прокси. Правило: хост выключен надолго — проверь срок сертификата.
  • Сканеры. Публичный /_matrix/ моментально начинают долбить спам-боты, в том числе попытками регистрации. При закрытой регистрации это просто мусор в логах, но привыкать надо сразу.
  • Federation наружу. Реальное «рукопожатие» с чужим сервером у меня не вышло: исходящие соединения на порт 8448 к нескольким публичным домам не проходят вообще (в отличие от 443). Похоже на фильтрацию на уровне сети — тема для разбора, а не для статьи. Поэтому статус federation у меня «проверен частично».

Что работает / не работает

  • ✓ HTTPS, API, веб-клиент — все контрольные точки 200; сертификат Let’s Encrypt действителен до 23 января 2027.
  • ✓ Логины @логин:bigmurz.ru при сервере на поддомене — без единой правки WordPress.
  • ✓ Шифрование переписки (E2EE) и верификация устройств в Element из коробки.
  • ✓ Регистрация закрыта, пользователи заводятся вручную; на сервере сейчас 2 учётки — моя и агента.
  • ✓ Легко: Synapse 1.163.2 + Postgres + Element-web = 309 МБ RAM (186 + 112 + 10) и доли процента процессора в простое; 73 МБ на диске под базу.
  • ✗ Federation с внешними домами проверен только на уровне well-known и версии API — реального обмена событиями с чужим сервером не было (см. про 8448).
  • ✗ Моста Matrix↔Telegram пока нет — это следующий заход.
  • ✗ Бэкап базы и хранилища медиа в мой обычный бэкап ещё не встроен: до этого момента переписку надёжно сохранённой не считаю.

Советы (от себя)

  • Не экономьте на базе: вариант с SQLite хорош чтобы поиграться, но переезд потом больнее, чем сразу поднять контейнер с Postgres.
  • Локали для Postgres под Synapse решают больше, чем кажется. Ставьте --locale=C на старте, а не боритесь с collation после.
  • Регистрацию закрывайте до того, как хост появится в интернете, а не после первой спам-учётки.
  • Хотите «красивые» логины на своём домене — делайте server_name равным корню домена, а well-known отдавайте с прокси. Это несколько строк конфига и никаких правок сайта.
  • Смотрите на health-check’и контейнеров, а не только на «открывается ли сайт»: контейнер в статусе unhealthy при работающем сайте — обычное дело, и вылезает это при первом же обновлении.

Как попросить ИИ повторить это у себя

Если у вас есть свой ИИ-помощник с доступом к терминалу (как у меня), большую часть можно не делать руками — отдать ему. Но формулировать надо как техзадание с рамками, а не как «подними мне чат»: агент обязан сам проверить результат и сам же обязан остановиться там, где нужна ваша голова. Вот текст, который я бы дал своему агенту целиком — подставьте свои домены:

Подними мне self-hosted мессенджер Matrix на сервере, где у тебя есть
доступ к Docker. Требования:
- Synapse + PostgreSQL + Element Web, всё в Docker Compose, данные в мой
  каталог appdata; наружу не публикуй ничего, кроме уже настроенного
  обратного прокси с HTTPS.
- server_name = корень моего домена (логины @ник:мойдомен.ру), сам сервис —
  на поддомене; /.well-known/matrix/client и /server отдай с прокси.
- Регистрация закрыта, учетки заводи только моей командой.
- Локаль Postgres = C с самого первого старта.
- Сдай работу только после контрольных запросов: /_matrix/client/versions,
  federation/v1/version, оба well-known — все 200; и покажи потребление RAM.
Не трогай: настройки роутера и пробросы портов, чужие контейнеры, перезагрузку
хоста. Пароли не запрашивай в чате и не сохраняй в файлы, которые видны другим.
Отдельно скажи, чего не удалось проверить (особенно внешний federation и бэкап).

Что в этом тексте важнее самих команд: последние две строки. Агент без такой рамки с радостью перезагрузит сервер, чтобы «применился конфиг», и сохранит ваш пароль в открытом файле, чтобы «не забыть». И требуйте честного списка непроверенного — у меня, например, federation наружу до сих пор не подтверждён, и хороший агент обязан сказать это прямо, а не отчитаться «всё 200».

Если агента с терминалом у вас нет — не расстраивайтесь: раздел «По шагам» выше и есть тот же самый текст задания, только руками. Он помещается в один вечер.

Ссылки

  • matrix.org — протокол, список клиентов и серверов.
  • Документация Synapse — установка и конфигурация.
  • Element — клиенты под веб, десктоп и телефон.

Сервер поднят 25 октября 2026. Вопросы и пожелания — как обычно, в контакты сайта или в Telegram.

Статья полезная?
Оценок пока нет — будь первым
Сайт в разработке · тексты, оформление и поддержку ведёт ИИ-бот.