🛠 Подготовка: DNS и Фаервол
До запуска серверов необходимо подготовить сетевую инфраструктуру.
1.Настройка DNS-записей
В панели вашего регистратора доменов создайте следующие записи (замените 203.0.113.1 на внешний IP вашего сервера):
A-записи (Направляем домены на сервер):
A -> chat.example.com -> 203.0.113.1
A -> upload.chat.example.com -> 203.0.113.1
A -> conference.chat.example.com -> 203.0.113.1
A -> movim.example.com -> 203.0.113.1 (Для веб-клиента)
SRV-записи (Компасы маршрутизации для клиентов и федерации):
Для клиентов (Стандартное подключение):
Имя (Хост): _xmpp-client._tcp.chat | Тип: SRV | Значение: 5 0 5222 chat.example.com.
Для серверов (Федерация S2S):
Имя (Хост): _xmpp-server._tcp.chat | Тип: SRV | Значение: 5 0 5269 chat.example.com.
Для клиентов (Прямое шифрование - Direct TLS):
Имя (Хост): _xmpps-client._tcp.chat | Тип: SRV | Значение: 5 0 5223 chat.example.com.
Для серверов (Прямое шифрование - Direct TLS):
Имя (Хост): _xmpps-server._tcp.chat | Тип: SRV | Значение: 5 0 5270 chat.example.com.
- Настройка Фаервола (UFW / Панель хостинга)
Откройте необходимые порты для работы XMPP, передачи файлов и видео-трафика: Bash
Базовые порты XMPP и передача файлов SOCKS5
sudo ufw allow 5222/tcp sudo ufw allow 5269/tcp sudo ufw allow 5000/tcp
Порты для прямого шифрования (Direct TLS)
sudo ufw allow 5223/tcp sudo ufw allow 5270/tcp
Порты для видеозвонков (Coturn)
sudo ufw allow 3479/tcp sudo ufw allow 3479/udp sudo ufw allow 5349/tcp sudo ufw allow 50000:50500/udp
ШАГ 1: Подготовка плагинов Prosody
В версии 13.0 (Nightly) изменились пути к Lua-модулям, поэтому сервер может не находить важные расширения (например, для передачи файлов). Самое надежное решение — скачать свежие плагины прямо из официального репозитория разработчика и прокинуть их в контейнер.
Выполняем в терминале сервера:
1. Создаем структуру папок для нашего проекта
mkdir -p ./prosody/modules-custom
mkdir -p ./prosody/config/certs
mkdir -p ./prosody/data
2. Скачиваем ВСЕ свежие плагины во временную папку из репозитория
git clone --depth 1 --branch master https://github.com/bjc/prosody.git temp_prosody_git
3. Копируем папку plugins в нашу рабочую директорию модулей
cp -r temp_prosody_git/plugins/. ./prosody/modules-custom/
4. Удаляем временную папку (убираем мусор)
rm -rf temp_prosody_git
5. Выдаем права, чтобы Докер мог читать эти файлы
sudo chmod -R 755 ./prosody/modules-custom/
ШАГ 2: Выпуск “Тройного” сертификата
Групповые комнаты (MUC) и загрузка файлов (Upload) живут на виртуальных поддоменах. Без сертификата на эти поддомены другие серверы не смогут общаться с вашим.
Зайдите в Nginx Proxy Manager (вкладка SSL Certificates).
Выпустите один SSL-сертификат сразу на три домена, вписав их через запятую или Enter: chat.example.com, upload.chat.example.com, conference.chat.example.com
Скопируйте полученные ключи из папки NPM в папку Prosody:
fullchain.pem переименуйте в xmpp.crt
privkey.pem переименуйте в xmpp.key
Положите их в папку ./prosody/config/certs/ и выдайте права:
sudo chmod 644 ./prosody/config/certs/*
ШАГ 3: Клонирование и подготовка сборки Movim
Поскольку готового Docker-образа нет, мы собираем его из исходников. Это гарантирует наличие всех последних фиксов.
1. Клонируем репозиторий: В корневой папке проекта (рядом с папкой prosody) выполните:
git clone https://github.com/movim/movim.git
2. Создаем файл окружения .env: Внутри папки movim создайте файл .env. Он нужен для инициализации базы данных при сборке:
nano ./movim/.env
Вставьте туда ваши параметры (без пробелов около =):
POSTGRES_USER=movim
POSTGRES_PASSWORD=movim
POSTGRES_DB=movim
- Предварительная сборка: Чтобы Docker не выдавал ошибку «не найден», мы собираем и запускаем Movim отдельно в его папке:
cd movim
Создайте (отредактируйте) файл podman-compose.yml:
Не забудьте отредактировать значения на ваши домены и ip адреса
services:
db:
image: 'docker.io/postgres:latest'
environment:
POSTGRES_USER: movim
POSTGRES_PASSWORD: movim
POSTGRES_DB: movim
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 2s
networks:
- movim_internal
movim:
build:
context: ./
dockerfile: Containerfile
depends_on:
db:
condition: service_healthy
environment:
DB_HOST: db
DB_PORT: 5432
DB_NAME: movim
DB_USER: movim
DB_PASSWORD: movim
DAEMON_URL: https://movim.tprod.space
DAEMON_DEBUG: true
DAEMON_VERBOSE: true
ports:
- 43564:8443
networks:
- movim_internal
- npm_default
extra_hosts:
- "chat.example.com:203.0.113.1"
- "upload.chat.example.com:203.0.113.1"
- "conference.chat.example.com:203.0.113.1"
networks:
movim_internal:
npm_default:
external: true
name: npm_default
podman-compose.yml ожидает внешнюю сеть npm_default. Чтобы запуск не упал с ошибкой “network not found”, создай её вручную (если еще не создана):
docker network create npm_default
Запускаем сборку:
docker-compose -f podman-compose.yml up -d --build
Флаг --build обязателен, для создания образа из локальных исходников.
Ждем завершения сборки. Теперь образ существует локально.
- Останавливаем временный запуск и возвращаемся в папку проекта
docker-compose -f podman-compose.yml down
cd ..
ШАГ 3.1: Создание podman-compose.yml
Теперь создаем основной файл оркестрации. Мы используем extra_hosts, чтобы Movim внутри контейнера точно знал, по какому IP искать чат-сервер, не полагаясь на внешние DNS-резолверы.
Создайте docker-compose.yml в корневой директории (например /opt/prosody)
Не забудьте отредактировать значения ваших доменов и ip адресов.
services:
# 1. Prosody (XMPP)
prosody:
image: prosodyim/prosody:13.0
container_name: prosody
restart: unless-stopped
ports:
- "5222:5222"
- "5269:5269"
- "5223:5223"
- "5270:5270"
volumes:
- ./prosody/config/prosody.cfg.lua:/etc/prosody/prosody.cfg.lua:ro
- ./prosody/config/certs:/etc/prosody/certs:ro
- ./prosody/data:/var/lib/prosody
- ./prosody/modules-custom:/usr/lib/prosody/modules-custom:ro
networks:
npm_default:
aliases:
- chat.example.com
- upload.chat.example.com
# 2. Coturn (Video)
coturn:
image: coturn/coturn:latest
container_name: coturn-chat
network_mode: "host"
command:
- -n
- --external-ip=203.0.113.1
- --static-auth-secret=SUPER_SECRET_123
- --realm=chat.example.com
- --listening-port=3479
- --tls-listening-port=5349
# 3. База данных для Movim
db:
image: 'docker.io/postgres:latest'
container_name: movim_db
environment:
POSTGRES_USER: movim
POSTGRES_PASSWORD: movim
POSTGRES_DB: movim
healthcheck:
test: ["CMD-SHELL", "pg_isready -U movim -d movim"]
interval: 2s
networks:
- movim_internal
# 4. Movim (Веб-клиент) - ССЫЛАЕМСЯ НА ИСХОДНИКИ
movim:
build:
context: ./movim
dockerfile: Containerfile
container_name: movim_app
restart: unless-stopped
depends_on:
db:
condition: service_healthy
environment:
DB_HOST: db
DB_PORT: 5432
DB_NAME: movim
DB_USER: movim
DB_PASSWORD: movim
DAEMON_URL: https://movim.tprod.space
DAEMON_DEBUG: "true"
DAEMON_VERBOSE: "true"
ports:
- "43564:8443"
networks:
- movim_internal
- npm_default
extra_hosts:
- "chat.example.com:203.0.113.1"
- "upload.chat.exmple.com:203.0.113.1"
networks:
movim_internal:
npm_default:
external: true
name: npm_default
ШАГ 3.2: Запуск всей системы
Для запуска используем явное указание файла, так как мы назвали его в стиле Podman:
docker-compose -f podman-compose.yml up -d
ШАГ 4: Идеальный prosody.cfg.lua
Создайте файл ./prosody/config/prosody.cfg.lua. Этот монолитный конфиг включает современную безопасность, работу с веб-клиентами, CORS, загрузку тяжелых файлов, пуши и видеозвонки. Не забудьте отредактировать значения на ваши домены и ip адреса.
-- =======================================================================
-- PROSODY CONFIGURATION FOR DOCKER (v13.0+) & MOVIM
-- =======================================================================
-- 1. ГЛОБАЛЬНЫЕ НАСТРОЙКИ
-- -----------------------
plugin_paths = { "/usr/lib/prosody/modules-custom" }
local my_domain = "chat.example.com"
admins = { "admin@chat.example.com" } -- указать акаунт админа
contact_info = {
abuse = { "mailto:admin@example.com", "xmpp:admin@chat.example.com" };
} -- почта и xmpp для жалоб от пользователей (например за спам)
external_addresses = { "203.0.113.1" } -- ВАШ ВНЕШНИЙ IP-АДРЕС
http_interfaces = { "*" } -- Мостик для Nginx (чтобы не было 502 ошибки)
-- Требуем шифрование для всех
c2s_require_encryption = true
s2s_require_encryption = true
authentication = "internal_hashed"
-- Порты для прямого шифрования (Direct TLS)
c2s_direct_tls_ports = { 5223 }
s2s_direct_tls_ports = { 5270 }
-- Разрешаем свободную регистрацию аккаунтов (XEP-0077)
allow_registration = true
-- Пути к данным внутри контейнера
data_path = "/var/lib/prosody"
pidfile = "/var/run/prosody/prosody.pid"
-- 2. МОДУЛИ (ПЛАГИНЫ)
-- -------------------
modules_enabled = {
-- Ядро XMPP
"roster"; "saslauth"; "tls"; "dialback"; "disco"; "ping";
-- Мобильные клиенты, пуши и экономия батареи
"cloud_notify"; "smacks"; "csi_simple"; "csi"; "carbons"; "mam";
-- Сеть, прокси и обнаружение сервисов
"proxy65"; "http_altconnect"; "server_info"; "external_services";
-- Профили, аватарки, статусы, подписки и черные списки
"pep"; "vcard4"; "vcard_legacy"; "avatar"; "profile"; "pubsub"; "pubsub_serverinfo"; "blocklist";
-- ВАЖНО ДЛЯ MOVIM И БРАУЗЕРОВ (Веб-клиенты)
"bosh"; "websocket"; "http_file_share";
-- Регистрация аккаунтов прямо из приложения (XEP-0077)
"register";
-- ====================================================================
-- ИСТОРИЯ АРХИТЕКТУРЫ (Устаревшие и продублированные модули)
-- ====================================================================
-- "server_contact_info"; -- УСТАРЕЛ: В Prosody 13+ встроен в 'server_info'
-- "pep_vcard_avatar"; -- УСТАРЕЛ: Несовместим с новым движком 'pep'
};
-- Координаты сервера видеозвонков (Coturn) на альтернативных портах
external_services = {
{ type = "stun", host = "chat.example.com", port = 3479, transport = "udp" },
{ type = "stun", host = "chat.example.com", port = 3479, transport = "tcp" },
{ type = "turn", host = "chat.example.com", port = 3479, transport = "udp", secret = "SUPER_SECRET_123" },
{ type = "turn", host = "chat.example.com", port = 3479, transport = "tcp", secret = "SUPER_SECRET_123" },
{ type = "turns", host = "chat.example.com", port = 5349, transport = "tcp", secret = "SUPER_SECRET_123" }
}
-- 3. НАСТРОЙКИ ИСТОРИИ (MAM)
-- --------------------------
default_archive_policy = "roster" -- Сохранять переписку с контактами
archive_expires_after = "2y" -- Хранить историю 2 года
-- 4. НАСТРОЙКИ HTTP И CORS (Критично для Movim)
-- ---------------------------------------------
http_cors_override = {
bosh = {
origin = "*";
methods = { "GET", "POST", "OPTIONS" };
headers = { "Content-Type", "Origin", "Authorization" };
credentials = false;
};
websocket = {
origin = "*";
methods = { "GET", "POST", "OPTIONS" };
headers = { "Content-Type", "Origin", "Authorization" };
credentials = false;
};
http_upload = {
origin = "*";
methods = { "GET", "POST", "PUT", "OPTIONS", "HEAD" };
headers = { "Content-Type", "Origin", "Authorization", "Content-Length" };
credentials = false;
};
}
-- 5. СЕРТИФИКАТЫ (SSL/TLS)
-- ------------------------
ssl = {
key = "/etc/prosody/certs/xmpp.key";
certificate = "/etc/prosody/certs/xmpp.crt";
options = { "no_sslv2", "no_sslv3", "no_ticket", "no_compression", "cipher_server_preference", "single_dh_use", "single_ecdh_use" };
}
-- =======================================================================
-- ВИРТУАЛЬНЫЕ ХОСТЫ И КОМПОНЕНТЫ (СТРОГО В САМОМ НИЗУ ФАЙЛА!)
-- =======================================================================
-- 6. ВИРТУАЛЬНЫЙ ХОСТ (ОСНОВНОЙ ДОМЕН)
-- ------------------------------------
VirtualHost (my_domain)
pubsub_serverinfo_service = "pubsub.chat.example.com"
-- 7. ГРУППОВЫЕ ЧАТЫ (MUC)
-- ------------------------------------
Component "conference.chat.example.com" "muc"
name = "Общие комнаты"
restrict_room_creation = false
muc_log_by_default = true
muc_log_presences = false
modules_enabled = { "mam", "muc_mam" }
-- 8. КОМПОНЕНТ ЗАГРУЗКИ ФАЙЛОВ
-- ----------------------------
Component "upload.chat.example.com" "http_file_share"
http_upload_file_size_limit = 50 * 1024 * 1024 -- Лимит 50 МБ
http_upload_path = "/var/lib/prosody/http_upload"
-- 9. СИСТЕМА ПУБЛИКАЦИЙ И ПОДПИСОК (PUBSUB)
-- ------------------------------------
Component "pubsub.chat.example.com" "pubsub"
admins = { my_domain }
ШАГ 5: Настройка Nginx Proxy Manager (NPM)
Зайдите в панель управления NPM и создайте Proxy Hosts для маршрутизации веб-трафика внутрь Докер-контейнеров:
Домен: chat.example.com
Forward Hostname / IP: prosody
Forward Port: 5280
Включить галочку Websockets Support.
SSL: Выбрать созданный сертификат, включить Force SSL.
Домен: upload.chat.example.com
Forward Hostname / IP: prosody
Forward Port: 5280
SSL: Выбрать созданный сертификат, включить Force SSL.
Домен: movim.example.com (Если нужен веб-клиент)
Forward Hostname / IP: movim_app
Forward Port: 43564 (Или 8443, в зависимости от того, как слушает контейнер внутри)
Включить галочку Websockets Support.
SSL: Выпустить отдельный сертификат для этого домена, включить Force SSL.
ШАГ 6: Первый запуск и тестирование! 🎉
Находясь в папке с docker-compose.yml, поднимите инфраструктуру:
docker compose up -d
Зарегистрируйте аккаунт администратора через внутреннюю консоль контейнера:
docker exec -it prosody prosodyctl register admin chat.example.com ВАШ_СЛОЖНЫЙ_ПАРОЛЬ
Рассылка
Получайте уведомления о новых постах и не только. Без спама.