Установка и настройка Zulip Chat на Rocky Linux 9
О чём эта статья
Краткое практическое руководство для системного администратора или DevOps-инженера по развёртыванию Zulip (open-source чат-сервер) на Rocky Linux 9. Подойдёт для небольших команд и сред с самоуправляемой инфраструктурой.
Важно: в примерах используется домен zulip.example.com — замените его на реальный домен вашей инсталляции.
Основные варианты запроса (SEO intent)
- Установка Zulip на Rocky Linux 9
- Развёртывание Zulip в Docker на CentOS/Rocky
- Настройка Nginx и LetsEncrypt для Zulip
- Резервное копирование и обновление Zulip
Краткая архитектура (в двух словах)
Zulip собирается из отдельных служб в Docker-контейнерах: PostgreSQL, Redis, Memcached, RabbitMQ и сам Zulip (Django + Tornado + nginx внутри контейнера). Внешний Nginx выступает как обратный прокси и TLS-терминатор.
Важно: в этом руководстве используется docker compose и официальные образы Zulip; это упрощённый и поддерживаемый путь для большинства случаев.
Предварительные требования
- Сервер с Rocky Linux 9.
- Рекомендуемая ОЗУ: минимум 2 ГБ (для <100 пользователей). Для 100+ пользователей — 4 ГБ и 2 CPU или больше.
- Нерутовый пользователь с sudo-привилегиями.
- Домен, указывающий на сервер (в примерах — zulip.example.com).
- Система обновлена:
$ sudo dnf update- Установлены базовые пакеты:
$ sudo dnf install wget curl nano unzip yum-utils policycoreutils-python-utils -yНекоторые пакеты могут быть уже установлены по умолчанию.
Важно: перед началом убедитесь, что на сервере нет других сервисов, прослушивающих порты 80/443, иначе конфигурация nginx и Certbot завершится с ошибкой.
Шаг 1 — Настройка брандмауэра (firewalld)
Rocky Linux использует firewalld. Откройте HTTP и HTTPS порты в зоне public.
Проверка статуса:
$ sudo firewall-cmd --state
runningСписок активных сервисов в зоне public:
$ sudo firewall-cmd --zone=public --list-allОткройте сервисы HTTP и HTTPS:
$ sudo firewall-cmd --zone=public --add-service=http
$ sudo firewall-cmd --zone=public --add-service=httpsСделайте изменения постоянными и перезагрузите правила:
$ sudo firewall-cmd --runtime-to-permanent
$ sudo firewall-cmd --reloadШаг 2 — Установка Docker и Docker Compose
Добавьте официальный репозиторий Docker и установите пакеты:
$ sudo dnf install yum-utils
$ sudo dnf config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
$ sudo dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginВключите и запустите демон Docker:
$ sudo systemctl enable docker --now
$ sudo systemctl status dockerДобавьте своего пользователя в группу docker, чтобы не вводить sudo при запуске команд Docker:
$ sudo usermod -aG docker $(whoami)Затем выйдите и войдите снова в сессию, чтобы изменения вступили в силу.
Шаг 3 — Установка Nginx (мейнлайн)
Rocky Linux 9 может поставляться со старой версией nginx. Чтобы установить актуальную мейнлайн-версию, используйте официальный репозиторий nginx.
Создайте файл /etc/yum.repos.d/nginx.repo и вставьте в него конфигурацию репо (как в оригинале).
Включите ветку mainline и установите nginx:
$ sudo dnf config-manager --enable nginx-mainline
$ sudo dnf install nginx -y
$ nginx -v
$ sudo systemctl enable nginx --now
$ sudo systemctl status nginxШаг 4 — Установка SSL (Certbot через snapd)
Для получения сертификатов Let’s Encrypt в статье используется certbot из snap.
Установите EPEL, snapd и certbot (команды как в оригинале):
$ sudo dnf install epel-release -y
$ sudo dnf install snapd -y
$ sudo systemctl enable snapd --now
$ sudo snap install core && sudo snap refresh core
$ sudo ln -s /var/lib/snapd/snap /snap
$ echo 'export PATH=$PATH:/var/lib/snapd/snap/bin' | sudo tee -a /etc/profile.d/snapd.sh
$ sudo snap install --classic certbot
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
$ certbot --versionСгенерируйте сертификат для домена (замените email и домен):
$ sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m [email protected] -d zulip.example.comСертификаты будут сохранены в /etc/letsencrypt/live/zulip.example.com.
Создайте DH-параметры (рекомендуется для безопасности):
$ sudo openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096Проверьте автоматическое обновление:
$ systemctl list-timers
$ sudo certbot renew --dry-runШаг 5 — Настройка SELinux для работы с сетью и БД
Разрешите Nginx и httpd подключаться к внешним сервисам и БД:
$ sudo setsebool -P httpd_can_network_connect 1
$ sudo setsebool -P httpd_can_network_connect_db 1Шаг 6 — Подготовка и конфигурация Zulip для установки
Создайте секретный ключ (сохраните его в безопасном месте):
$ openssl rand -base64 32
sLIeucGPMCNbR0LwcRhyXafXmputmtse6+EYU04+9JY=Создайте директорию и файл окружения:
$ mkdir ~/docker-zulip
$ cd ~/docker-zulip
$ nano .envВставьте содержимое .env (см. исходник) и замените метки REPLACEWITH_SECURE и EMAIL_ на реальные значения.
Пояснения к ключевым переменным изложены ниже (переведено и расширено):
- ZULIP_ADMINISTRATOR — email администратора, создаваемого при установке.
- EXTERNAL_HOST — внешний домен вашей инстанции.
- ZULIP_AUTH_BACKENDS — метод аутентификации (EmailAuthBackend, Github, Google и т.д.).
- DISABLE_HTTPS — выставлено в true, если TLS обслуживается внешним nginx.
- SSL_CERTIFICATE_GENERATION — self-signed при отключённом HTTPS внутри контейнера.
- EMAIL_* — параметры SMTP для отправки уведомлений (пример: Amazon SES).
- SECRET_KEY — секретное значение Django/Zulip для шифрования.
- POSTGRES_*, REDIS_PASSWORD, MEMCACHED_PASSWORD, RABBITMQ_DEFAULT_PASS — обязательно задайте сильные пароли.
Важно: НЕ храните .env в публичном репозитории.
Шаг 7 — Docker Compose: файл и сервисы
Создайте docker-compose.yml в ~/docker-zulip и вставьте конфигурацию сервисов (database, memcached, rabbitmq, redis, zulip) как в источнике. Важно сохранить определения volumes и networks.
Пояснения к ключевым сервисам и переменным:
- database — образ zulip/zulip-postgresql:14. Обратите внимание: образ поддерживает PostgreSQL 14 (даже если Zulip совместим с более новыми версиями БД).
- memcached — запускается в режиме SASL для аутентификации.
- rabbitmq — хранит очередь задач.
- redis — хранит кэш и состояние.
- zulip — основной образ zulip/docker-zulip:<версия>. В контейнер включены Django и Tornado; внутри также nginx на порту 80, который проброшен наружу на порт 8080 хоста.
Настройте статические IP внутри bridge-сети docker (в примере 10.5.0.x). Это упрощает конфигурацию в переменных среды.
После сохранения файла запустите контейнеры:
$ docker compose up -dПроверка статуса контейнеров:
$ docker ps
$ docker compose ps
$ docker logs zulip --followОжидайте, что запуск контейнера может занять несколько минут — внутри выполняются миграции и сборка.
Шаг 8 — Настройка внешнего Nginx как обратного прокси
Отредактируйте /etc/nginx/nginx.conf: добавьте перед include /etc/nginx/conf.d/*.conf; строку:
server_names_hash_bucket_size 64;Создайте /etc/nginx/conf.d/zulip.conf с содержимым (как в источнике), где nginx слушает 80 -> редирект на https и 443 -> proxy_pass на http://127.0.0.1:8080.
Проверка и перезапуск:
$ sudo nginx -t
$ sudo systemctl restart nginxШаг 9 — Доступ к интерфейсу Zulip и создание организации
Откройте в браузере: https://zulip.example.com/
Если интерфейс не позволяет создать организацию (так бывает при initial setup), сгенерируйте защищённую одноразовую ссылку из контейнера:
$ docker compose exec -u zulip zulip /home/zulip/deployments/current/manage.py generate_realm_creation_linkОткройте сгенерированный URL и создайте организацию, затем учетную запись администратора.





Шаг 10 — Команды управления Zulip Server
Доступ в контейнер под пользователем zulip:
$ docker compose exec -u zulip zulip bashИли однократный запуск manage.py:
$ docker compose exec -u zulip zulip \
/home/zulip/deployments/current/manage.py help Для удобства можно создать скрипт управления zulip_manage.sh (как в источнике):
#!/bin/sh
docker compose exec -u zulip zulip /home/zulip/deployments/current/manage.py "$@"Доступные подкоманды manage.py — полный список содержится в исходнике (create_user, create_realm, send_test_email и т.д.).
Остановка/запуск сервера внутри контейнера:
$ docker exec -u zulip zulip /home/zulip/deployments/current/scripts/stop-server
$ docker exec -u zulip zulip /home/zulip/deployments/current/scripts/start-server
$ docker exec -u zulip zulip /home/zulip/deployments/current/scripts/restart-serverШаг 11 — Тестирование отправки почты
Пример команды тестовой отправки:
$ ~/docker-zulip/zulip_manage.sh send_test_email [email protected]Если письма не отправляются, проверьте лог ошибок, настройки SMTP в .env и документацию Zulip: https://zulip.readthedocs.io/en/latest/production/email.html#troubleshooting
Шаг 12 — Обновление Zulip
Процесс обновления:
- Остановите контейнеры:
$ cd ~/docker-zulip
$ docker compose stop- Отредактируйте docker-compose.yml, изменив тег образа zulip/docker-zulip:8.2-0 на нужный.
- Запустите контейнеры:
$ docker compose up -d- Удалите старые контейнеры:
$ docker compose rmВсегда проверяйте совместимость миграций и ченджлог Zulip перед апгрейдом.
Резервное копирование и восстановление (Runbook)
Минимальное резервирование:
- Файлы данных в volumes: postgresql-14, redis, rabbitmq, zulip.
- Регулярно экспортируйте дамп PostgreSQL (pg_dump), бэкапьте /data Zulip.
- План восстановления должен включать последовательность:
- Остановка контейнеров.
- Восстановление данных PostgreSQL.
- Восстановление файлов Zulip /data.
- Запуск контейнеров и проверку логов.
Пример: локальный дамп PostgreSQL
$ docker exec -t zulip-db pg_dump -U zulip zulip > zulip-db-backup.sqlВосстановление:
$ docker exec -i zulip-db psql -U zulip zulip < zulip-db-backup.sqlВажно: тестируйте процедуру восстановления на отдельной тестовой машине.
Безопасность и жесткая защита (Security hardening)
Рекомендации уровня “production”:
- Используйте актуальные образы и обновляйте их в рамках CVE-патчей.
- Размещайте контейнеры в приватной сети, а внешний nginx — единственная точка входа.
- TLS: используйте Let’s Encrypt или корпоративный CA, отключите слабые протоколы (в nginx конфигурации разрешены TLSv1.2 и TLSv1.3).
- Оградите административные интерфейсы (SSH) через брандмауэр и VPN.
- Храните секреты в безопасном хранилище (vault, secret manager) вместо .env в репозитории.
- Ограничьте права на файлы и директории, используемые контейнерами.
- Отключите ненужные сервисы внутри контейнера; примените ulimits (как в compose-файле).
- Логи: агрегируйте в централизованный стек (ELK/Graylog/Promtail+Loki).
SELinux: оставьте включённым и применяйте только нужные bool-флаги, как показано ранее.
Политика приватности и соответствие (Privacy / GDPR notes)
- Знайте, какие данные проходят через сервер — сообщения, вложения, метаданные пользователей.
- Для соответствия GDPR: документируйте сроки хранения данных, процедуры выгрузки данных по запросу, удаление учётных записей и логов.
- Шифрование at-rest: если требуется, храните бэкапы в зашифрованном виде и используйте зашифрованные тома для volumes.
- Транспортное шифрование: обязателен (HTTPS с современными протоколами).
- Минимизируйте сбор логов и обезличивайте данные, где возможно.
Механика отказа: когда этот метод не подходит
Контейнерный подход с Docker-пакетом Zulip удобен для большинства случаев, но может не подойти если:
- Вам требуется кластерная, высокодоступная архитектура с несколькими мастерами и автоматическим failover для PostgreSQL.
- Есть строгие корпоративные требования по сертификации и поддержке, где предпочтительнее коммерческий SaaS Zulip или управляемый продукт.
- Необходима глубокая кастомизация исходников Zulip (тогда лучше собрать образ с вашего CI/CD и тестировать).
Альтернативные подходы
- Пакетная (source) установка на виртуальной машине (без Docker) — для полного контроля над окружением.
- Kubernetes (Helm chart) — для более масштабируемых и отказоустойчивых сред.
- Управляемые сервисы Zulip Cloud — если не хотите управлять инфраструктурой.
Чек-листы по ролям
Администратор / DevOps — перед продом:
- Проверил совместимость версии Zulip и Docker образа.
- Настроил резервное копирование PostgreSQL и volumes.
- Настроил мониторинг и оповещения (CPU, память, дисковое пространство, контейнеры stopped).
- Проверил автоматическое обновление сертификатов certbot.
- Выключил неиспользуемые порты и ограничил SSH доступ.
Служба поддержки / Менеджер сообщества:
- Настроил шаблоны приветственных писем и проверил отправку почты.
- Произвёл тестовую регистрацию и проверил регистрацию новых учётных записей.
Разработчик интеграций / SRE:
- Настроил и протестировал интеграции (GitHub, Jira, Webhooks).
- Протестировал webhooks и outgoing webhooks reliability.
Тест-кейсы и критерии приёмки
Критерии приёмки для базового развертывания:
- Сайт https://EXTERNAL_HOST открывается по HTTPS без ошибок сертификата.
- Можно создать организацию через сгенерированную ссылку и зарегистрировать администратора.
- Отправка тестовой почты проходит успешно (провести тесты с двумя разными получателями).
- Все контейнеры (database, redis, rabbitmq, memcached, zulip) находятся в статусе Up.
- Процесс обновления (замена тега образа) выполняется без потери данных при корректном восстановлении из бэкапов.
Тест-кейсы (минимум):
- Проверить доступность веб-интерфейса на 3 клиентах (десктоп, мобильный, curl).
- Отправить и получить сообщение между двумя пользователями.
- Загрузить файл (drag-and-drop) и убедиться, что он доступен для других.
- Провести имитацию сбоя: выключить контейнер zulip, восстановить и проверить сервис.
Сценарий отката при неудачном обновлении
- Остановить новые контейнеры
- Восстановить бэкап PostgreSQL из точки перед обновлением
- Вернуть тег образа в docker-compose.yml на прежнюю версию
- Запустить docker compose up -d
- Проверить логи и состояние сервиса
Проверяйте откат на тестовой среде перед продом.
Набор полезных команд (cheat sheet)
- Просмотр логов Zulip:
$ docker logs zulip --follow- Вход в shell контейнера под пользователем zulip:
$ docker compose exec -u zulip zulip bash- Остановка/запуск через scripts внутри контейнера:
$ docker exec -u zulip zulip /home/zulip/deployments/current/scripts/stop-server
$ docker exec -u zulip zulip /home/zulip/deployments/current/scripts/start-server- Генерация ссылки для создания организации:
$ docker compose exec -u zulip zulip /home/zulip/deployments/current/manage.py generate_realm_creation_link- Тест отправки почты:
$ ~/docker-zulip/zulip_manage.sh send_test_email [email protected]- Бэкап базы данных:
$ docker exec -t zulip-db pg_dump -U zulip zulip > zulip-db-backup.sqlСоветы по производительности и масштабированию
- Для небольших команд (до ~100 активных пользователей) достаточно 2 ГБ ОЗУ, но у вас должны быть резервы по диску и swap.
- Для более активных инсталляций увеличьте память и CPU, подумайте о выделенном хосте для PostgreSQL или использовании managed PostgreSQL с репликацией.
- Для высокой нагрузки рассмотрите отдельный кластер Redis и кластер PostgreSQL с репликацией и failover.
Совместимость и миграция: краткие рекомендации
- Перед миграцией из других чатов (Slack, Rocket.Chat) используйте инструменты импорта Zulip: в manage.py есть команды convert_slack_data, convert_mattermost_data и т.д.
- Тестируйте импорт в отдельной среде и проводите проверки целостности сообщений и аттачей.
Gallery ошибок и решения (Edge cases)
- Ошибка: certbot не может получить http-01 challenge — проверьте, не блокируются ли порты 80/443 и корректно ли прописаны A/AAAA записи DNS.
- Ошибка: контейнеры стартуют, но веб-интерфейс возвращает 502 — проверьте, слушает ли внутренняя nginx внутри контейнера порт 80 и проброшен ли порт 8080 на хост.
- Ошибка: невозможность подключиться к Redis/PG — проверьте переменные окружения и пароли в .env; убедитесь, что контейнерам назначены уникальные IP внутри сети.
Мини-методология развёртывания (playbook)
- Подготовка сервера: обновления, установка Docker, настройка брандмауэра.
- Установка Nginx и Certbot, получение сертификата.
- Создание .env и docker-compose.yml (в тестовой ветке репозитория).
- Запуск в staging, проверка функциональности, тест бэкапов.
- Перенос в production: DNS, SSL, мониторинг, план отката.
- Регулярные проверки: обновления образов, тесты восстановления.
Пример решения — когда всё идёт не так
Если при запуске контейнера zulip вы получаете постоянные ошибки миграций или упёрлись в несовместимость версий:
- Откатитесь к предыдущему образу (версия, которую вы тестировали ранее).
- Запустите контейнер с тем же набором данных и сравните логи.
- Если необходимо применить миграции вручную, используйте manage.py migrate внутри контейнера (предварительно создайте бэкап).
Краткий глоссарий (1 строка на термин)
- Zulip — open-source система групповых чатов с потоковыми (threaded) разговорами.
- Docker compose — инструмент для описания и запуска многоконтейнерных Docker-приложений.
- Certbot — клиент Let’s Encrypt для получения TLS-сертификатов.
- SELinux — подсистема безопасности ядра Linux, контролирующая доступы по политикам.
FAQ (коротко)
Q: Можно ли запускать Zulip без Docker? — Да, можно собрать Zulip из исходников, но это требует больше ручной настройки и управления зависимостями.
Q: Нужен ли внешний nginx? — Да, для production рекомендуется внешний nginx как TLS-терминатор и балансировщик.
Q: Как часто обновлять образы? — Обновляйте по мере выхода критических исправлений безопасности и перед major-upgrade тестируйте в staging.
Заключение
Это подробное пошаговое руководство по установке и управлению Zulip Chat на Rocky Linux 9 с использованием Docker Compose и внешнего Nginx. Включены рекомендации по безопасности, бэкапам, обновлениям и процедурам отката. Для развёртывания в production следуйте чек-листам, тестируйте процедуры восстановления и обновления в изолированной среде.
Если нужны примеры CI/CD для автоматизации обновлений контейнеров или Helm-чарты для Kubernetes — можно подготовить отдельное руководство.
Контакты и дополнительные материалы
Официальная документация Zulip: https://zulip.readthedocs.io
Похожие материалы
Несколько аккаунтов Skype: Multi Skype Launcher
Журнал для работы: повысить продуктивность
Персональные звуки уведомлений на Android
Скачивание шоу Hulu для офлайн‑просмотра
Microsoft Start: персонализированная новостная лента