This commit is contained in:
bvn13 2026-03-21 00:14:22 +03:00
parent 2e8c8ebdde
commit 41c2f9d07b

263
README.md
View File

@ -0,0 +1,263 @@
# Jabogram
XMPP-сервер для мессенджера с поддержкой голосовых/видеозвонков и хранением медиафайлов в S3.
**Стек:**
- [Snikket](https://snikket.org/) (Prosody) — XMPP-сервер
- PostgreSQL 17 — хранение данных Prosody
- rclone — монтирование S3-бакета как локальной директории
- Docker Compose — оркестрация сервисов
---
## Структура репозитория
```
jabogram/
├── server/ # Docker Compose + конфиги Snikket/Prosody
│ ├── scripts/ # Скрипты управления пользователями
│ └── ...
└── s3-mount/ # Скрипты монтирования S3 через rclone
```
---
## Установка с нуля
### 1. Требования к серверу
- Ubuntu 22.04+ (или Debian 12+)
- Docker + Docker Compose plugin
- Публичный IP-адрес
- Домен, указывающий на этот IP
### 2. DNS-записи
Создайте три записи для вашего домена (замените `chat.example.org` на свой):
| Тип | Имя | Значение |
|-------|----------------------------|--------------------|
| A | `chat.example.org` | IP-адрес сервера |
| CNAME | `groups.chat.example.org` | `chat.example.org` |
| CNAME | `share.chat.example.org` | `chat.example.org` |
Записи должны быть активны до первого запуска — они нужны для получения TLS-сертификатов.
### 3. Настройка файрвола
```bash
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 5222/tcp # XMPP client-to-server
ufw allow 5269/tcp # XMPP server-to-server (федерация)
ufw allow 5000/tcp # Proxy65 (передача файлов)
ufw allow 3478/udp
ufw allow 3478/tcp # STUN/TURN
ufw allow 5349/tcp
ufw allow 5349/udp # TURNS (TURN over TLS)
ufw allow 49152:65535/udp # TURN relay (аудио/видео)
```
### 4. Монтирование S3 через rclone
S3-бакет монтируется в `/mnt/snikket-files` и пробрасывается в контейнер Snikket — именно туда сохраняются файлы, загруженные через XMPP (XEP-0363 HTTP File Upload).
#### 4.1. Установка rclone и fuse3
```bash
cd s3-mount
sudo bash install-rclone.sh
```
Скрипт установит `fuse3`, скачает и установит `rclone`, после чего запустит `rclone config` для интерактивной настройки удалённого хранилища.
При конфигурации создайте remote с именем `jabogram-vk` (или измените имя в `rclone-snikket.service`), выбрав тип `s3` и указав ключи доступа к вашему S3-совместимому хранилищу.
#### 4.2. Настройка systemd-сервиса
Отредактируйте `s3-mount/rclone-snikket.service` при необходимости — проверьте путь к бакету:
```ini
ExecStart=/usr/bin/rclone mount \
jabogram-vk:jabogram/http_file_share \ # <remote>:<bucket>/<path>
/mnt/snikket-files \
...
```
Установите сервис:
```bash
cd s3-mount
sudo bash install-service.sh
```
Сервис запустится автоматически и будет стартовать при загрузке системы раньше Docker.
Проверьте монтирование:
```bash
systemctl status rclone-snikket
ls /mnt/snikket-files
```
### 5. Настройка сервера
```bash
cd server
```
#### 5.1. snikket.conf
```bash
cp snikket.conf.example snikket.conf
```
Обязательно задайте:
```ini
SNIKKET_DOMAIN=chat.example.org # ваш домен (нельзя изменить после первого запуска!)
SNIKKET_ADMIN_EMAIL=you@example.org # email для Let's Encrypt
```
#### 5.2. prosody.cfg.lua
```bash
cp prosody.cfg.lua.example prosody.cfg.lua
```
Замените `chat.example.org` на свой домен в строке:
```lua
http_upload_external_base_url = "http://chat.example.org:5050/upload/"
```
> Файл монтируется в контейнер Snikket как `/etc/prosody/conf.d/custom.cfg.lua` и задаёт PostgreSQL-бэкенд и внешний обработчик загрузки файлов.
#### 5.3. secrets.env
```bash
cp secrets.env.example secrets.env
```
Заполните реальными значениями:
```ini
UPLOAD_SECRET=случайная-строка-32-символа
AWS_ACCESS_KEY_ID=ваш-ключ
AWS_SECRET_ACCESS_KEY=ваш-секретный-ключ
POSTGRES_PASSWORD=надёжный-пароль
```
> `UPLOAD_SECRET` должен совпадать с `http_upload_external_secret` в `prosody.cfg.lua` — они уже связаны через `os.getenv("UPLOAD_SECRET")`.
#### 5.4. docker-compose.yml — путь монтирования файлов
В `docker-compose.yml` найдите строку вида:
```yaml
- /mnt/snikket-files:/snikket/prosody/share%2ejbr%2ebvn13%2eme/http_file_share
```
Часть `share%2ejbr%2ebvn13%2eme` — это URL-encoded путь вида `share.<домен>`. Замените на свой домен:
```yaml
- /mnt/snikket-files:/snikket/prosody/share%2echat%2eexample%2eorg/http_file_share
```
Правило кодирования: каждая точка `.` заменяется на `%2e`.
### 6. Первый запуск
```bash
cd server
docker compose up -d
```
Подождите ~30 секунд, пока Snikket получит TLS-сертификаты. Затем создайте администратора:
```bash
docker exec snikket create-invite --admin --group default
```
Команда выведет инвайт-ссылку вида `https://chat.example.org/invite/...` — откройте её в браузере для регистрации первого администратора.
---
## Управление пользователями
Все скрипты находятся в `server/scripts/` и читают `SNIKKET_DOMAIN` из `snikket.conf`.
| Скрипт | Действие |
|-----------------------|---------------------------------------|
| `invite-new.sh` | Создать инвайт для обычного пользователя |
| `invite-new-admin.sh` | Создать инвайт для администратора |
| `invite-list.sh` | Показать список инвайтов |
| `invite-revoke.sh` | Отозвать инвайт |
| `user-delete.sh` | Удалить пользователя |
| `cmd.sh` | Выполнить произвольную команду prosodyctl |
---
## Обновление
```bash
cd server
docker compose pull
docker compose up -d
```
---
## Бэкап
```bash
cd server
# Данные Snikket (аккаунты, сертификаты, настройки)
docker run --rm \
-v jabogram_snikket_data:/data \
-v $(pwd):/backup \
alpine tar czf /backup/snikket-backup.tar.gz -C /data .
# База данных PostgreSQL
docker exec snikket-postgres pg_dump -U snikket snikket \
| gzip > snikket-pg-backup.sql.gz
```
Медиафайлы хранятся в S3-бакете и бэкапируются отдельно средствами вашего S3-провайдера.
---
## Архитектура хранения файлов
```
XMPP-клиент
│ 1. Запрос слота (XEP-0363)
Prosody (mod_http_upload_external)
│ 2. Выдаёт подписанный URL → http://chat.example.org:5050/upload/...
s3_upload_handler (порт 5050)
│ 3. Проверяет HMAC, сохраняет файл в S3
│ (или через /mnt/snikket-files, смонтированный rclone)
S3-бакет
```
---
## Открытые порты
| Порт | Протокол | Назначение |
|---------------|----------|--------------------------------|
| 80 | TCP | HTTP (ACME, редирект на HTTPS) |
| 443 | TCP | HTTPS (веб-портал, файлы) |
| 5222 | TCP | XMPP client-to-server |
| 5269 | TCP | XMPP server-to-server |
| 5000 | TCP | Proxy65 (передача файлов) |
| 5050 | TCP | S3 upload handler |
| 3478, 5349 | TCP+UDP | STUN/TURN (звонки) |
| 4915265535 | UDP | TURN relay (аудио/видео) |