Before deploying this project, you MUST configure your environment for security!
This is a template repository. The following files contain sensitive information and must be created from templates:
- ✅
.env- Database passwords and configuration (use.env.example) - ✅
config.sh- SSH server credentials (useconfig.example.sh)
Never commit these files to version control! They are protected by .gitignore.
-
Clone and navigate to the repository:
git clone <your-repo-url> cd mattermost-deployment
-
Create environment file:
cp .env.example .env nano .env
REQUIRED changes:
DOMAIN: Your server IP or domainPOSTGRES_PASSWORD: Strong password (20+ characters)TZ: Your timezone
-
Create deployment config (for SSH deployment):
cp config.example.sh config.sh nano config.sh
Set:
SERVER_IP: Your server's IPSERVER_USER: Your SSH usernameSERVER_PATH: Deployment directory
-
Deploy:
# Local: ./deploy.sh # Remote: ./deploy-to-ssh.sh
-
Secure after first login: Disable open registration in
.env:MM_TEAMSETTINGS_ENABLEOPENSERVER=false
📖 For complete security guidelines, see SECURITY.md
- Overview
- Quick Start
- Prerequisites
- Deployment Methods
- Management Commands
- Backup & Restore
- Troubleshooting
- Security Recommendations
- Configuration Guide
- Directory Structure
- Additional Resources
This directory contains the complete configuration for deploying Mattermost Team Chat on your infrastructure using Docker containers.
- Deployment: SSH to remote server or local
- Access: Configurable (LAN or public with SSL)
- Edition: Mattermost Team Edition (Free & Open Source)
- Version: 9.5 (Team Edition)
- Database: PostgreSQL 13-alpine
- Deployment Method: Docker Compose
- ✅ Self-hosted team messaging platform
- ✅ Real-time collaboration
- ✅ File sharing and search
- ✅ Mobile and desktop apps
- ✅ Plugin support
- ✅ REST API integration
# From your local machine
cd /path/to/mattermost-deployment
./deploy-to-ssh.sh
# This will automatically transfer files and deploy
# You'll be prompted for sudo password during setup# Transfer files (after creating config.sh)
./transfer-to-server.sh
# SSH and deploy
ssh user@your-server
cd /your/deployment/path
./deploy.shURL: http://YOUR_SERVER_IP:8065 or http://YOUR_DOMAIN (configured in .env)
-
Create System Admin Account
- Open http://YOUR_SERVER_IP:8065
- Fill in email and password
- This will be your main administrator account
-
Create Your First Team
- Choose a team name (e.g., "Your Company")
- Set team URL
-
Invite Users
- Go to Main Menu → Invite People
- Send invitation links to team members on your LAN
Before deploying, ensure you have:
- SSH Access to your target server (for remote deployment)
- Docker Engine (version 20.10 or later)
- Docker Compose (version 1.28 or later)
- Sudo privileges for setting directory permissions
- Open Ports:
- Port 8065 (for direct access without NGINX)
- OR Ports 80/443 (if using NGINX)
If Docker is not installed on your server, run:
# Update package list
sudo apt-get update
# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Install Docker Compose
sudo apt-get install docker-compose-plugin
# Verify installation
docker --version
docker compose versionThe deployment script handles everything automatically:
cd /devops/prod/Mattermost
chmod +x deploy.sh
./deploy.shThe script will:
- ✅ Check Docker installation
- ✅ Create required directories
- ✅ Set proper permissions
- ✅ Ask for deployment mode (with/without NGINX)
- ✅ Pull Docker images
- ✅ Start services
- ✅ Display access URL
If you prefer manual control:
mkdir -p ./volumes/app/mattermost/{config,data,logs,plugins,client/plugins,bleve-indexes}
mkdir -p ./volumes/db/var/lib/postgresql/data
sudo chown -R 2000:2000 ./volumes/app/mattermostEdit the .env file:
nano .envKey settings to review/change:
DOMAIN=your-server-ip-or-domain- Your server IP or hostnamePOSTGRES_PASSWORD=change-this-to-a-strong-password- Change to a secure password (20+ chars)MM_SUPPORTSETTINGS_SUPPORTEMAIL=support@yourdomain.com- Your support emailTZ=Asia/Tehran- Your timezone
Without NGINX (Port 8065):
docker compose -f docker-compose.yml -f docker-compose.without-nginx.yml up -dWith NGINX (Port 80/443):
docker compose -f docker-compose.yml -f docker-compose.nginx.yml up -d# Without NGINX
docker compose -f docker-compose.yml -f docker-compose.without-nginx.yml up -d
# With NGINX
docker compose -f docker-compose.yml -f docker-compose.nginx.yml up -d# Without NGINX
docker compose -f docker-compose.yml -f docker-compose.without-nginx.yml down
# With NGINX
docker compose -f docker-compose.yml -f docker-compose.nginx.yml down# Without NGINX
docker compose -f docker-compose.yml -f docker-compose.without-nginx.yml restart
# With NGINX
docker compose -f docker-compose.yml -f docker-compose.nginx.yml restartdocker compose ps# All services
docker compose logs -f
# Mattermost only
docker compose logs -f mattermost
# PostgreSQL only
docker compose logs -f postgres
# Last 100 lines
docker compose logs --tail=100 mattermost# Backup data first!
./backup.sh
# Pull new images
docker compose pull
# Restart with new images
docker compose -f docker-compose.yml -f docker-compose.without-nginx.yml up -ddocker image prune -aUse the provided backup script:
./backup.shBackups are stored in ./backups/ with timestamp in the filename.
# Create database backup
docker exec mattermost-postgres pg_dump -U mmuser mattermost > mattermost_db_backup_$(date +%Y%m%d).sql
# Compress backup
gzip mattermost_db_backup_$(date +%Y%m%d).sql# Backup all volumes
tar -czf mattermost_volumes_backup_$(date +%Y%m%d).tar.gz ./volumes/
# Backup only Mattermost data
tar -czf mattermost_data_backup_$(date +%Y%m%d).tar.gz ./volumes/app/mattermost/data/# Decompress if needed
gunzip mattermost_db_backup_YYYYMMDD.sql.gz
# Restore database
cat mattermost_db_backup_YYYYMMDD.sql | docker exec -i mattermost-postgres psql -U mmuser -d mattermost# Stop services first
docker compose down
# Restore volumes
tar -xzf mattermost_volumes_backup_YYYYMMDD.tar.gz
# Fix permissions
sudo chown -R 2000:2000 ./volumes/app/mattermost
# Restart services
docker compose -f docker-compose.yml -f docker-compose.without-nginx.yml up -dSymptoms:
- Browser shows "Connection refused" or "Can't reach this page"
- Timeout when accessing http://YOUR_SERVER_IP:8065
Solutions:
-
Check if containers are running:
docker compose ps
Expected output should show
mattermostandpostgrescontainers as "Up" or "healthy" -
Check Mattermost logs:
docker compose logs mattermost
Look for error messages or startup issues
-
Verify port is open:
sudo netstat -tlnp | grep 8065Should show Docker is listening on port 8065
-
Test from server itself:
curl http://localhost:8065/api/v4/system/ping
Should return:
{"status":"OK"} -
Check firewall:
sudo ufw status # If blocking, allow the port sudo ufw allow 8065/tcp -
Restart containers:
docker compose restart
Symptoms:
- Browser shows infinite redirect loop
- "Too many redirects" error
Solutions:
-
Check SITE_URL configuration:
grep SITE_URL .env
Should match your access URL (e.g.,
http://YOUR_SERVER_IP:8065) -
Verify you're using correct compose files:
# Without NGINX - should NOT redirect docker compose -f docker-compose.yml -f docker-compose.without-nginx.yml ps -
Clear browser cache and cookies for your server domain
-
Check if NGINX is interfering:
docker compose ps nginx # If nginx is running when you don't want it, stop it docker compose stop nginx -
Reset configuration:
docker compose down rm -rf ./volumes/app/mattermost/config/* docker compose -f docker-compose.yml -f docker-compose.without-nginx.yml up -d
Symptoms:
- Mattermost logs show database errors
- "Unable to connect to database"
Solutions:
-
Check PostgreSQL logs:
docker compose logs postgres
-
Verify database is healthy:
docker exec mattermost-postgres pg_isready -U mmuser -d mattermostShould return:
accepting connections -
Test database connection:
docker exec -it mattermost-postgres psql -U mmuser -d mattermost -c "SELECT version();"
-
Check database password in .env:
grep POSTGRES_PASSWORD .env grep MM_SQLSETTINGS_DATASOURCE .env
Make sure they match
-
Restart database:
docker compose restart postgres # Wait 10 seconds docker compose restart mattermost
Symptoms:
- Errors about "permission denied" in logs
- Cannot create files or directories
- Upload errors
Solutions:
-
Check current permissions:
ls -la ./volumes/app/mattermost/
-
Reset permissions:
sudo chown -R 2000:2000 ./volumes/app/mattermost sudo chmod -R 755 ./volumes/app/mattermost
-
Fix database permissions:
sudo chown -R 999:999 ./volumes/db/var/lib/postgresql/data
-
Restart after fixing permissions:
docker compose restart
Symptoms:
- Error: "bind: address already in use"
- Cannot start containers
Solutions:
-
Check what's using the port:
sudo lsof -i :8065 sudo ss -tlnp | grep 8065 -
Stop the conflicting service:
# If it's another Docker container docker ps | grep 8065 docker stop <container_id>
-
Change APP_PORT in .env:
nano .env # Change APP_PORT to a different port (e.g., 8066) # Then restart docker compose down docker compose -f docker-compose.yml -f docker-compose.without-nginx.yml up -d
Symptoms:
- Container immediately exits
- Status shows "Exited (1)" or "Restarting"
Solutions:
-
Check detailed logs:
docker compose logs --tail=200 mattermost
-
Check Docker events:
docker events & docker compose up -d -
Verify configuration syntax:
docker compose config
-
Remove and recreate containers:
docker compose down docker compose -f docker-compose.yml -f docker-compose.without-nginx.yml up -d
-
Complete reset (
⚠️ WARNING: Deletes data!):# Backup first! ./backup.sh # Remove everything docker compose down -v rm -rf ./volumes/app/mattermost/* rm -rf ./volumes/db/* # Recreate from scratch ./deploy.sh
Symptoms:
- Server becomes slow or unresponsive
- Out of memory errors
Solutions:
-
Check resource usage:
docker stats
-
Limit container resources in docker-compose.yml:
services: mattermost: deploy: resources: limits: cpus: '2.0' memory: 2G reservations: memory: 1G
-
Check for memory leaks in logs:
docker compose logs mattermost | grep -i "memory\|oom"
-
Restart containers:
docker compose restart
-
Upgrade server resources if consistently high
Symptoms:
- File upload fails with error message
- "Request entity too large" error
Solutions:
-
Check Mattermost file size limit:
- Go to System Console → Environment → File Storage
- Increase "Maximum File Size"
-
If using NGINX, update client_max_body_size:
nano nginx.conf # Add or modify: client_max_body_size 100M; docker compose restart nginx
-
Check disk space:
df -h
-
Verify permissions on data directory:
sudo chown -R 2000:2000 ./volumes/app/mattermost/data
Symptoms:
- Users don't receive email notifications
- SMTP errors in logs
Solutions:
-
Configure SMTP settings in .env:
nano .env
Add SMTP configuration:
MM_EMAILSETTINGS_SMTPSERVER=smtp.gmail.com MM_EMAILSETTINGS_SMTPPORT=587 MM_EMAILSETTINGS_SMTPUSERNAME=your-email@gmail.com MM_EMAILSETTINGS_SMTPPASSWORD=your-app-password MM_EMAILSETTINGS_ENABLESMTPAUTH=true -
Test email from System Console:
- Go to System Console → Environment → SMTP
- Click "Test Connection"
-
Check logs for SMTP errors:
docker compose logs mattermost | grep -i smtp
Symptoms:
- Search returns no results
- Old messages cannot be found
Solutions:
-
Rebuild search index:
- Go to System Console → Environment → Elasticsearch
- Click "Purge Indexes" then "Build Index"
-
Check Bleve indexes:
ls -la ./volumes/app/mattermost/bleve-indexes/ sudo chown -R 2000:2000 ./volumes/app/mattermost/bleve-indexes
-
Restart Mattermost:
docker compose restart mattermost
-
Edit config.json or use environment variable:
# Add to .env MM_LOGSETTINGS_CONSOLELEVEL=DEBUG MM_LOGSETTINGS_FILELEVEL=DEBUG -
Restart and check logs:
docker compose restart mattermost docker compose logs -f mattermost
# Access Mattermost container
docker exec -it mattermost bash
# Access PostgreSQL container
docker exec -it postgres bash
# Inside container, check configuration
cat /mattermost/config/config.json# Check Docker network
docker network ls
docker network inspect mattermost_default
# Test connectivity between containers
docker exec mattermost ping postgresIf you've tried the troubleshooting steps and still have issues:
- ✅ Review all logs:
docker compose logs --tail=500 - ✅ Check Mattermost Troubleshooting Guide
- ✅ Search Mattermost Forum
- ✅ Review your
.envconfiguration - ✅ Contact your support email configured in
.env
-
Change Default Passwords
nano .env # Update these values: POSTGRES_PASSWORD=YourStrongPassword123!
Use strong, unique passwords with:
- Minimum 12 characters
- Mix of uppercase, lowercase, numbers, and symbols
- No dictionary words
-
Enable HTTPS (For production use)
- Use NGINX configuration with SSL/TLS
- Obtain SSL certificates from Let's Encrypt:
sudo apt-get install certbot sudo certbot certonly --standalone -d yourdomain.com
- Update nginx.conf with certificate paths
-
Firewall Configuration
# Allow only from LAN (adjust network range as needed) sudo ufw allow from 172.18.0.0/16 to any port 8065 # Or allow specific IP addresses sudo ufw allow from 172.18.10.0/24 to any port 8065 # Check firewall status sudo ufw status
-
Disable Open User Registration
- Go to System Console → Authentication → Signup
- Disable "Enable Open Server"
- Enable "Enable Email Invitations"
-
Configure Session Length
- Go to System Console → Environment → Session Lengths
- Set appropriate session timeout (e.g., 30 days for mobile, 24 hours for web)
-
Regular Updates
# Create a maintenance schedule # Check for updates monthly docker compose pull docker compose down docker compose -f docker-compose.yml -f docker-compose.without-nginx.yml up -d
- Monitor Mattermost Security Updates
- Subscribe to security notifications
-
Regular Backups
# Schedule automated backups (add to crontab) crontab -e # Add this line for daily backup at 2 AM: 0 2 * * * cd /devops/prod/Mattermost && ./backup.sh >> /var/log/mattermost_backup.log 2>&1
- Test restore procedures monthly
- Store backups off-site or on different server
-
Monitor Logs
# Check for suspicious activity docker compose logs mattermost | grep -i "failed\|error\|unauthorized"
-
Limit Admin Privileges
- Create separate admin accounts for different administrators
- Use normal user accounts for daily work
- Enable multi-factor authentication (MFA) for admins
-
Network Isolation
- Keep database not exposed to external network
- Use Docker networks for service isolation
- Regular security audits
Key configuration options in .env file:
# Domain Configuration
DOMAIN=your-server-ip
SITE_URL=http://your-server-ip:8065
# PostgreSQL Configuration
POSTGRES_USER=mmuser
POSTGRES_PASSWORD=mmuser_password # CHANGE THIS!
POSTGRES_DB=mattermost
# Mattermost Database Connection
MM_SQLSETTINGS_DATASOURCE=postgres://mmuser:mmuser_password@postgres:5432/mattermost?sslmode=disable&connect_timeout=10
# Application Settings
APP_PORT=8065
TZ=Asia/Tehran
# Support Settings
MM_SUPPORTSETTINGS_SUPPORTEMAIL=support@yourdomain.com
# File Storage
MM_FILESETTINGS_MAXFILESIZE=104857600 # 100MB in bytes
# Plugin Settings
MM_PLUGINSETTINGS_ENABLE=true
MM_PLUGINSETTINGS_ENABLEUPLOADS=trueAfter deployment, configure via web interface:
- Site URL: System Console → Environment → Web Server → Site URL
- Email: System Console → Environment → SMTP
- File Storage: System Console → Environment → File Storage
- Notifications: System Console → Site Configuration → Notifications
- Authentication: System Console → Authentication
Edit config.json directly (requires restart):
# Backup first
cp ./volumes/app/mattermost/config/config.json ./volumes/app/mattermost/config/config.json.backup
# Edit
nano ./volumes/app/mattermost/config/config.json
# Restart to apply
docker compose restart mattermost/devops/prod/Mattermost/
├── .env # Environment configuration
├── .gitignore # Git ignore rules
├── docker-compose.yml # Main Docker Compose file
├── docker-compose.without-nginx.yml # Direct access configuration (port 8065)
├── docker-compose.nginx.yml # NGINX reverse proxy configuration (port 80/443)
├── nginx.conf # NGINX configuration (if using NGINX)
├── deploy.sh # Automated deployment script
├── backup.sh # Automated backup script
├── transfer-to-server.sh # Transfer files to server script
├── README.md # This file (comprehensive guide)
├── QUICKSTART.md # Quick reference guide
├── DEPLOYMENT_CHECKLIST.md # Deployment checklist
└── volumes/ # Data persistence
├── app/
│ └── mattermost/
│ ├── config/ # Mattermost configuration (config.json)
│ ├── data/ # User data, files, uploads
│ ├── logs/ # Application logs
│ ├── plugins/ # Installed plugins
│ ├── client/plugins/ # Client-side plugins
│ └── bleve-indexes/ # Search indexes
└── db/
└── var/lib/postgresql/data/ # PostgreSQL database files
Use this checklist for deployments:
- Verify SSH access to your server
- Confirm Docker is installed on server
- Confirm Docker Compose is installed on server
- Create directory:
/devops/prod/Mattermost - Review and customize
.envfile settings - Change default
POSTGRES_PASSWORD - Set
MM_SUPPORTSETTINGS_SUPPORTEMAIL
- Transfer files to server
- Make scripts executable:
chmod +x *.sh - Run deployment script:
./deploy.sh - Verify containers are running:
docker compose ps
- Access web interface: http://YOUR_SERVER_IP:8065
- Create system admin account
- Create first team
- Test sending messages
- Configure backup schedule
- Document admin credentials (securely!)
- Configure firewall rules if needed
- Set up regular automated backups
- Test backup and restore procedures
- Review security settings
- Disable open registration (if desired)
- Mattermost Documentation: https://docs.mattermost.com/
- Docker Deployment Guide: https://docs.mattermost.com/install/install-docker.html
- Configuration Settings: https://docs.mattermost.com/administration/config-settings.html
- Troubleshooting: https://docs.mattermost.com/deployment-guide/server/docker-troubleshooting.html
- API Documentation: https://api.mattermost.com/
- Mattermost Forum: https://forum.mattermost.com/
- GitHub Repository: https://github.com/mattermost/mattermost
- Security Updates: https://mattermost.com/security-updates/
- Docker Documentation: https://docs.docker.com/
- iOS: https://apps.apple.com/app/mattermost/id1257222717
- Android: https://play.google.com/store/apps/details?id=com.mattermost.rn
- Download: https://mattermost.com/download/
- ✅ Check the Troubleshooting section above
- ✅ Review Mattermost logs:
docker compose logs -f - ✅ Consult official documentation
- ✅ Search the Mattermost forum
- ✅ Contact your support email configured in
.env
# Quick status check
docker compose ps
# View logs
docker compose logs -f mattermost
# Restart services
docker compose restart
# Create backup
./backup.sh
# Update Mattermost
docker compose pull && docker compose up -d
# Access Mattermost container
docker exec -it mattermost bash
# Test API
curl http://localhost:8065/api/v4/system/ping- Mattermost Version: 9.5 (Team Edition)
- PostgreSQL Version: 13-alpine
- Deployment Method: Docker Compose
- Last Updated: 2025-12-29
- Guide Version: 2.0 (Comprehensive)
-
Explore Features
- Create channels for different teams/projects
- Set up integrations with other tools
- Install plugins from Marketplace
-
Configure Notifications
- Set up email notifications
- Configure webhook integrations
- Set up mobile push notifications
-
User Training
- Share user guides with team members
- Conduct training sessions
- Create internal documentation
-
Performance Monitoring
- Monitor resource usage
- Check logs regularly
- Set up alerts for issues
-
Plan for Growth
- Monitor user count
- Plan for scaling if needed
- Review upgrade paths
Q: Can I access Mattermost from outside the LAN? A: Yes, but you'll need to:
- Configure your firewall/router to forward port 8065
- Set up HTTPS with valid SSL certificates
- Use a domain name instead of IP address
- Ensure proper security measures are in place
Q: How do I add users? A: System Admin can invite users via:
- Main Menu → Invite People → Send Email Invite
- Or share the team invitation link
- Or create accounts in System Console → Users
Q: Can I integrate with other tools? A: Yes, Mattermost supports:
- Webhooks (incoming/outgoing)
- Slash commands
- OAuth 2.0
- Plugins (GitLab, GitHub, Jira, etc.)
- REST API for custom integrations
Q: How much disk space do I need? A: Minimum requirements:
- 2GB for application
- Database size depends on usage (start with 5GB minimum)
- File storage depends on uploads (plan for at least 10GB)
- Total recommended: 20GB+ for small teams
Q: Can I migrate from Slack or Teams? A: Yes, Mattermost provides migration tools:
- Bulk Loading Tool for Slack imports
- See: https://docs.mattermost.com/onboard/migrating-to-mattermost.html
Happy Collaborating! 🎉
For quick reference, see QUICKSTART.md
