Skip to content

Repository files navigation

OwnCord

License: MIT Node

Self-hosted минималистичный мессенджер с голосовыми/видео звонками и демонстрацией экрана (или отдельного окна/приложения).

  • Регистрация/логин по имени пользователя и паролю
  • Единый список всех пользователей — без друзей, звонить и писать можно кому угодно
  • Direct-сообщения с историей, markdown, редактированием/удалением и системными сообщениями о звонках
  • Групповые чаты (до 10 участников) с названием, аватаркой, списком участников, сообщениями/файлами/голосовыми
  • Групповые звонки (голос + опционально видео) — mesh WebRTC, до 10 участников, сетка плиток
  • Файлы и медиа: фото, видео, любые документы (до 50 МБ), голосовые сообщения
  • WebRTC звонки 1:1: микрофон, камера (опционально), шаринг экрана/окна/приложения
  • Окно реконнекта 5 мин: если связь 1:1 оборвалась, кнопка «Подключиться» позволяет вернуться без нового вызова
  • Регистрация по приглашению: серверный REGISTRATION_CODE, одноразовые/multi-use коды через UI, или полное закрытие регистрации
  • Push-уведомления: системные через Web Push — звонки и сообщения долетают и при закрытой вкладке
  • Профиль: ник, аватарка, политика удаления собственных сообщений, удаление аккаунта (история сохраняется как «Удалённый пользователь»)
  • Авто-чистка истории: сообщения и вложения старше RETENTION_DAYS (по умолчанию 90) автоматически удаляются из БД и с диска
  • Мьюты: серверные, синхронизируются между устройствами
  • Гранулярные звуковые уведомления + общий тумблер
  • Кроссплатформенно: работает в любом современном браузере (ПК и телефон), ставится как PWA

Стек

  • Backend: Node.js + Express + Socket.IO + SQLite (better-sqlite3) + JWT/bcrypt
  • Frontend: React + Vite + TailwindCSS + Lucide icons
  • P2P медиа: WebRTC (STUN — Google public). Для жёстких NAT можно подключить TURN (см. .env).

Быстрый старт

# из корня проекта
npm run install:all

# dev-режим (сервер :3001, клиент :5173, клиент проксирует API на сервер)
npm run dev

Открой http://localhost:5173, зарегистрируй двух пользователей в двух вкладках/устройствах и звони.

Production

Самый быстрый путь — на одном сервере:

npm run build            # собирает клиент в client/dist
npm start                # сервер раздаёт dist + API на одном порту (по умолчанию 3001)

Для нормального деплоя с доменом, HTTPS и автозапуском есть отдельный пошаговый гайд: deploy/DEPLOY.md.

В папке deploy/ лежат готовые шаблоны:

  • install.sh — устанавливает Node, ставит зависимости, собирает фронт, заводит системного пользователя owncord, кладёт код в /opt/owncord, включает systemd-сервис.
  • nginx.conf.example — reverse-proxy с поддержкой WebSocket и большими загрузками; стыкуется с Let's Encrypt через certbot.
  • owncord.service — unit-файл systemd для автозапуска и логов через journalctl.

Для маленькой группы пользователей хватает: VPS → bash install.sh → nginx + certbot → выставить REGISTRATION_CODE в .env → раздать код доверенным людям.

Переменные окружения (server/.env)

Полный пример с комментариями: server/.env.example.

Переменная Назначение
PORT HTTP-порт сервера (по умолчанию 3001).
NODE_ENV production включает строгий CSP/CORS и форсит проверку JWT_SECRET.
JWT_SECRET Секрет для JWT. Обязательно замени на длинную случайную строку (≥16 символов). В production сервер не стартует без неё.
JWT_TTL Срок жизни токена. По умолчанию 14d.
APP_ORIGIN CSV доменов фронтенда для CORS. В production без неё все кросс-доменные запросы блокируются (same-origin продолжает работать).
REGISTRATION_CODE Если задан — без этого кода регистрация невозможна.
REGISTRATION_DISABLED 1/true — полностью закрыть регистрацию (логин остаётся).
ADMIN_USERNAMES CSV username'ов админов. По умолчанию админ — пользователь id=1.
MAX_UPLOAD_MB Максимальный размер одного файла, по умолчанию 500.
RETENTION_DAYS Сколько дней хранить сообщения/вложения. По умолчанию 90 (раз в час чистится).
VAPID_PUBLIC_KEY / VAPID_PRIVATE_KEY / VAPID_SUBJECT Web Push (опц.; иначе автогенерация).
TURN_URL / TURN_USERNAME / TURN_PASSWORD Свой TURN (для строгого NAT).

