snikket xmpp сервер

Snikket: простой XMPP-сервер для команды — установка в Docker за 15 минут

Snikket XMPP-сервер — это готовая Docker-сборка для команды от 5 до 50 человек, которая разворачивается за 15 минут на VPS с 1 ГБ RAM и Docker 20.10.10 или новее. Внутри уже работает Prosody, ACME-клиент Let’s Encrypt, прокси push-уведомлений для iOS и Android, веб-клиент Converse.js — без отдельных конфигов nginx, certbot и знания протокола XMPP.

Ниже разбираем пошаговую установку на Ubuntu 22.04, конфигурацию из трёх DNS-записей, открытие портов 80, 443, 5222, 5223, 5269, интеграцию с существующим nginx и сравнение с ejabberd и Matrix/Synapse по TCO на 12 месяцев. В конце — четыре частых вопроса по reverse proxy, бэкапу SQLite и подключению десктопных клиентов вроде Gajim и Dino.

snikket xmpp сервер

Ключевой тезис: snikket xmpp сервер запускается одной командой docker compose up -d, требует минимум 1 ГБ RAM, Docker 20.10.10+ и три DNS-записи (A для chat., CNAME для groups.chat. и share.chat.) — остальное он делает сам, включая выпуск сертификатов Let’s Encrypt.

Содержание

Что такое Snikket и кому он подходит вместо ejabberd или Matrix

Snikket — это не самостоятельный XMPP-сервер с нуля, а preconfigured XMPP server distribution (так его описывает каталог xmpp.org). Внутри Docker-образа работают Prosody с набором модулей, веб-интерфейс администратора, ACME-клиент Let’s Encrypt, прокси push-уведомлений для iOS и Android, веб-клиент Converse.js на адресе chat.your-domain.

Мы в IT For Prof выбираем snikket xmpp сервер, когда у заказчика SMB-команда на 5–50 человек, нет отдельного DevOps-инженера и нужно мобильное приложение, которое не требует объяснять пользователям, что такое JID и SRV-запись. Snikket прячет эту сложность за инвайт-системой: администратор генерирует одноразовую ссылку, пользователь сканирует QR — клиент сам подставляет домен, логин и пароль.

Случаи, когда Snikket не подходит: команда больше 100 человек с ливом из LDAP/AD — смотрите ejabberd Business или Matrix/Synapse; требуется федерация с Telegram и IRC через bridges — это домен Matrix; нужны webhooks от GitLab CI и каналы по проектам — Mattermost удобнее.

Архитектурно Snikket = Prosody + готовый набор модулей: mod_invites, mod_storage_sql, mod_cloud_notify, mod_http_upload, mod_pubsub. Если собирать такой стек на чистом ejabberd, уйдёт 30–60 минут на конфиг и столько же на push-прокси для iOS. Snikket ставит это коробочно за 15 минут.

Поддерживаемые архитектуры: Linux 64-bit (amd64), ARMv7 и ARMv8, включая Raspberry Pi 2/3/4 — для домашних сценариев или офиса с одноплатником в шкафу. Лицензия — AGPL, исходники открыты на github.com/snikket-im. Платных подписок нет — только добровольные взносы через Open Collective или GitHub Sponsors. Для российского B2B это важно: проект не закроется по решению зарубежной компании и не сменит модель монетизации в один день, как это сделали Slack и Atlassian с бесплатными тарифами в 2023–2024 годах.

Что такое Snikket и кому он подходит вместо ejabberd или Matrix

Подготовка VPS и DNS-записей: SRV, A и порты для XMPP

Перед запуском убедитесь, что VPS отвечает минимуму: Ubuntu 22.04 или Debian 12, от 1 ГБ RAM, Docker 20.10.10 или новее. Официальный FAQ Snikket указывает, что сервер вмещает 10–15 пользователей в 128 МБ RAM, но в production этого мало: docker-образ весит ~250 МБ, ACME-перевыпуск сертификатов и swap-фризы бьют по такой конфигурации. Берите 1 ГБ сразу.

