В свете сами знаете чего, свой приватный мессенджер и возможность звонков на XMPP стали как никогда актуальны.
Есть быстрый и простой способ: за несколько минут вы поднимаете собственный Jabber-сервер. Дальше — дело техники: рассылаете приглашения маме, бабушке, теще, жене и соседке Даше. После этого можно спокойно звонить и переписываться в защищённом мессенджере, который полностью под вашим контролем.
Звонки идут в зашифрованном режиме, работают p2p. А если у собеседника хитрый NAT, то на помощь автоматически приходит встроенный STUN-сервер.
Клиенты есть под все платформы: Android, iOS, Windows, macOS и Linux.
Можно запустить и на старых дистрибутивах — всё будет работать. Но на этом останавливаться не будем. Скрипты требуют Docker Compose версии 2 и несовместимы с устаревшим docker-compose v1.
Прописываем DNS
A chat.your-domain.com → <белый IP VDS/VPS>
CNAME groups.chat.your-domain.com → chat.your-domain.com
CNAME share.chat.your-domain.com → chat.your-domain.com
cd /opt
git clone https://github.com/snikket-im/snikket-selfhosted.git snikket
cd snikket
./scripts/init.sh
После запуска ./scripts/init.sh вас спросят имя вашего домена и email, после этого запускаем:
./scripts/start.sh
Если все прошло ок, то https://<your domain>/ уже будет форма для ввода логина и пароля.
Теперь осталось сформировать и послать самому себе админский инвайт:
./scripts/new-invite.sh --admin --group default
Админка и инвайты для юзеров
После того как вы создали админский инвайт и прошли регистрацию, можно зайти на сайт https://<ваш-домен>/ — и вы попадёте в админ-зону:
Скриншот
Из админ-зоны можно сразу отправить первое приглашение. Как только человек его примет и установит приложение — можно звонить и переписываться.
На этом всё!
Технические подробности
Если кому-то интересно, то давайте посмотрим, что мы получили из коробки:
Сервер XMPP (Jabber) — личный мессенджер без рекламы и слежки.
Поддержка федерации — общение с пользователями на других серверах XMPP.
Группы и чаты — приватные и публичные комнаты.
Файлы и мультимедиа — отправка фото, документов
Звонки — встроенный STUN/TURN для аудио- и видеосвязи (WebRTC).
Сквозное шифрование и автономность аккаунта — сквозное шифрование, независимость от телефонного номера
Мультиаккаунты и мультидевайсы — один юзер может быть на нескольких устройствах.
Docker-установка — быстрый запуск на Linux-сервере.
Минимальные требования — достаточно 1 ГБ RAM, поддерживается Raspberry Pi.
Бесплатно — всё бесплатно, звонки работают через встроенный TURN/STUN, ну либо есть ещё Snikket Hosting для тех, кому совсем лень и готов просто заплатить около $6/мес за готовый сервер с поддержкой медиарелеев по всему миру и автоматическим обновлением
Jitter‑буфер для WebRTC — служит буфером, выравнивает задержки и помогает стабильно передавать аудио, особенно при нестабильных сетях и сложных NAT.
Snikket сам получает и продлевает сертификаты Let’s Encrypt. У него внутри есть certbot-контейнер, который автоматически запрашивает и обновляет сертификаты и для веб‑портала, и для служб XMPP, STUN/TURN
Немного о jitter-буфере
Jitter‑буфер — это временное хранилище аудио‑пакетов, которое регулирует их подачу на клиент в равномерном потоке, чтобы избежать искажений и пропаданий звука при переменных задержках сети или нестабильном подключении.
В Snikket такой буфер встроен в WebRTC-движок, поэтому, даже если пользователь за NAT с нестабильной связью, звонок остаётся плавным и без резких «дёрганий» аудио.
Немного о звонках
По умолчанию звонки P2P. Клиенты стараются установить прямое соединение друг с другом через STUN.
Если NAT сложный (симметричный, CGNAT и т.п.), тогда в дело вступает TURN-сервер. В Snikket он встроен, можно оставить свой или подключить внешний. TURN просто пересылает UDP-пакеты между клиентами.
TURN не расшифровывает медиапоток. Всё зашифровано протоколом SRTP (Secure RTP) в рамках WebRTC.
Даже администратор сервера, на котором крутится TURN, не может прослушать или записать звонок, потому что у него нет ключей для расшифровки. Он видит только зашифрованный поток байтов.
То есть схема такая:
Обычный случай: звонок идёт напрямую P2P.
Сложный NAT: трафик «прокачивается» через TURN, но всё равно остаётся end-to-end encrypted, без возможности перехвата.
Маскировка аудиотрафика
Если всё работает стабильно — лучше ничего не менять, так вы сохраните качество звука. Но если провайдер или мобильный оператор начинает «резать» звонки, можно запустить TURN на порту 443 и замаскировать трафик под HTTPS.
Есть два способа:
Использовать дополнительный белый IP и повесить TURN на него, на порт 443.
Запустить nginx-сплиттер и разрулить всё на одном IP.
Оба варианта мы разберём чуть ниже. А пока — поднимем turnserver в Docker: он пригодится в любом случае.
mkdir /opt/turnserver
cd /opt/turnserver
Создаем в этой папке файл docker-compose.yml вот с таким содержанием:
Плюсы: проще, меньше прослоек; отличная устойчивость, звонки реально «как HTTPS» на 443/TLS; меньше джиттера по сравнению с проксированием через stream.
Минусы: нужен второй IP.
Вариант B: ОДИН «белый» IP и nginx как сплиттер
Создаем поддомен turn.your-domain.com и вешаем на тот же самый белый ip.