jabogram/server/README.md
2026-02-27 00:32:28 +03:00

195 lines
9.2 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.

# Snikket Server
XMPP-сервер на базе [Snikket](https://snikket.org/) (обёртка над Prosody с предварительной конфигурацией).
## Состав сервисов
| Сервис | Образ | Назначение |
|--------|-------|------------|
| `snikket_server` | `snikket/snikket-server:stable` | Ядро — Prosody XMPP-сервер |
| `snikket_proxy` | `snikket/snikket-web-proxy:stable` | Веб-прокси (nginx) |
| `snikket_certs` | `snikket/snikket-cert-manager:stable` | Автоматическое получение TLS-сертификатов (Let's Encrypt) |
| `snikket_portal` | `snikket/snikket-web-portal:stable` | Веб-портал для управления пользователями и инвайтами |
| `s3_upload_handler` | собирается из `./s3-upload-handler` | Обработчик загрузки файлов — принимает файлы от XMPP-клиентов и сохраняет в S3 |
| `postgres` | `postgres:15` | База данных PostgreSQL для Prosody |
Все сервисы работают в режиме `network_mode: host`.
## Требования
### DNS-записи
Для домена `chat.example.org` необходимо создать 3 записи:
| Тип | Имя | Значение |
|-----|-----|----------|
| A | `chat.example.org` | IP-адрес сервера |
| CNAME | `groups.chat.example.org` | `chat.example.org` |
| CNAME | `share.chat.example.org` | `chat.example.org` |
Опционально: AAAA-запись для IPv6, SRV-запись `_xmpps-client._tcp` для подключения через порт 443.
### Порты
| Порт | Протокол | Назначение |
|------|----------|------------|
| 80 | TCP | HTTP (ACME challenges, редирект на HTTPS) |
| 443 | TCP | HTTPS (веб-портал, file sharing) |
| 5222 | TCP | XMPP client-to-server |
| 5269 | TCP | XMPP server-to-server (федерация) |
| 5000 | TCP | Proxy65 (передача файлов) |
| 5050 | TCP | S3 upload handler (HTTP Upload External) |
| 5432 | TCP | PostgreSQL |
| 3478, 3479 | TCP+UDP | STUN/TURN |
| 5349, 5350 | TCP+UDP | STUN/TURN over TLS |
| 4915265535 | UDP | TURN relay (аудио/видео данные) |
## Конфигурация
### prosody.cfg.lua
Кастомная конфигурация Prosody, монтируется в контейнер `snikket_server` как `/etc/prosody/conf.d/custom.cfg.lua`. Содержит:
- **PostgreSQL** — `storage = "sql"` с драйвером PostgreSQL (подключение к `127.0.0.1:5432`)
- **HTTP Upload External** — `mod_http_upload_external` для загрузки файлов через внешний S3 upload handler
### secrets.env
Файл с секретами, **не коммитится в git** (добавлен в `.gitignore`). Перед первым запуском необходимо создать его и заполнить реальными значениями:
```bash
cp secrets.env.example secrets.env
# отредактировать secrets.env
```
| Переменная | Описание |
|------------|----------|
| `UPLOAD_SECRET` | Shared secret (должен совпадать с `http_upload_external_secret` в `prosody.cfg.lua`) |
| `AWS_ACCESS_KEY_ID` | Ключ доступа AWS/S3 |
| `AWS_SECRET_ACCESS_KEY` | Секретный ключ AWS/S3 |
| `POSTGRES_PASSWORD` | Пароль PostgreSQL |
### S3 Upload Handler (environment)
Несекретные параметры задаются в `docker-compose.yml` в секции `environment` сервиса `s3_upload_handler`:
| Переменная | Описание |
|------------|----------|
| `S3_BUCKET` | Имя S3-бакета |
| `S3_REGION` | Регион S3 |
| `S3_ENDPOINT` | URL S3-совместимого хранилища (MinIO и др.), не задавать для AWS |
| `PRESIGN_EXPIRE` | Время жизни presigned URL для скачивания (секунды, по умолчанию `3600`) |
### snikket.conf
### Обязательные параметры
| Переменная | Описание |
|------------|----------|
| `SNIKKET_DOMAIN` | Домен сервера. **Нельзя изменить после первого запуска.** |
| `SNIKKET_ADMIN_EMAIL` | Email администратора (используется для Let's Encrypt) |
### Основные параметры
| Переменная | По умолчанию | Описание |
|------------|-------------|----------|
| `SNIKKET_SITE_NAME` | значение `SNIKKET_DOMAIN` | Человекочитаемое имя сервера |
| `SNIKKET_RETENTION_DAYS` | `7` | Сколько дней хранить сообщения (MAM) и загруженные файлы |
| `SNIKKET_UPLOAD_STORAGE_GB` | без лимита | Лимит дискового пространства для загруженных файлов (напр. `1.5`) |
| `SNIKKET_LOGLEVEL` | `info` | Уровень логирования: `error`, `warn`, `info`, `debug` |
| `SNIKKET_ABUSE_EMAIL` | — | Публичный email для жалоб |
| `SNIKKET_SECURITY_EMAIL` | — | Публичный email для сообщений о безопасности |
| `SNIKKET_UPDATE_CHECK` | `1` | Установить `0` чтобы отключить проверку обновлений |
### Параметры reverse proxy
| Переменная | По умолчанию | Описание |
|------------|-------------|----------|
| `SNIKKET_TWEAK_HTTP_PORT` | `80` | HTTP-порт (изменить при работе за reverse proxy) |
| `SNIKKET_TWEAK_HTTPS_PORT` | `443` | HTTPS-порт (изменить при работе за reverse proxy) |
### Параметры TURN-сервера
| Переменная | По умолчанию | Описание |
|------------|-------------|----------|
| `SNIKKET_TWEAK_TURNSERVER` | `1` | Установить `0` для отключения встроенного TURN |
| `SNIKKET_TWEAK_TURNSERVER_DOMAIN` | значение `SNIKKET_DOMAIN` | Домен внешнего TURN-сервера |
| `SNIKKET_TWEAK_TURNSERVER_PORT` | `3478` | Порт TURN-сервера |
| `SNIKKET_TWEAK_TURNSERVER_SECRET` | автогенерация | Shared secret для аутентификации TURN |
### Прочие параметры
| Переменная | По умолчанию | Описание |
|------------|-------------|----------|
| `SNIKKET_TWEAK_IPV6` | `1` | Установить `0` для отключения IPv6 |
| `SNIKKET_TWEAK_STORAGE` | `files` | Бэкенд хранения: `files` или `sqlite` (превью) |
| `SNIKKET_TWEAK_EXTRA_CONFIG` | — | Путь/glob к дополнительным файлам конфигурации Prosody |
| `SNIKKET_PROXY65_PORT` | `5000` | Порт proxy для передачи файлов |
| `SNIKKET_TWEAK_DNSSEC` | — | Включить поддержку DNSSEC и DANE |
## Запуск
```bash
cd server
# 1. Настроить конфигурацию
# отредактировать snikket.conf значениями вашего домена
# 2. Заполнить секреты
cp secrets.env.example secrets.env
# отредактировать secrets.env реальными значениями
# 3. Запустить
docker compose up -d
# 3. Создать admin-аккаунт
docker exec snikket create-invite --admin --group default
```
Инвайт-ссылку открыть в браузере для регистрации администратора.
## Обновление
```bash
cd server
docker compose pull
docker compose up -d
```
## Хранение данных
Данные хранятся в Docker volumes:
| Volume | Содержимое |
|--------|-----------|
| `snikket_data` | Данные сервера: аккаунты, сообщения, TLS-сертификаты |
| `acme_challenges` | Временные файлы ACME (Let's Encrypt) |
| `postgres_data` | Данные PostgreSQL |
Загруженные файлы хранятся в S3-бакете (не в volumes).
### Бэкап
Необходимо сохранить volume `snikket_data` и базу PostgreSQL:
```bash
# Snikket data
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)
Загруженные файлы (HTTP File Upload, XEP-0363) хранятся в **S3-бакете** через кастомный `s3_upload_handler`.
Схема работы:
1. XMPP-клиент запрашивает у Prosody слот для загрузки файла
2. Prosody (`mod_http_upload_external`) генерирует подписанный URL, указывающий на `s3_upload_handler`
3. Клиент загружает файл по этому URL
4. `s3_upload_handler` проверяет HMAC-подпись и сохраняет файл в S3
5. При скачивании — handler генерирует presigned S3 URL и делает redirect