DNS-записи. snikket xmpp сервер требует три записи на основном домене chat.your-domain: A-запись chat.example.com в IP вашего VPS, CNAME groups.chat.example.com в chat.example.com, CNAME share.chat.example.com в chat.example.com. Это нужно для разделения зон ACME-валидации: Let’s Encrypt выпускает раздельные сертификаты на каждый поддомен, и share/groups обслуживают свои функции (http_upload и MUC).

Если перед сервером стоит CDN или CloudFlare, выключите proxy-режим («оранжевую тучку») для всех трёх записей: XMPP-трафик на 5222 и 5269 через HTTP-CDN не пройдёт. На этом этапе мы обычно отвязываем домен от CloudFlare вообще — иначе все клиенты будут видеть «connection refused» на 5222.

SRV-записи опциональны. XMPP-клиенты вроде Gajim и Conversations определяют сервер автоматически по _xmpp-client._tcp.example.com SRV 0 0 5222 chat.example.com и _xmpp-server._tcp.example.com SRV 0 0 5269 chat.example.com. Без этого пользователям придётся ручно вписывать домен сервера. Для команды это допустимо, для самообслуживания внешних клиентов — добавьте.

Порты по официальной документации Snikket из firewall guide:

  • 80/tcp, 443/tcp — HTTPS, веб-клиент Converse.js, валидация Let’s Encrypt;
  • 5222/tcp — XMPP-клиент с STARTTLS (нешифрованный трафик с обязательным upgrade);
  • 5223/tcp — encrypted XMPP (DirectTLS / xmpps), явный TLS без STARTTLS;
  • 5269/tcp — server-to-server (s2s) федерация с другими XMPP-серверами;
  • 5000/tcp — proxy65, передача файлов когда P2P невозможен;
  • 3478/tcp+udp, 5349/tcp+udp — STUN/TURN для аудио- и видеозвонков.

В ufw это добавляется по списку одной командой. Если хостинг-провайдер вроде Selectel или Timeweb имеет собственный внешний firewall, добавьте правила в панели управления.

Подготовка VPS и DNS-записей: SRV, A и порты для XMPP

Установка Snikket в Docker за 15 минут: docker-compose.yml с пояснениями

Мы разворачиваем snikket xmpp сервер по официальному квикстарту с github.com/snikket-im/snikket-server. Готовый docker-compose.yml уже есть в репозитории — клонируем и запускаем. Создайте директорию /opt/snikket и положите туда два файла: docker-compose.yml с описанием сервиса и snikket.conf с переменными среды.

В snikket.conf пропишите минимум две переменные: SNIKKET_DOMAIN=chat.example.com и SNIKKET_ADMIN_EMAIL=admin@example.com. Это всё, что нужно для первого запуска. Дополнительные тюнинги (TWEAK-переменные) добавятся позже при интеграции с reverse proxy.

Запускаем контейнер командой docker compose up -d. На холодном старте Snikket делает несколько вещей за 2–3 минуты: тянет образ ~250 МБ, инициализирует SQLite-базу Prosody, генерирует DH-параметры для XMPP и запрашивает три сертификата Let’s Encrypt по HTTP-01-вызову. Логи смотрим через docker compose logs -f snikket.

Если всё прошло успешно, откройте https://chat.example.com — появится welcome-страница с предложением создать первого администратора. Если выдаёт 502 или сертификат не выпустился — проверьте, что порты 80 и 443 свободны (на свежем Ubuntu иногда висит apache2 из стандартной поставки) и что все три DNS-записи резолвятся в IP вашего VPS.

Создаём первого администратора через CLI: docker exec snikket_server snikket create-invite –admin –group default. Команда выдаст ссылку вида https://chat.example.com/invite/abc123. Откройте её в Snikket-приложении на телефоне или в Converse.js по адресу chat.example.com — задайте логин и пароль. Флаг –admin даёт права администратора, –group default включает вас в общий чат. Дальше всё администрирование идёт через веб-панель https://chat.example.com/admin/.

				
					version: "3"
