Семейный мессенджер со сквозным шифрованием
Хотелось семейный чат, который живёт на своём сервере, не просит номер телефона и не зависит от чужих сервисов. И чтобы даже свой сервер не мог прочитать переписку. Так появился Family Messenger - код от протокола до релизов писал агент Claude Code под моим чутким руководством!

Что умеет
- Сквозное шифрование - каждое сообщение шифруется случайным ключом, который запечатывается каждому участнику (X25519 + XChaCha20-Poly1305) и подписывается Ed25519. На сервере лежит только шифротекст
- Чаты и группы до 100 человек, фото и файлы (тоже зашифрованы), исчезающие сообщения, правка и удаление
- Звонки 1:1 - голос, видео и демонстрация экрана, камеру и экран можно включить одновременно
- Голосовой канал в группе - заходишь когда хочешь, без звонка. Камеры и экраны у всех сразу, звук идёт напрямую между участниками
- Несколько устройств - телефон и ПК на одном аккаунте, новое устройство видит всю историю
- Поиск по сообщениям - прямо на устройстве: сервер их прочитать не может, значит и искать там нечего
- Приглашения по QR, админка, боты с вебхуками
- Клиенты - веб (ставится как PWA), Android, Windows и Linux на Flutter.
Дизайн
Интерфейс сначала нарисовал Claude Design: макеты всех экранов от входа до админки. Спецификацию с цветами и шрифтами Claude Code перенёс в оба клиента, так что веб и приложение выглядят одинаково.
Установка
Один бинарник на Go и один файл SQLite, хватает VPS на 1 vCPU и 512 МБ:
curl -fsSL https://raw.githubusercontent.com/william-aqn/family-messenger-e2e/main/deploy/install.sh | sudo sh
Скрипт спросит домен, скачает готовый сервер из релиза и сверит контрольную сумму, поднимет Caddy с сертификатом Let’s Encrypt и coturn для звонков из-за NAT, а в конце выдаст первый инвайт. Первый зарегистрированный становится администратором.
Обновления тоже без ручной возни: сервер - sudo family-messenger update, веб-версия сама предлагает перезагрузить страницу, приложения скачивают новый релиз с GitHub и ставят его.
Честно о границах
- Сервер видит метаданные - кто, с кем и когда переписывается, но не что
- Чтобы новое устройство читало всю историю, ключ у аккаунта один и хранится на сервере, зашифрованный паролем. Сбросить пароль через сервер нельзя: с любого устройства, где вы вошли, он меняется без старого, но если забыли его и не осталось ни одного такого устройства - переписка потеряна
- Коды безопасности собеседников стоит один раз сверить при встрече - так подмену ключей не провернёт даже свой сервер
Код и протокол открыты: github.com/william-aqn/family-messenger-e2e, готовые сборки - в релизах.
tags: ai - go - flutter - webrtc - e2e - self-hosted