Zulip + PostgreSQL + RabbitMQ + Redis
Threaded group chat with topic organization.
Overview
Zulip is an open-source team chat application that revolutionizes group communication through its unique topic-based threading system. Originally developed by a team of MIT graduates and later acquired by Dropbox before becoming open-source, Zulip combines the real-time nature of chat with the organized structure of email threads. Unlike traditional chat platforms where conversations flow chronologically, Zulip organizes messages into streams and topics, making it easy to follow multiple conversations simultaneously and catch up on missed discussions without losing context.
This deployment stack leverages PostgreSQL as Zulip's primary database for storing messages, user data, and organizational information, while RabbitMQ handles the message queuing system for real-time message delivery and background task processing. Redis provides session management and caching capabilities, significantly improving response times for frequently accessed data, while Memcached offers an additional caching layer for database query optimization. Together, these components create a robust messaging infrastructure capable of handling enterprise-scale communication loads.
This configuration is ideal for development teams, open-source projects, academic institutions, and organizations that value organized communication over chaotic chat streams. The combination provides enterprise-grade reliability with self-hosted control, making it perfect for teams requiring data sovereignty, custom integrations, or advanced administrative controls that aren't available in hosted chat solutions.
Key Features
- Topic-based message threading that allows multiple conversations per stream without message interleaving
- PostgreSQL backend providing ACID compliance for message integrity and complex user permission queries
- RabbitMQ message queuing enabling real-time message delivery, push notifications, and background email processing
- Redis-powered session management and real-time presence indicators for online/offline status
- Memcached query result caching reducing PostgreSQL load for frequently accessed streams and user data
- Built-in LaTeX and syntax highlighting support for mathematical formulas and code discussions
- Advanced search capabilities leveraging PostgreSQL full-text search across messages, files, and user content
- Multi-protocol authentication support including LDAP, SAML, and social login integration
Common Use Cases
- 1Software development teams needing organized code review discussions and bug tracking conversations
- 2Academic research groups managing multiple concurrent project discussions with topic separation
- 3Open-source projects requiring public archives with searchable message history and contributor onboarding
- 4Remote-first organizations needing asynchronous communication that doesn't lose context across time zones
- 5Compliance-focused companies requiring self-hosted chat with full message retention and audit capabilities
- 6Educational institutions managing course discussions with topic-based assignment and lecture threads
- 7Technical support teams organizing customer issues by product area with persistent conversation history
Prerequisites
- Minimum 4GB RAM available (2GB for PostgreSQL and Zulip, 1GB for RabbitMQ, 512MB for Redis/Memcached)
- Docker and Docker Compose v2.0+ installed with BuildKit support enabled
- Available ports 80, 443, and 5432 for web interface and database connections
- Valid email SMTP credentials for user registration and notification delivery
- SSL certificate or domain name for production deployment (self-signed certificates included for development)
- Basic understanding of message queuing concepts and PostgreSQL database administration
For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms
docker-compose.yml
docker-compose.yml
1services: 2 zulip: 3 image: zulip/docker-zulip:latest4 environment: 5 - DB_HOST=postgres6 - DB_HOST_PORT=54327 - DB_USER=zulip8 - SETTING_MEMCACHED_LOCATION=memcached:112119 - SETTING_RABBITMQ_HOST=rabbitmq10 - SETTING_REDIS_HOST=redis11 - SECRETS_email_password=${EMAIL_PASSWORD}12 - SECRETS_rabbitmq_password=${RABBITMQ_PASSWORD}13 - SECRETS_postgres_password=${POSTGRES_PASSWORD}14 - SECRETS_secret_key=${SECRET_KEY}15 - SETTING_EXTERNAL_HOST=localhost16 - SETTING_ZULIP_ADMINISTRATOR=admin@example.com17 - SSL_CERTIFICATE_GENERATION=self-signed18 volumes: 19 - zulip-data:/data20 ports: 21 - "80:80"22 - "443:443"23 depends_on: 24 - postgres25 - rabbitmq26 - redis27 - memcached28 networks: 29 - zulip-network30 restart: unless-stopped3132 postgres: 33 image: zulip/zulip-postgresql:1434 environment: 35 - POSTGRES_USER=zulip36 - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}37 - POSTGRES_DB=zulip38 volumes: 39 - postgres-data:/var/lib/postgresql/data40 networks: 41 - zulip-network42 restart: unless-stopped4344 rabbitmq: 45 image: rabbitmq:3-management46 environment: 47 - RABBITMQ_DEFAULT_USER=zulip48 - RABBITMQ_DEFAULT_PASS=${RABBITMQ_PASSWORD}49 volumes: 50 - rabbitmq-data:/var/lib/rabbitmq51 networks: 52 - zulip-network53 restart: unless-stopped5455 redis: 56 image: redis:alpine57 volumes: 58 - redis-data:/data59 networks: 60 - zulip-network61 restart: unless-stopped6263 memcached: 64 image: memcached:alpine65 networks: 66 - zulip-network67 restart: unless-stopped6869volumes: 70 zulip-data: 71 postgres-data: 72 rabbitmq-data: 73 redis-data: 7475networks: 76 zulip-network: 77 driver: bridge.env Template
.env
1# Zulip2POSTGRES_PASSWORD=secure_postgres_password3RABBITMQ_PASSWORD=secure_rabbitmq_password4SECRET_KEY=your-very-long-secret-key-min-50-chars5EMAIL_PASSWORD=optional_email_passwordUsage Notes
- 1Zulip at https://localhost
- 2Generate realm: manage.py generate_realm_creation_link
- 3Topic-based threading
- 4Mobile apps available
- 5LDAP/SAML auth supported
Individual Services(5 services)
Copy individual services to mix and match with your existing compose files.
zulip
zulip:
image: zulip/docker-zulip:latest
environment:
- DB_HOST=postgres
- DB_HOST_PORT=5432
- DB_USER=zulip
- SETTING_MEMCACHED_LOCATION=memcached:11211
- SETTING_RABBITMQ_HOST=rabbitmq
- SETTING_REDIS_HOST=redis
- SECRETS_email_password=${EMAIL_PASSWORD}
- SECRETS_rabbitmq_password=${RABBITMQ_PASSWORD}
- SECRETS_postgres_password=${POSTGRES_PASSWORD}
- SECRETS_secret_key=${SECRET_KEY}
- SETTING_EXTERNAL_HOST=localhost
- SETTING_ZULIP_ADMINISTRATOR=admin@example.com
- SSL_CERTIFICATE_GENERATION=self-signed
volumes:
- zulip-data:/data
ports:
- "80:80"
- "443:443"
depends_on:
- postgres
- rabbitmq
- redis
- memcached
networks:
- zulip-network
restart: unless-stopped
postgres
postgres:
image: zulip/zulip-postgresql:14
environment:
- POSTGRES_USER=zulip
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=zulip
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- zulip-network
restart: unless-stopped
rabbitmq
rabbitmq:
image: rabbitmq:3-management
environment:
- RABBITMQ_DEFAULT_USER=zulip
- RABBITMQ_DEFAULT_PASS=${RABBITMQ_PASSWORD}
volumes:
- rabbitmq-data:/var/lib/rabbitmq
networks:
- zulip-network
restart: unless-stopped
redis
redis:
image: redis:alpine
volumes:
- redis-data:/data
networks:
- zulip-network
restart: unless-stopped
memcached
memcached:
image: memcached:alpine
networks:
- zulip-network
restart: unless-stopped
Quick Start
terminal
1# 1. Create the compose file2cat > docker-compose.yml << 'EOF'3services:4 zulip:5 image: zulip/docker-zulip:latest6 environment:7 - DB_HOST=postgres8 - DB_HOST_PORT=54329 - DB_USER=zulip10 - SETTING_MEMCACHED_LOCATION=memcached:1121111 - SETTING_RABBITMQ_HOST=rabbitmq12 - SETTING_REDIS_HOST=redis13 - SECRETS_email_password=${EMAIL_PASSWORD}14 - SECRETS_rabbitmq_password=${RABBITMQ_PASSWORD}15 - SECRETS_postgres_password=${POSTGRES_PASSWORD}16 - SECRETS_secret_key=${SECRET_KEY}17 - SETTING_EXTERNAL_HOST=localhost18 - SETTING_ZULIP_ADMINISTRATOR=admin@example.com19 - SSL_CERTIFICATE_GENERATION=self-signed20 volumes:21 - zulip-data:/data22 ports:23 - "80:80"24 - "443:443"25 depends_on:26 - postgres27 - rabbitmq28 - redis29 - memcached30 networks:31 - zulip-network32 restart: unless-stopped3334 postgres:35 image: zulip/zulip-postgresql:1436 environment:37 - POSTGRES_USER=zulip38 - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}39 - POSTGRES_DB=zulip40 volumes:41 - postgres-data:/var/lib/postgresql/data42 networks:43 - zulip-network44 restart: unless-stopped4546 rabbitmq:47 image: rabbitmq:3-management48 environment:49 - RABBITMQ_DEFAULT_USER=zulip50 - RABBITMQ_DEFAULT_PASS=${RABBITMQ_PASSWORD}51 volumes:52 - rabbitmq-data:/var/lib/rabbitmq53 networks:54 - zulip-network55 restart: unless-stopped5657 redis:58 image: redis:alpine59 volumes:60 - redis-data:/data61 networks:62 - zulip-network63 restart: unless-stopped6465 memcached:66 image: memcached:alpine67 networks:68 - zulip-network69 restart: unless-stopped7071volumes:72 zulip-data:73 postgres-data:74 rabbitmq-data:75 redis-data:7677networks:78 zulip-network:79 driver: bridge80EOF8182# 2. Create the .env file83cat > .env << 'EOF'84# Zulip85POSTGRES_PASSWORD=secure_postgres_password86RABBITMQ_PASSWORD=secure_rabbitmq_password87SECRET_KEY=your-very-long-secret-key-min-50-chars88EMAIL_PASSWORD=optional_email_password89EOF9091# 3. Start the services92docker compose up -d9394# 4. View logs95docker compose logs -fOne-Liner
Run this command to download and set up the recipe in one step:
terminal
1curl -fsSL https://docker.recipes/api/recipes/zulip-complete/run | bashTroubleshooting
- Zulip fails to start with database connection errors: Ensure PostgreSQL container is fully initialized before Zulip starts by checking postgres logs for 'database system is ready to accept connections'
- Messages not delivering in real-time: Verify RabbitMQ management interface at rabbitmq:15672 shows active queues and check RABBITMQ_PASSWORD matches between services
- Slow page load times and timeouts: Monitor Redis and Memcached connections using redis-cli ping and telnet memcached:11211 to verify caching layers are responsive
- User registration emails not sending: Validate SMTP settings in EMAIL_PASSWORD environment variable and check Zulip logs for email backend connection errors
- High memory usage and container restarts: Adjust PostgreSQL shared_buffers and work_mem settings, and monitor RabbitMQ queue depths for message backlog buildup
- SSL certificate warnings in browser: Replace self-signed certificates with proper domain certificates or configure SETTING_EXTERNAL_HOST to match your actual domain name
Community Notes
Loading...
Loading notes...
Download Recipe Kit
Get all files in a ready-to-deploy package
Includes docker-compose.yml, .env template, README, and license
Components
zulippostgresqlrabbitmqredismemcached
Tags
#zulip#chat#threading#topics#team-communication
Category
Message Queues & BrokersAd Space
Shortcuts: C CopyF FavoriteD Download