services:
  snikket:
    image: snikket/snikket:latest
    container_name: snikket_server
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "5222:5222"
      - "5223:5223"
      - "5269:5269"
      - "5000:5000"
      - "3478:3478"
      - "5349:5349"
      - "3478:3478/udp"
      - "5349:5349/udp"
    env_file:
      - ./snikket.conf
    volumes:
      - snikket_data:/snikket
volumes:
  snikket_data:
				
			

Интеграция с Nginx reverse proxy и Let's Encrypt без конфликта портов

Базовая установка Snikket занимает порты 80 и 443. Если на сервере уже работает nginx — лендинг компании, dashboard Grafana или другой сервис — snikket xmpp сервер в стандартной конфигурации не запустится: ACME-валидация Let’s Encrypt не получит ответ на http-01 challenge.

Решения два: либо отдать 80/443 Snikket’у целиком, либо проксировать через ваш nginx. Официальная документация Snikket держит отдельный раздел про reverse proxy с готовыми конфигами Nginx (snikket.org/service/help/advanced/reverse_proxy/). Принцип такой: nginx слушает 80/443, выполняет TLS-терминацию, проксирует HTTP-трафик трёх поддоменов (chat.*, groups.chat.*, share.chat.*) в Snikket по альтернативным портам (например, 5080/5443).

XMPP-порты 5222, 5223, 5269 не проксируются — это не HTTP, и nginx их просто не видит. Они идут напрямую в контейнер. Сертификаты Let’s Encrypt в этом сценарии получает nginx через certbot или acme.sh, а Snikket внутри работает по внутренним самоподписанным.

Сертификат нужен с тремя SAN-именами — выпускается командой certbot certonly –nginx -d chat.example.com -d groups.chat.example.com -d share.chat.example.com. На загрузку файлов через mod_http_upload поставьте client_max_body_size 50M или больше, иначе пользователи будут получать 413 при отправке вложений.

