Mattermost Team Chat
Enterprise messaging platform with PostgreSQL, Elasticsearch search, and file storage.
Overview
Mattermost is an open-source, self-hosted team collaboration platform designed as an enterprise alternative to Slack and Microsoft Teams. Originally created by SpinPunch in 2016, Mattermost has evolved into a comprehensive messaging solution that prioritizes data sovereignty, security, and integration capabilities. The platform supports unlimited message history, file sharing, voice calls, and extensive plugin ecosystem while maintaining complete control over your data and infrastructure.
This enterprise-grade deployment combines Mattermost with PostgreSQL for robust message and metadata storage, Elasticsearch for advanced search capabilities across channels and files, MinIO as S3-compatible object storage for file attachments and media, and NGINX as a high-performance reverse proxy. PostgreSQL ensures ACID compliance for critical chat data while supporting Mattermost's complex relational queries. Elasticsearch enables instant search across thousands of messages and channels with relevance scoring. MinIO provides scalable file storage that's compatible with AWS S3 APIs but remains under your control.
This stack is ideal for organizations requiring enterprise-grade team communication with complete data control, compliance teams needing audit trails and data retention policies, development teams wanting extensive integrations and custom bots, and companies migrating from proprietary solutions like Slack while maintaining advanced features. The combination delivers production-ready performance with the flexibility to customize authentication, integrate with existing LDAP/SAML systems, and scale across multiple teams and departments.
Key Features
- PostgreSQL backend with ACID compliance for reliable message storage and complex user permission queries
- Elasticsearch integration for full-text search across messages, files, and user profiles with relevance ranking
- MinIO S3-compatible object storage for unlimited file attachments, image previews, and media sharing
- NGINX reverse proxy with SSL termination, request buffering, and WebSocket support for real-time messaging
- Bleve search indexing as fallback when Elasticsearch is unavailable, stored in persistent Docker volumes
- Multi-database support through PostgreSQL's JSON capabilities for plugin data and custom integrations
- High-availability file storage with MinIO's erasure coding and bucket lifecycle management
- Advanced PostgreSQL full-text search capabilities as backup to Elasticsearch cluster
Common Use Cases
- 1Enterprise team communication replacing Slack or Microsoft Teams with on-premises data control
- 2Software development teams needing GitLab, Jira, and CI/CD pipeline integrations with custom webhooks
- 3Healthcare and financial organizations requiring HIPAA/SOX compliance with audit logging and data retention
- 4Remote-first companies needing persistent chat history, file sharing, and voice/video calling infrastructure
- 5Government agencies requiring air-gapped communication systems with classified data handling
- 6Educational institutions managing student and faculty communication across multiple departments
- 7Managed service providers offering white-labeled team collaboration platforms to clients
Prerequisites
- Minimum 6GB RAM (PostgreSQL 1GB + Elasticsearch 2GB + MinIO 1GB + Mattermost 1GB + system overhead)
- Docker Engine 20.10+ and Docker Compose v2 for health check dependencies and network isolation
- Ports 80, 443, 8065, 9000, and 9001 available for NGINX, Mattermost, and MinIO console access
- Valid SSL certificates for production deployment with HTTPS termination at NGINX
- Basic understanding of Mattermost System Console for Elasticsearch configuration and user management
- PostgreSQL administration knowledge for backup strategies and performance tuning
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 mattermost: 3 image: mattermost/mattermost-team-edition:latest4 ports: 5 - "8065:8065"6 environment: 7 MM_SQLSETTINGS_DRIVERNAME: postgres8 MM_SQLSETTINGS_DATASOURCE: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?sslmode=disable9 MM_BLEVESETTINGS_INDEXDIR: /mattermost/bleve-indexes10 MM_FILESETTINGS_DRIVERNAME: amazons311 MM_FILESETTINGS_AMAZONS3ACCESSKEYID: ${MINIO_ACCESS_KEY}12 MM_FILESETTINGS_AMAZONS3SECRETACCESSKEY: ${MINIO_SECRET_KEY}13 MM_FILESETTINGS_AMAZONS3BUCKET: mattermost14 MM_FILESETTINGS_AMAZONS3ENDPOINT: minio:900015 MM_FILESETTINGS_AMAZONS3SSL: "false"16 volumes: 17 - mattermost_data:/mattermost/data18 - mattermost_logs:/mattermost/logs19 - mattermost_config:/mattermost/config20 - mattermost_plugins:/mattermost/plugins21 - mattermost_bleve:/mattermost/bleve-indexes22 depends_on: 23 postgres: 24 condition: service_healthy25 minio: 26 condition: service_started27 networks: 28 - mm-net29 restart: unless-stopped3031 postgres: 32 image: postgres:16-alpine33 environment: 34 POSTGRES_USER: ${POSTGRES_USER}35 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}36 POSTGRES_DB: ${POSTGRES_DB}37 volumes: 38 - postgres_data:/var/lib/postgresql/data39 healthcheck: 40 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]41 interval: 10s42 timeout: 5s43 retries: 544 networks: 45 - mm-net46 restart: unless-stopped4748 elasticsearch: 49 image: elasticsearch:8.11.050 environment: 51 - discovery.type=single-node52 - xpack.security.enabled=false53 - ES_JAVA_OPTS=-Xms512m -Xmx512m54 volumes: 55 - es_data:/usr/share/elasticsearch/data56 networks: 57 - mm-net58 restart: unless-stopped5960 minio: 61 image: minio/minio:latest62 ports: 63 - "9000:9000"64 - "9001:9001"65 environment: 66 MINIO_ROOT_USER: ${MINIO_ACCESS_KEY}67 MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY}68 volumes: 69 - minio_data:/data70 command: server /data --console-address ":9001"71 networks: 72 - mm-net73 restart: unless-stopped7475 nginx: 76 image: nginx:alpine77 ports: 78 - "80:80"79 - "443:443"80 volumes: 81 - ./nginx.conf:/etc/nginx/nginx.conf:ro82 - ./certs:/etc/nginx/certs:ro83 depends_on: 84 - mattermost85 networks: 86 - mm-net87 restart: unless-stopped8889volumes: 90 mattermost_data: 91 mattermost_logs: 92 mattermost_config: 93 mattermost_plugins: 94 mattermost_bleve: 95 postgres_data: 96 es_data: 97 minio_data: 9899networks: 100 mm-net: 101 driver: bridge.env Template
.env
1# PostgreSQL2POSTGRES_USER=mattermost3POSTGRES_PASSWORD=secure_postgres_password4POSTGRES_DB=mattermost56# MinIO7MINIO_ACCESS_KEY=minioadmin8MINIO_SECRET_KEY=secure_minio_passwordUsage Notes
- 1Mattermost at http://localhost:8065
- 2Create MinIO bucket 'mattermost' first
- 3MinIO Console at http://localhost:9001
- 4Enable Elasticsearch in System Console
Individual Services(5 services)
Copy individual services to mix and match with your existing compose files.
mattermost
mattermost:
image: mattermost/mattermost-team-edition:latest
ports:
- "8065:8065"
environment:
MM_SQLSETTINGS_DRIVERNAME: postgres
MM_SQLSETTINGS_DATASOURCE: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?sslmode=disable
MM_BLEVESETTINGS_INDEXDIR: /mattermost/bleve-indexes
MM_FILESETTINGS_DRIVERNAME: amazons3
MM_FILESETTINGS_AMAZONS3ACCESSKEYID: ${MINIO_ACCESS_KEY}
MM_FILESETTINGS_AMAZONS3SECRETACCESSKEY: ${MINIO_SECRET_KEY}
MM_FILESETTINGS_AMAZONS3BUCKET: mattermost
MM_FILESETTINGS_AMAZONS3ENDPOINT: minio:9000
MM_FILESETTINGS_AMAZONS3SSL: "false"
volumes:
- mattermost_data:/mattermost/data
- mattermost_logs:/mattermost/logs
- mattermost_config:/mattermost/config
- mattermost_plugins:/mattermost/plugins
- mattermost_bleve:/mattermost/bleve-indexes
depends_on:
postgres:
condition: service_healthy
minio:
condition: service_started
networks:
- mm-net
restart: unless-stopped
postgres
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test:
- CMD-SHELL
- pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}
interval: 10s
timeout: 5s
retries: 5
networks:
- mm-net
restart: unless-stopped
elasticsearch
elasticsearch:
image: elasticsearch:8.11.0
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- ES_JAVA_OPTS=-Xms512m -Xmx512m
volumes:
- es_data:/usr/share/elasticsearch/data
networks:
- mm-net
restart: unless-stopped
minio
minio:
image: minio/minio:latest
ports:
- "9000:9000"
- "9001:9001"
environment:
MINIO_ROOT_USER: ${MINIO_ACCESS_KEY}
MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY}
volumes:
- minio_data:/data
command: server /data --console-address ":9001"
networks:
- mm-net
restart: unless-stopped
nginx
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certs:/etc/nginx/certs:ro
depends_on:
- mattermost
networks:
- mm-net
restart: unless-stopped
Quick Start
terminal
1# 1. Create the compose file2cat > docker-compose.yml << 'EOF'3services:4 mattermost:5 image: mattermost/mattermost-team-edition:latest6 ports:7 - "8065:8065"8 environment:9 MM_SQLSETTINGS_DRIVERNAME: postgres10 MM_SQLSETTINGS_DATASOURCE: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?sslmode=disable11 MM_BLEVESETTINGS_INDEXDIR: /mattermost/bleve-indexes12 MM_FILESETTINGS_DRIVERNAME: amazons313 MM_FILESETTINGS_AMAZONS3ACCESSKEYID: ${MINIO_ACCESS_KEY}14 MM_FILESETTINGS_AMAZONS3SECRETACCESSKEY: ${MINIO_SECRET_KEY}15 MM_FILESETTINGS_AMAZONS3BUCKET: mattermost16 MM_FILESETTINGS_AMAZONS3ENDPOINT: minio:900017 MM_FILESETTINGS_AMAZONS3SSL: "false"18 volumes:19 - mattermost_data:/mattermost/data20 - mattermost_logs:/mattermost/logs21 - mattermost_config:/mattermost/config22 - mattermost_plugins:/mattermost/plugins23 - mattermost_bleve:/mattermost/bleve-indexes24 depends_on:25 postgres:26 condition: service_healthy27 minio:28 condition: service_started29 networks:30 - mm-net31 restart: unless-stopped3233 postgres:34 image: postgres:16-alpine35 environment:36 POSTGRES_USER: ${POSTGRES_USER}37 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}38 POSTGRES_DB: ${POSTGRES_DB}39 volumes:40 - postgres_data:/var/lib/postgresql/data41 healthcheck:42 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]43 interval: 10s44 timeout: 5s45 retries: 546 networks:47 - mm-net48 restart: unless-stopped4950 elasticsearch:51 image: elasticsearch:8.11.052 environment:53 - discovery.type=single-node54 - xpack.security.enabled=false55 - ES_JAVA_OPTS=-Xms512m -Xmx512m56 volumes:57 - es_data:/usr/share/elasticsearch/data58 networks:59 - mm-net60 restart: unless-stopped6162 minio:63 image: minio/minio:latest64 ports:65 - "9000:9000"66 - "9001:9001"67 environment:68 MINIO_ROOT_USER: ${MINIO_ACCESS_KEY}69 MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY}70 volumes:71 - minio_data:/data72 command: server /data --console-address ":9001"73 networks:74 - mm-net75 restart: unless-stopped7677 nginx:78 image: nginx:alpine79 ports:80 - "80:80"81 - "443:443"82 volumes:83 - ./nginx.conf:/etc/nginx/nginx.conf:ro84 - ./certs:/etc/nginx/certs:ro85 depends_on:86 - mattermost87 networks:88 - mm-net89 restart: unless-stopped9091volumes:92 mattermost_data:93 mattermost_logs:94 mattermost_config:95 mattermost_plugins:96 mattermost_bleve:97 postgres_data:98 es_data:99 minio_data:100101networks:102 mm-net:103 driver: bridge104EOF105106# 2. Create the .env file107cat > .env << 'EOF'108# PostgreSQL109POSTGRES_USER=mattermost110POSTGRES_PASSWORD=secure_postgres_password111POSTGRES_DB=mattermost112113# MinIO114MINIO_ACCESS_KEY=minioadmin115MINIO_SECRET_KEY=secure_minio_password116EOF117118# 3. Start the services119docker compose up -d120121# 4. View logs122docker 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/mattermost-enterprise/run | bashTroubleshooting
- Mattermost shows 'Database connection failed': Check PostgreSQL health check status and verify POSTGRES_USER/POSTGRES_PASSWORD environment variables match between services
- File uploads fail with S3 errors: Manually create 'mattermost' bucket in MinIO console at localhost:9001 before first use, verify MINIO_ACCESS_KEY credentials
- Search returns no results: Enable Elasticsearch in Mattermost System Console > Environment > Elasticsearch, then run bulk indexing job to populate search index
- 502 Bad Gateway from NGINX: Ensure nginx.conf properly proxies to mattermost:8065 internal hostname, check that Mattermost container is running and healthy
- PostgreSQL container exits with permission errors: Fix Docker volume ownership with 'docker-compose down && docker volume rm postgres_data' then restart
- Elasticsearch fails to start with memory errors: Increase Docker Desktop memory allocation above 4GB or reduce ES_JAVA_OPTS heap size for development environments
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
mattermostpostgresqlelasticsearchminionginx
Tags
#mattermost#team-chat#slack-alternative#enterprise#collaboration
Category
Message Queues & BrokersAd Space
Shortcuts: C CopyF FavoriteD Download