8.2.18 Deployment of the corporate chat server Zulip

The Host Banner Zulip Installation

Zulip is a modern open-source team communication system that combines real-time messaging with asynchronous threaded conversations. Deploying it with Docker enables fast and reproducible installation, eliminating the need to configure dependencies manually (PostgreSQL, RabbitMQ, Redis, memcached, etc.).

Server Preparation

Requirements

Variables to Replace

  • DOMAIN_NAME — your domain name (e.g., chat.example.com);
  • ADMIN_EMAIL — Zulip administrator’s email address;
  • POSTGRES_PASSWORD, RABBITMQ_PASSWORD, REDIS_PASSWORD, MEMCACHED_PASSWORD — service passwords;
  • SECRET_KEY — a 50-character random string (Django SECRET_KEY);

Security Configuration

Restrict access to non-public ports and allow only the required services.

UFW:

sudo ufw allow OpenSSH
sudo ufw allow 80,443/tcp
sudo ufw enable

iptables:

sudo iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -P INPUT DROP

Installation

First, create a directory for the project:

mkdir ~/zulip && cd ~/zulip

Then clone the docker-zulip repository:

git clone https://github.com/zulip/docker-zulip.git
cd docker-zulip

gitclone

The repository includes a sample docker-compose.yml file that defines five containers: Zulip, PostgreSQL, Redis, RabbitMQ, and memcached.

Tip: to generate secure random keys, use:

openssl rand -base64 40 | tr -d '/+=' | head -c 50

Now edit docker-compose.yml. Locate the environment section under the zulip service and insert your values:

services:
  zulip:
    image: zulip/docker-zulip:10.4-0  # latest tag
    environment:
      - SETTING_EXTERNAL_HOST=DOMAIN_NAME
      - SETTING_ZULIP_ADMINISTRATOR=ADMIN_EMAIL
      - POSTGRES_PASSWORD=POSTGRES_PASSWORD
      - SECRETS_postgres_password=POSTGRES_PASSWORD
      - RABBITMQ_DEFAULT_PASS=RABBITMQ_PASSWORD
      - SECRETS_rabbitmq_password=RABBITMQ_PASSWORD
      - REDIS_PASSWORD=REDIS_PASSWORD
      - SECRETS_redis_password=REDIS_PASSWORD
      - SECRETS_secret_key=SECRET_KEY
      - SSL_CERTIFICATE_GENERATION=certbot

Warning: after the first launch, service passwords can only be changed manually inside containers or by recreating data volumes.

Pull Images and Launch Zulip

Run the following commands to pull the latest images and start all five containers in the background:

sudo docker compose pull
sudo docker compose up -d

dockercomposeup-d

Creating an Organization

Generate an organization creation link with the following command:

sudo docker compose exec -u zulip zulip \
  "/home/zulip/deployments/current/manage.py generate_realm_creation_link"

dockercomposeexec

Open the generated link in your browser and create an admin account:

webinterfacecreateorg

Verifying Functionality

  1. Check that all containers are marked as “healthy”:
docker compose ps

dockercomposeps

  1. Open https://<DOMAIN_NAME>/ and log in with the admin account you created.

webinterfacewelcome 3. In the admin menu, go to Administration → Server logs and verify there are no errors.

Common Issues
Error Cause Solution
port 5432 is already allocated Local PostgreSQL service is running Stop the postgresql service or change the port in docker-compose.yml.
502 Bad Gateway / self‑signed cert Let’s Encrypt certificate has not yet been issued Wait for Certbot to finish or temporarily use HTTP.
django.core.exceptions.ImproperlyConfigured: SECRET_KEY The SECRETS_secret_key variable is missing Generate a new key, add it to docker-compose.yml, and restart the container.
Not enough RAM, “worker not running” queue warning Server lacks memory for multiprocess workers Set QUEUE_WORKERS_MULTIPROCESS=false or upgrade RAM.