Особенности шаринга экрана

  • Браузер сам предлагает выбрать: весь экран / окно / вкладка. Это эквивалент "конкретного приложения" в Discord.
  • На iOS Safari шаринг экрана через getDisplayMedia не поддерживается — на iPhone можно только принимать демонстрацию и участвовать в звонке. На Android Chrome и всех десктопах работает полноценно.

Десктоп-версия (Electron)

Опциональная нативная обёртка над веб-клиентом — нужна, если хочется глобальные хоткеи (мьют микро/наушников, работают даже когда окно не в фокусе) и автостарт. Все данные (сообщения, звонки, контакты) по-прежнему живут на сервере — десктоп ходит к нему по тем же URL'ам, что и браузер, и не дублирует ничего локально.

# Запуск из исходников (поднимет Electron, грузящий http://localhost:5173)
npm run dev          # стартует сервер + dev-сервер клиента
npm run desktop:dev  # в отдельном терминале — Electron-окно

# Сборка релиза под текущую ОС
npm run desktop:build
# Артефакты: desktop/dist/<platform>/...

При первом запуске десктоп спросит URL сервера. Конфиг сохраняется в %APPDATA%/OwnCord/owncord.config.json (на Linux/macOS — аналогичная папка профиля). Подробности и пер-OS сборка — в desktop/README.md.

Биндинги: Настройки → вкладка «Биндинги» (видна только в десктопе). Сейчас доступны два действия: «Мьют микрофона» и «Глушить динамики». Хоткей назначается записью комбинации (Ctrl/Shift/Alt + клавиша), формат — accelerator Electron'а (https://electronjs.org/docs/latest/api/accelerator).

Тесты

Backend (vitest + supertest) и frontend (vitest + RTL) покрывают auth, мьюты, сообщения, конечный автомат звонков (callRegistry), markdown-рендерер и ключевые компоненты.

# из корня проекта
npm test --workspace server   # node-тесты, изолированная sqlite
npm test --workspace client   # jsdom-тесты компонентов

Группы

  • В сайдбаре есть отдельная секция Группы с кнопкой для создания.
  • Создатель автоматически становится owner'ом; owner может переименовать группу, загрузить/удалить аватар, добавлять и удалять участников, а также удалить группу для всех. Обычный участник может только выйти.
  • Правой кнопкой на группе в сайдбаре — меню: «Редактировать», «Замутить», «Выйти»/«Удалить».
  • В групповом чате поддерживаются текст, редактирование/удаление, голосовые, файлы и изображения (всё как в DM).
  • Групповой звонок: кнопки 📞/🎥 в заголовке чата запускают сессию. Все остальные участники группы получают системное сообщение «X начал(а) звонок» с кнопкой «Подключиться»; над чатом параллельно показывается баннер «В этой группе сейчас идёт звонок · Подключиться», поэтому присоединиться можно в любой момент, пока сессия живая. В самом окне звонка доступны микрофон, камера и демонстрация экрана. Mesh-модель: каждый участник держит RTCPeerConnection с каждым, поэтому практический потолок — 8–10 человек; для больших встреч потребуется SFU (например mediasoup).
  • Все события групп (создание/правка/удаление/входящие сообщения/звонок) приходят через сокет в реальном времени — UI обновляется без перезагрузки.

Что дальше

Основа специально минимальная и расширяемая:

  • SFU для групповых встреч 10+ человек (например mediasoup)
  • Роли/модерация внутри группы
  • E2E-шифрование сообщений
  • Мобильные клиенты-обёртки (Capacitor/Tauri Mobile)

Лицензия

MIT © 2026 Restez

Исходный код и все производные работы распространяются свободно. Если разворачиваешь у себя — достаточно сохранить файл LICENSE с авторскими. Багрепорты и PR — в GitHub репозиторий.

About

self messenger

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages