Self-Host Mattermost: Team Chat Slack Alternative 2026
TL;DR
Mattermost (MIT, ~31K GitHub stars, Go) is the leading open source Slack alternative for self-hosted teams. Slack charges $7.25/user/month. Mattermost Team Edition is free and includes channels, direct messages, threads, file sharing, search, webhooks, bots, slash commands, and native iOS/Android apps. It's the communication platform used by NASAl, Samsung, and thousands of engineering teams who need to keep data on-premises.
Key Takeaways
- Mattermost: MIT, ~31K stars, Go — Slack alternative with channels, threads, DMs
- Native apps: iOS, Android, Desktop (Windows/Mac/Linux) — all free
- Integrations: Incoming/outgoing webhooks, slash commands, bots, OAuth2
- GitOps integration: Natibe Gitea, GitLab, GitHub notifications and PR previews
- Compliance: Full message export, audit logs, retention policies (Team Edition)
- vs Slack: Mattermost has all core features; Slack wins on third-party app count
Mattermost vs Slack vs Rocket.Chat vs Zulip
| Feature | Mattermost | Slack | Rocket.Chat | Zulip |
|---|---|---|---|---|
| License | MIT | Proprietary | MIT | Apache 2.0 |
| GitHub Stars | ~31K | — | ~40K | ~22K |
| Cost (self-hosted) | Free | $7.25/user/mo | Free | Free |
| Threads | Yes | Yes | Yes | Yes (topic-based) |
| Voice/video | Paid only | Yes | Yes | No |
| Mobile apps | Yes | Yes | Yes | Yes |
| GitLab/Gitea native | Yes | Via plugin | Via integration | No |
| Bots/webhooks | Yes | Yes | Yes | Yes |
| LDAP | Paid (E10) | Yes | Free | Free |
Part 1: Docker Setup
# docker-compose.yml
services:
mattermost:
image: mattermost/mattermost-team-edition:latest
container_name: mattermost
restart: unless-stopped
ports:
- "8065:8065"
volumes:
- mattermost_config:/mattermost/config
- mattermost_data:/mattermost/data
- mattermost_logs:/mattermost/logs
- mattermost_plugins:/mattermost/plugins
- mattermost_client_plugins:/mattermost/client/plugins
- mattermost_bleve:/mattermost/bleve-indexes
environment:
MM_SQLSETTINGS_DRIVERNAME: "postgres"
MM_SQLSETTINGS_DATASOURCE: "postgres://mattermost:${POSTGRES_PASSWORD}@postgres:5432/mattermost?sslmode=disable&connect_timeout=10"
MM_BLEVESETTINGS_INDEXDIR: "/mattermost/bleve-indexes"
MM_SERVICESETTINGS_SITEURL: "https://chat.yourdomain.com"
MM_EMAILSETTINGS_SENDEMAILNOTIFICATIONS: "true"
MM_EMAILSETTINGS_SMTPSERVER: "smtp.yourdomain.com"
MM_EMAILSETTINGS_SMTPPORT: "587"
MM_EMAILSETTINGS_SMTPUSERNAME: "${SMTP_USER}"
MM_EMAILSETTINGS_SMTPPASSWORD: "${SMTP_PASS}"
MM_EMAILSETTINGS_FEEDBACKEMAIL: "mattermost@yourdomain.com"
depends_on:
postgres:
condition: service_healthy
postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: mattermost
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
POSTGRES_DB: mattermost
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U mattermost"]
interval: 10s
start_period: 20s
volumes:
mattermost_config:
mattermost_data:
mattermost_logs:
mattermost_plugins:
mattermost_client_plugins:
mattermost_bleve:
postgres_data:
# .env
POSTGRES_PASSWORD=your-secure-db-password
docker compose up -d
Visit http://your-server:8065 → create the admin account.
Part 2: HTTPS with Caddy
chat.yourdomain.com {
reverse_proxy localhost:8065
}
Part 3: First-Time Configuration
After creating admin account:
- System Console → Site Configuration → Site URL:
https://chat.yourdomain.com - Email settings: Configure SMTP (already set via env vars)
- Create first team: Name your workspace (e.g., "Engineering Team")
- Invite users: Team Settings → Invite People → by email or invite link
- Create channels:
#generaland#randomare auto-created; add project channels
Part 4: Incoming Webhooks
Set up webhooks to receive notifications from external services:
- Integrations → Incoming Webhooks → Add Incoming Webhook
- Select channel (e.g.,
#deployments) - Copy the webhook URL
# Send a message via webhook:
curl -X POST https://chat.yourdomain.com/hooks/YOUR-WEBHOOK-ID \
-H "Content-Type: application/json" \
-d '{"text": "🚀 Deployment to production complete!", "username": "deploy-bot"}'
# With attachment (rich message):
curl -X POST https://chat.yourdomain.com/hooks/YOUR-WEBHOOK-ID \
-H "Content-Type: application/json" \
-d '{
"attachments": [{
"color": "#36a64f",
"title": "Build #42 Passed",
"title_link": "https://ci.yourdomain.com/builds/42",
"text": "All 347 tests passed in 2m 15s",
"fields": [
{"short": true, "title": "Branch", "value": "main"},
{"short": true, "title": "Commit", "value": "abc1234"}
]
}]
}'
Part 5: Gitea/GitHub Integration
Receive notifications from your Git forge:
Gitea webhook
In Gitea: Repo → Settings → Webhooks → Add Webhook → Gitea
- Payload URL:
https://chat.yourdomain.com/hooks/YOUR-WEBHOOK-ID - Content type:
application/json - Events: Push, PR, Issues — select what you need
Mattermost auto-formats Gitea push events:
[repo] main: alice pushed 3 commits
• abc1234 fix: resolve login bug
• def5678 feat: add dark mode
GitHub app plugin
Install from Marketplace: https://chat.yourdomain.com/admin_console/integrations/marketplace
Search "GitHub" → install → configure with GitHub personal token
Part 6: Bots and Slash Commands
Create a bot account
- Integrations → Bot Accounts → Add Bot Account
- Username:
deploy-bot - Role: Member
- Copy the access token
# Use the bot token to post messages:
import requests
MATTERMOST_URL = "https://chat.yourdomain.com"
BOT_TOKEN = "your-bot-token"
CHANNEL_ID = "channelid123"
def post_message(text):
requests.post(
f"{MATTERMOST_URL}/api/v4/posts",
headers={"Authorization": f"Bearer {BOT_TOKEN}"},
json={"channel_id": CHANNEL_ID, "message": text}
)
post_message("🔴 Production alert: Database CPU > 90%")
Custom slash command
- Integrations → Slash Commands → Add Slash Command
- Command:
/deploy - Request URL:
https://your-backend.com/deploy-webhook - Response username:
deploy-bot
When a user types /deploy staging, Mattermost POSTs to your backend with the command and arguments.
Part 7: LDAP / Active Directory (E10 feature)
For enterprises needing SSO — requires Enterprise Edition. For Team Edition, use GitLab/Gitea OAuth2:
environment:
# GitLab OAuth2 (free):
MM_GITLABSETTINGS_ENABLE: "true"
MM_GITLABSETTINGS_SECRET: "${GITLAB_SECRET}"
MM_GITLABSETTINGS_ID: "${GITLAB_CLIENT_ID}"
MM_GITLABSETTINGS_AUTHENDPOINT: "https://gitlab.yourdomain.com/oauth/authorize"
MM_GITLABSETTINGS_TOKENENDPOINT: "https://gitlab.yourdomain.com/oauth/token"
MM_GITLABSETTINGS_USERAPIENDPOINT: "https://gitlab.yourdomain.com/api/v4/user"
For Authentik OIDC, use the GitLab OAuth2 settings with Authentik endpoints.
Part 8: Mobile and Desktop Apps
Mobile (iOS/Android)
- Install Mattermost from App Store or Google Play
- + Add Server →
https://chat.yourdomain.com - Push notifications work via Mattermost's HPNS (push proxy) or self-hosted push server
Self-hosted push notifications
# Add push proxy to docker-compose.yml:
services:
push-proxy:
image: mattermost/mattermost-push-proxy:latest
container_name: mm_push_proxy
ports:
- "8066:8066"
volumes:
- ./push-proxy.json:/go/src/github.com/mattermost/mattermost-push-proxy/config/mattermost-push-proxy.json
# System Console → Push Notification Server:
environment:
MM_EMAILSETTINGS_PUSHNOTIFICATIONSERVER: "https://push.yourdomain.com"
Maintenance
# Update Mattermost:
docker compose pull
docker compose up -d
# Backup:
docker exec mattermost-postgres-1 pg_dump -U mattermost mattermost \
| gzip > mattermost-db-$(date +%Y%m%d).sql.gz
tar -czf mattermost-data-$(date +%Y%m%d).tar.gz \
$(docker volume inspect mattermost_mattermost_data --format '{{.Mountpoint}}')
# Logs:
docker compose logs -f mattermost
# CLI admin commands:
docker exec mattermost mattermost user create --email admin@yourdomain.com --username admin --password secret --system-admin
docker exec mattermost mattermost channel list myteam
See all open source team communication tools at OSSAlt.com/categories/communication.