В docker-compose.yml переменные SNIKKET_TWEAK_HTTP_PORT=5080 и SNIKKET_TWEAK_HTTPS_PORT=5443 добавляются в блок environment или в snikket.conf, входящие порты мапятся как 5080:80 и 5443:443. После изменения конфига — docker compose down, потом docker compose up -d, перечитываем nginx через nginx -s reload и проверяем https://chat.example.com/. На стороне XMPP-клиентов ничего не меняется.

				
					server {
    listen 443 ssl http2;
    server_name chat.example.com groups.chat.example.com share.chat.example.com;

    ssl_certificate /etc/letsencrypt/live/chat.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/chat.example.com/privkey.pem;

    client_max_body_size 50M;

    location / {
        proxy_pass http://127.0.0.1:5080;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
				
			

Приглашение пользователей, мобильные клиенты и групповые чаты

Snikket принципиально работает по приглашениям — открытой регистрации нет. На странице https://chat.example.com/admin/invites администратор генерирует одноразовую или многоразовую ссылку для всей команды. Ссылка действует ограниченное время (по умолчанию 7 дней) и привязывается к группам, в которые автоматически попадает новый пользователь.

Мобильные клиенты. У проекта два собственных приложения. Snikket для iOS — форк Siskin, доступен в App Store. Push-уведомления идут через APNs-прокси самого Snikket-проекта — бесплатно и не требует своего разработчического аккаунта Apple. Snikket для Android — форк Conversations, есть в Google Play и в F-Droid. F-Droid-сборка работает без Google Services, push идёт по ntfy-протоколу.

Первый запуск: пользователь сканирует QR с приглашением — клиент сам прописывает домен сервера, JID и пароль. Никаких полей «введите server.example.com, port 5223, encryption type STARTTLS» — это критично для внедрения в команде из 30 человек, из которых только пять разбираются в IT.

Десктоп. Своего приложения у Snikket нет, и это сознательный выбор: сервер использует стандартный XMPP, и любой XMPP-клиент подключится без специальной настройки. Мы рекомендуем заказчикам: Gajim на Windows и Linux — зрелый клиент с OMEMO-шифрованием, группами и аудио-видеозвонками; Dino на Linux и macOS через brew — современный UI; Monal — нативный клиент для macOS и iOS; Beagle IM — лёгкий клиент Tigase для macOS. Конфигурация одинаковая: JID — user@chat.your-domain, пароль — из Snikket-приглашения.

Групповые чаты (MUC, Multi-User Chat) создаются через мобильный клиент или Converse.js. Администратор назначает тип: открытый (любой пользователь сервера присоединяется), закрытый (только по приглашению), публичный (доступен извне через HTTP). История хранится на сервере в mod_mam, синхронизируется между устройствами одного пользователя. Шифрование OMEMO работает «из коробки» в личных чатах; в групповых требует включения каждым участником отдельно — это ограничение OMEMO, не Snikket.

Резервное копирование SQLite и media, обновление контейнеров без простоя

Snikket хранит данные в Docker volume snikket_data. Структура внутри: /snikket/prosody/data/ — SQLite-база с сообщениями, ростерами и метаданными; /snikket/letsencrypt/ — сертификаты; /snikket/uploads/ — файлы из mod_http_upload. На команде из 30 человек после года переписки полный бэкап весит 200–500 МБ.

Минимальный бэкап — tar-архив всего volume через временный alpine-контейнер. Положите задачу в cron еженедельно, ротируйте копии (мы держим 4 недельных + 12 месячных). Для hot-copy SQLite без блокировки записи используйте встроенную команду .backup — она атомарна.

Обновление контейнера. Snikket выпускает релизы примерно раз в 2–3 месяца, security-фиксы Prosody подтягиваются в latest-теге автоматически. Процедура: cd /opt/snikket, затем docker compose pull и docker compose up -d. Простой составляет 10–20 секунд, пока стартует новый контейнер. Volume сохраняется, миграции SQLite в Prosody отрабатываются на запуске.

Миграций между мажорными версиями Snikket почти не бывает, но раз в год читайте release notes на github.com/snikket-im/snikket-server/releases — переход на Prosody 0.12, например, потребовал ручного обновления storage_sql-настроек. Восстановление из бэкапа: останавливаем контейнер через docker compose down, разворачиваем архив в volume через временный alpine, запускаем снова.

После восстановления проверьте актуальность сертификатов: если бэкап старше 60 дней, Let’s Encrypt уже выпустил новые при первом успешном запуске, и старые в архиве не годятся. На свежем сервере удалите /snikket/letsencrypt/ перед стартом — Snikket запросит сертификаты заново. Мониторинг: статус контейнера виден через docker exec snikket_server snikket health, а на уровне Prosody — на странице /admin/dashboard.

				
					docker run --rm \
  -v snikket_data:/source:ro \
  -v /backup:/backup \
  alpine tar czf /backup/snikket-$(date +%F).tar.gz -C /source .

docker exec snikket_server sqlite3 /snikket/prosody/data/prosody.sqlite \
  ".backup /snikket/prosody/data/prosody.sqlite.bak"
docker cp snikket_server:/snikket/prosody/data/prosody.sqlite.bak \
  /backup/prosody-$(date +%F).bak
				
			

TCO на 12 месяцев: Snikket vs ejabberd vs Matrix для команды 10–50 человек

Когда мы считаем стоимость владения корпоративным мессенджером для SMB, в смете три позиции: VPS, время администратора и опциональные лицензии enterprise-версий. Цены округлены до 2026 года, провайдер российский (Selectel или Timeweb), VPS с 1 ГБ RAM и 1 vCPU — около 250 ₽/мес.

ПараметрSnikketejabberd CEMatrix/Synapse
RAM на 30 пользователях200–300 МБ250–400 МБ600 МБ–1 ГБ
VPS на 12 мес.3 000 ₽ (1 ГБ)3 000 ₽ (1 ГБ)6 000 ₽ (2 ГБ)
Время на установку15 минут60 минут90 минут
Часов админа в год4–612–2024–40
Push iOSвстроеносвой APNssygnal+APNs
LDAP/ADнетда (конфиг)да (модулем)

Если час администратора-DevOps стоит 3 000 ₽ (типичная ставка аутсорсинга для SMB в РФ на 2026 год), TCO выглядит так. snikket xmpp сервер — 3 000 ₽ за VPS плюс 5 часов × 3 000 ₽, итого около 18 000 ₽ в год. ejabberd CE — 3 000 ₽ плюс 16 часов × 3 000 ₽, итого 51 000 ₽ в год. Разница в 33 000 ₽ — это плата за то, что вы умеете руками править конфиги и вам нужна LDAP-интеграция.

Matrix/Synapse — 6 000 ₽ за VPS 2 ГБ плюс 32 часа × 3 000 ₽, итого 102 000 ₽ в год. Окупается, если нужна федерация с другими серверами, бриджи в Telegram/IRC или больше 100 пользователей. На команде 30 человек переход с Slack Pro (примерно 200 ₽/мес × 30 = 72 000 ₽/год) на snikket xmpp сервер окупается за 4–5 месяцев.

У клиентов IT For Prof типичная экономия при переходе с иностранных подписочных мессенджеров — 50 000–80 000 ₽ в год, плюс исчезают риски блокировки аккаунтов и смены тарифов. Если вы НКО, школа или семья — VPS на 1 ГБ за 250 ₽/мес и 4 часа первичной настройки дают собственный мессенджер на год вперёд.

Итог

Часто задаваемые вопросы

Ответы на часто задаваемые вопросы по теме статьи.

Перейдите в директорию /opt/snikket и выполните последовательно docker compose pull и docker compose up -d. Volume snikket_data сохраняется между перезапусками контейнера, SQLite-миграции Prosody применяются автоматически. Простой составит 10–20 секунд. Перед обновлением сделайте бэкап через sqlite3 .backup — это атомарная копия без блокировки записи. Раз в год читайте release notes на github.com/snikket-im/snikket-server/releases — мажорные версии иногда требуют ручных шагов.

Три типичные причины. Первая — нет SRV-записей, и клиент не может найти порты 5222 и 5269; пропишите вручную хост chat.example.com в настройках клиента. Вторая — фаервол блокирует 5222 или 5223 (DirectTLS); проверьте ufw/iptables на VPS и правила в панели хостинг-провайдера. Третья — сертификат Let’s Encrypt не выпустился, клиент видит self-signed; посмотрите docker compose logs -f snikket на ошибки ACME и резолвинг всех трёх DNS-записей.

Официальный FAQ Snikket указывает, что сервер вмещает 10–15 пользователей в 128 МБ RAM, но для production мы рекомендуем 1 ГБ — это покрывает SQLite-кэш, прокси push-уведомлений и одновременные звонки. Поддерживаемые архитектуры: amd64, ARMv7 и ARMv8, включая Raspberry Pi 2/3/4. Docker нужен версии 20.10.10 или новее. Из портов открывайте 80, 443, 5222, 5269; 5223 для DirectTLS и 3478/5349 для звонков.

Используйте reverse proxy. Перенаправьте Snikket на альтернативные порты через переменные SNIKKET_TWEAK_HTTP_PORT=5080 и SNIKKET_TWEAK_HTTPS_PORT=5443 в snikket.conf. Nginx слушает 80/443, держит сертификаты Let’s Encrypt с тремя SAN-именами (chat., groups.chat., share.chat.) и проксирует HTTP-трафик в контейнер. XMPP-порты 5222, 5223, 5269 идут напрямую в Docker, минуя nginx. Документация: snikket.org/service/help/advanced/reverse_proxy/.

Константин Тютюнник, основатель IT For Prof. 15 лет опыта в IT-аутсорсинге для B2B. Эксперт по DevOps, Linux-инфраструктуре и импортозамещению.

Нужно развернуть корпоративный мессенджер без зависимости от Telegram и WhatsApp? Мы в IT For Prof поможем спроектировать VPS, DNS, бэкапы и подключить команду. Развернём Snikket и обучим вашего администратора за один рабочий день.