jabogram/README.md
2026-03-21 00:14:22 +03:00

264 lines
8.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 (аудио/видео) |