javascript

Я написал мессенджер с серверами и голосовыми каналами. Один. Рассказываю зачем и как

  • суббота, 14 марта 2026 г. в 00:00:06
https://habr.com/ru/articles/1009658/

Когда в октябре 2024-го заблокировали Дискорд, я сидел в голосовом канале с друзьями. Связь оборвалась, все полезли за впн-ками, кто-то ушёл в Телеграм, кто-то просто пропал. Серверы, которые мы строили годами, с каналами, ролями, ботами, в один момент стали недоступны.

Я фрилансер, пишу на React и Node.js. В тот вечер подумал: а насколько сложно вообще сделать свой мессенджер с серверной структурой? Не чат на вебсокетах из туториала, а нормальный. С серверами, каналами, ролями, голосовыми комнатами, ботами. Такой, чтобы можно было перетащить своё сообщество и не чувствовать разницы.

Оказалось, сложно. Но я всё равно сделал.

Что получилось

Проект называется Vela (с латыни «парус»). Это десктопное приложение на Электроне и веб-версия. Вот что работает прямо сейчас:

  • Серверы и каналы. Создаёшь сервер, внутри текстовые и голосовые каналы, категории. Всё как привычно.

  • Голосовые каналы. Заходишь и разговариваешь. Видео, демонстрация экрана, управление громкостью каждого участника. Под капотом WebRTC и Opus.

  • Роли и разрешения. 12 настраиваемых прав. Можно выдать роль «Модератор» с правом удалять сообщения, но без доступа к настройкам сервера. Разрешения работают и на уровне отдельных каналов.

  • Боты. Полноценный API: токены, вебхуки, слэш-команды с автодополнением, интерактивные кнопки, колбэки. Если писали ботов для Телеграма, разберётесь быстро, принцип похожий.

  • Личные сообщения. Отдельно от серверов. Файлы, реакции, стикеры, поиск по переписке.

  • Двухфакторная аутентификация, экспорт данных, удаление аккаунта. Всё что требует 152-ФЗ.

Серверы физически находятся в России. Работает без впн.

Стек

Тут будет скучно, но для Хабра в самый раз.

Клиент: React 18, TypeScript, Tailwind CSS, Framer Motion, Vite. Десктоп на Электроне с песочницей, изоляцией контекста и безопасным хранилищем для токенов (DPAPI на Виндоус, Keychain на Маке). Виртуализация сообщений через react-virtual, без неё при 10 000 сообщений в канале всё умирало.

Сервер: Node.js, Express, Prisma, PostgreSQL, Redis. Вебсокеты на ws, не Socket.io, чтобы контролировать протокол. Файлы льются в S3-совместимое хранилище (TWC Storage, серверы в России).

Голос: WebRTC, peer-to-peer. Кодек Opus 48 кГц. Web Audio API для микширования, шумоподавления и анализа громкости. Самая болезненная часть проекта, об этом ниже.

Инфраструктура: один VPS на Aéza (Россия), PM2, Nginx, Let's Encrypt. Бэкапы базы каждую ночь. Мониторинг через свой эндпоинт /health + Яндекс Метрика на лендинге.

Что было больнее всего

Голосовые каналы

Думал, будет просто. Взял WebRTC, написал сигналинг, и готово. Нет.

Первая проблема: NAT traversal. В России у многих пользователей двойной NAT (оператор + роутер). STUN-сервер помогает не всегда, нужен TURN для ретрансляции. А TURN это трафик через мой сервер, и он стоит денег.

Вторая: обратная связь от микрофона. Без эхоподавления голос возвращается с задержкой 200мс и начинается ад. Пришлось ковырять Web Audio API: анализатор громкости, voice activity detection, автоматическое отключение микрофона при тишине.

Третья: утечки памяти. MediaStream и AudioContext не отпускают ресурсы если их не закрыть вручную. После часа звонка приложение начинало тормозить. Пока не расставил disconnectSource() и close() в нужных местах, было больно.

Вебсокеты и реконнект

Казалось бы: клиент подключается, сервер шлёт события. Но нет.

Что если у пользователя пропал вайфай на 3 секунды? Сообщения, отправленные за это время, просто теряются. Пришлось делать: экспоненциальный бэкофф при реконнекте (от 1 до 30 секунд с джиттером), хартбит каждые 30 секунд с таймаутом на понг, и гэп-филл после переподключения, когда клиент запрашивает пропущенные сообщения.

Звучит очевидно, но каждый из этих пунктов это баги, которые я ловил в продакшене неделями.

Безопасность

Когда делаешь мессенджер, безопасность не «потом допилим». Я провёл полный аудит: от XSS (нашёл, что маркдаун-рендерер не санитизировал HTML, привет DOMPurify) до привилегий в ролевой системе (роль с правом «управление ролями» могла назначить себе все права, классический privilege escalation).

Полный список того, что пришлось закрыть:

  • Шифрование токена через системное хранилище (а не JSON-файл на диске)

  • Проверка origin при подключении к вебсокетам

  • Тайминг-безопасное сравнение TOTP-кодов

  • Блокировка аккаунта после 5 неудачных попыток входа

  • Rate limiting на все мутационные эндпоинты

  • Content Security Policy, HSTS, безопасные куки

Размер проекта

Чтобы понять масштаб, вот цифры на сегодня:

  • Около 300 компонентов на клиенте

  • 50+ API-маршрутов на сервере

  • 20+ таблиц в Prisma-схеме

  • 51 API-тест, 5 E2E-тестов

  • 14 ErrorBoundary (после аудита было 6)

  • Сборка: ~800 КБ основной бандл (разбит на чанки), установщик ~93 МБ

Это не стартап с командой из десяти человек. Это один человек с ноутбуком и Claude Code в терминале. Да, я активно использую ИИ-ассистенты для кодинга и не стесняюсь этого. Но каждое архитектурное решение, каждый компромисс, каждый баг в три часа ночи, всё это моё.

Зачем это всё

Честный ответ: я не планировал «убить Дискорд». Я хотел сделать инструмент, которым сам бы пользовался. Мессенджер с серверной структурой, который работает в России без костылей.

Сейчас на рынке есть альтернативы: Lenza Arena (115 тысяч пользователей, но лимит 15 человек в голосовом канале), Revolt (международный, на бета-стадии, серверы за границей), корпоративные решения вроде VK Teams и SaluteJazz (не для сообществ). Полноценного российского аналога с серверами, каналами, ролями, ботами и голосовыми комнатами я не нашёл. Поэтому сделал.

Что дальше

Я выпустил Vela в открытый доступ. Прямо сейчас можно:

  • Скачать приложение для Windows: velachat.ru

  • Открыть в браузере без установки velachat.online

  • Создать свой сервер и позвать друзей

Мне интересна обратная связь. Не абстрактная «ну, прикольно», а конкретная: что сломалось, чего не хватает, что раздражает. Я один, и мне важно понять, куда вкладывать следующие 200 часов разработки.

В ближайших планах:

  • Версия для macOS и Linux (сборки настроены, нужно тестирование)

  • Мобильное приложение (это отдельная большая история)

  • Рассматриваю возможность открыть исходный код

Если зайдёте, попробуете и напишете мне, буду благодарен. На официальном сервере Vela есть каналы для обратной связи и баг-репортов.


Я Денис, фрилансер из Нижнего Новгорода. Занимаюсь веб-разработкой, Телеграм-ботами и иногда мессенджерами. Сайт проекта: velachat.ru и веб приложение velachat.online