Self-Hosting Mattermost: Team Chat on Your Server 2026
Mattermost is the open source Slack alternative. Self-hosting gives you unlimited users, full data ownership, and costs only the price of a VPS. Here's the complete production setup.
Why Self-Host Mattermost
Slack's per-seat pricing adds up fast. The Pro plan costs $7.25/user/month (billed annually), which sounds manageable for a 10-person team at $870/year. Scale to 50 users and you're at $4,350/year. Add a hundred people and you're writing a $8,700 check annually — just for chat. The Business+ plan at $12.50/user/month doubles that cost again.
Mattermost on a €8/month Hetzner server handles 50 users for approximately $96/year — a 97% cost reduction compared to Slack Pro. Even factoring in a few hours of setup time, the math is overwhelmingly in favor of self-hosting for any team willing to own their infrastructure.
Compliance and data sovereignty are the primary reason regulated industries choose self-hosted Mattermost. Healthcare teams subject to HIPAA, fintech companies under SOC 2 obligations, and government contractors with data residency requirements cannot use SaaS chat platforms that store messages on US-based servers without complex BAA agreements and careful configuration. Self-hosting means messages never leave your infrastructure.
Full message history is another win. Slack's free tier limits search to 90 days of messages. Mattermost retains everything indefinitely (or for however long your retention policy dictates). Your team's institutional knowledge — decisions made in channels, technical discussions, customer context — stays accessible.
Customization includes custom integrations via webhooks, slash commands, and bots; branded themes; and the ability to write plugins in Go or React for deeply custom workflows.
When NOT to self-host Mattermost: If your team is under 15 people and lacks anyone comfortable managing a Linux server, Slack's free tier or Slack Pro is probably a better fit. The operational overhead of keeping a chat server running (updates, backups, disk management) is real. Also note: some Mattermost features like LDAP/AD sync and E2E encryption are Enterprise-only, so check the feature matrix before committing.
Prerequisites
Getting Mattermost production-ready requires more than just Docker Compose. Choosing the right VPS provider matters — Mattermost needs stable uptime since it's a communication tool your team will depend on.
Server specs: Mattermost recommends 4 GB RAM minimum for production. With 1-50 users, a 4 GB server works well; 50-200 users needs 8 GB. The PostgreSQL database running alongside Mattermost is the main RAM consumer — allocate 25-30% of your RAM to the database. CPU is less critical; 2 vCPU handles most small teams comfortably.
Operating system: Ubuntu 22.04 LTS is the recommended choice. It's the most widely documented platform for Docker deployments, receives security patches through 2027 standard support, and most troubleshooting resources assume Ubuntu.
Docker and Docker Compose: Mattermost's official Docker setup uses Docker Compose v2 (the docker compose command). Install Docker Engine 24+ using the official install script and confirm docker compose version shows v2.x before proceeding.
Storage planning: File attachments accumulate quickly on a team chat server. A 20 GB root disk will fill up within months on an active team. Either start with a larger disk or mount a separate block storage volume for the Mattermost data directory. Plan for 10 GB per active user per year as a rough estimate.
Domain and DNS: Point chat.yourdomain.com to your server IP. Caddy will automatically provision an SSL certificate — no manual certificate management needed.
SMTP for notifications: Team members need email notifications for mentions, direct messages, and account actions. Use Resend, Postmark, or Mailgun — all have free tiers that cover low-volume use.
Requirements
- VPS with 4 GB RAM minimum
- Docker and Docker Compose
- Domain name (e.g.,
chat.yourdomain.com) - 20+ GB disk for file attachments
Step 1: Clone the Official Docker Setup
git clone https://github.com/mattermost/docker.git mattermost-docker
cd mattermost-docker
# Create data directories
mkdir -p ./volumes/app/mattermost/{config,data,logs,plugins,client/plugins,bleve-indexes}
sudo chown -R 2000:2000 ./volumes/app/mattermost
# Copy environment
cp env.example .env
Step 2: Configure
Edit .env:
# Domain
DOMAIN=chat.yourdomain.com
# Database
POSTGRES_USER=mmuser
POSTGRES_PASSWORD=your-strong-password
POSTGRES_DB=mattermost
# Mattermost
MM_SQLSETTINGS_DRIVERNAME=postgres
MM_SQLSETTINGS_DATASOURCE=postgres://mmuser:your-strong-password@db:5432/mattermost?sslmode=disable&connect_timeout=10
# File storage
MM_FILESETTINGS_DRIVERNAME=local
MM_FILESETTINGS_DIRECTORY=/mattermost/data
# SMTP (for email notifications)
MM_EMAILSETTINGS_SMTPSERVER=smtp.resend.com
MM_EMAILSETTINGS_SMTPPORT=587
MM_EMAILSETTINGS_SMTPUSERNAME=resend
MM_EMAILSETTINGS_SMTPPASSWORD=re_your_api_key
MM_EMAILSETTINGS_CONNECTIONSECURITY=STARTTLS
MM_EMAILSETTINGS_FEEDBACKEMAIL=mattermost@yourdomain.com
Step 3: Start Mattermost
docker compose -f docker-compose.yml -f docker-compose.without-nginx.yml up -d
Step 4: Reverse Proxy (Caddy)
# /etc/caddy/Caddyfile
chat.yourdomain.com {
reverse_proxy localhost:8065
}
sudo systemctl restart caddy
Step 5: Initial Setup
- Open
https://chat.yourdomain.com - Create admin account
- Create your first team
- Configure System Console → Environment → verify settings
Step 6: Essential Configuration
System Console settings to configure:
| Setting | Recommendation |
|---|---|
| Site URL | https://chat.yourdomain.com |
| Max file size | 100 MB |
| Enable plugins | ✅ |
| Enable integrations | ✅ |
| Session length | 720 hours (30 days) |
| Rate limiting | Enable for production |
Step 7: Install Plugins
| Plugin | Purpose |
|---|---|
| Calls | Voice/video calls (built-in) |
| Playbooks | Incident management |
| GitHub | Notifications, PR reviews |
| Jira | Issue tracking integration |
| GitLab | MR notifications |
| Zoom | Meeting integration |
| Calendar | Shared team calendar |
Install via System Console → Plugin Marketplace.
Step 8: Invite Team
- Main Menu → Invite People
- Generate invite link or send email invitations
- Share desktop/mobile app download links:
- Desktop: mattermost.com/apps
- iOS: App Store
- Android: Google Play
Production Hardening
Backups:
# Database backup (daily cron)
docker compose exec db pg_dump -U mmuser mattermost > /backups/mm-$(date +%Y%m%d).sql
# File attachments backup
tar czf /backups/mm-files-$(date +%Y%m%d).tar.gz ./volumes/app/mattermost/data
Updates:
cd mattermost-docker
docker compose pull
docker compose up -d
Monitoring:
- Monitor port 8065 with Uptime Kuma
- Set up disk space alerts (file attachments grow)
- Monitor PostgreSQL connections
Resource Usage
| Users | RAM | CPU | Disk |
|---|---|---|---|
| 1-50 | 4 GB | 2 cores | 20 GB |
| 50-100 | 8 GB | 4 cores | 50 GB |
| 100-500 | 16 GB | 8 cores | 100 GB |
VPS Recommendations
| Provider | Spec (50 users) | Price |
|---|---|---|
| Hetzner | 4 vCPU, 8 GB RAM | €8/month |
| DigitalOcean | 2 vCPU, 4 GB RAM | $24/month |
| Linode | 2 vCPU, 4 GB RAM | $24/month |
Production Security Hardening
A team chat server holds sensitive conversations — internal decisions, customer data, credentials shared in DMs. Hardening goes beyond the app itself. Review the full self-hosting security checklist for a comprehensive treatment; below are the most critical steps for Mattermost specifically.
UFW firewall: Only Caddy's ports should be internet-facing. Mattermost's port 8065 should only be accessible from localhost.
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Block direct access to Mattermost — traffic goes through Caddy
sudo ufw deny 8065/tcp
sudo ufw enable
Fail2ban for SSH: Install and configure fail2ban to block IPs that make repeated failed SSH login attempts.
sudo apt install fail2ban -y
Create /etc/fail2ban/jail.local:
[sshd]
enabled = true
maxretry = 5
bantime = 1800
findtime = 300
Secrets in .env files: The .env file in your mattermost-docker directory contains your database password and SMTP credentials. Set strict permissions and never commit it to version control:
chmod 600 .env
echo ".env" >> .gitignore
Disable SSH password authentication: Edit /etc/ssh/sshd_config:
PasswordAuthentication no
PermitRootLogin no
Restart sshd: sudo systemctl restart sshd. Make sure your SSH key is in ~/.ssh/authorized_keys first.
Automatic security updates: Enable unattended-upgrades to patch vulnerabilities automatically:
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure --priority=low unattended-upgrades
Mattermost-specific: In the System Console, restrict team invitations to email domains you control (@yourcompany.com only), disable user profile picture uploads if not needed, and review the API Rate Limiting settings to prevent abuse.
Troubleshooting Common Issues
Mattermost shows "Site URL mismatch" in System Console
This happens when the MM_SERVICESETTINGS_SITEURL environment variable doesn't match the URL you're accessing. In the System Console, go to Environment → Web Server → Site URL and set it to https://chat.yourdomain.com exactly. Alternatively, set the environment variable: MM_SERVICESETTINGS_SITEURL=https://chat.yourdomain.com in your .env file and restart.
File uploads fail with 413 error
Caddy is rejecting request bodies larger than its default limit. Add a request body size directive to your Caddyfile:
chat.yourdomain.com {
reverse_proxy localhost:8065
request_body {
max_size 150MB
}
}
Also verify Mattermost's own file size limit in System Console → File Storage → Maximum File Size.
Email notifications not sending
Test SMTP credentials directly from the Mattermost System Console under Notifications → Email → Send a Test Email. If that fails, double-check your SMTP password and ensure port 587 isn't blocked by your VPS provider (some block outbound SMTP by default — Hetzner requires a support request to enable it).
Database connection errors after restart
The Mattermost container sometimes starts before PostgreSQL is ready to accept connections. Add a health check to the db service in your compose file, or simply restart Mattermost manually after a reboot: docker compose restart app. The database volume persists across restarts — no data is lost.
Disk space filling up from logs
Mattermost writes verbose logs by default. Configure log rotation in System Console → Environment → Logging, set the file log level to WARN or ERROR for production. Also set up regular backups to offload old attachments; see automated server backups with restic for a complete backup strategy to object storage.
Plugin installation fails
If plugins fail to install from the Marketplace, verify the server has outbound HTTPS access and that MM_SERVICESETTINGS_ENABLEMARKETPLACE=true is set. For air-gapped environments, download the plugin .tar.gz and upload it manually via System Console → Plugin Management → Upload Plugin.
Ongoing Maintenance and Operations
A self-hosted Mattermost instance requires occasional attention but is generally stable once correctly configured. Here's what to plan for over the lifetime of your deployment.
Weekly tasks: Check disk usage on the data volume where file attachments are stored. Mattermost doesn't automatically purge old file attachments — your disk fills up as users share files. Set up a Grafana or Uptime Kuma dashboard to alert when the data directory exceeds 80% capacity. Plan to either add disk space or set up a file retention policy.
File retention policy. In the Mattermost System Console under Compliance → Data Retention Policy, you can configure automatic deletion of messages and files older than a certain age. For most teams, a 1-year message retention with 90-day file retention is a reasonable balance between storage costs and institutional memory.
Database maintenance. The PostgreSQL database grows with message history. Running VACUUM ANALYZE periodically helps maintain query performance. Add this to a monthly maintenance cron: docker exec mattermost-db psql -U mmuser -d mattermost -c "VACUUM ANALYZE;". Mattermost's own background jobs handle most database maintenance, but explicit vacuuming keeps things tidy on busy instances.
Plugin updates. Mattermost plugins update independently from the core application. Check the Plugin Marketplace monthly for updates. Major plugin updates sometimes require reviewing changelog notes — the Calls plugin in particular has had breaking configuration changes between versions.
Certificate renewal. Caddy handles SSL certificate renewal automatically via ACME. Certificates are renewed 30 days before expiration. If your server's internet access is interrupted during renewal, certificates can expire. Monitor certificate expiry with a tool like Uptime Kuma's SSL monitoring feature, which alerts you if a certificate is within 30 days of expiry.
Upgrading Mattermost. The docker compose pull && docker compose up -d upgrade path is safe for minor version bumps (5.x to 5.y). For major version upgrades, Mattermost recommends a sequential upgrade path — you can't jump from v7 to v9 directly; you must go through v8 first. Check the Mattermost upgrade guide before pulling the latest tag on a major version boundary.
Team onboarding. The biggest friction with self-hosted Mattermost is onboarding new team members to the desktop and mobile apps. Unlike Slack where clicking an invite link does everything, Mattermost requires users to download the app and manually enter your server URL. Document this in your onboarding materials: "Download the Mattermost app at mattermost.com/apps. When prompted for server URL, enter https://chat.yourdomain.com." Making this a one-liner in your employee handbook prevents repeated support requests.
Estimated time cost. Plan for roughly 1-2 hours per month for a healthy Mattermost deployment: monthly plugin updates (15 min), checking disk space and backups (10 min), handling occasional user issues (variable), and quarterly version upgrades (30-60 min). It's genuinely manageable for any team with one technically-minded person.
Integrating with your development workflow. Mattermost's GitHub and GitLab plugins post PR, commit, and CI notifications to designated channels. This replaces the common pattern of forwarding GitHub notification emails to a shared alias. Configure a #deployments channel that receives all CI/CD events and a #code-review channel for PR requests. The Jira plugin creates two-way linking between Mattermost conversations and Jira tickets, allowing support conversations to be escalated directly into engineering workflows. These integrations are the primary productivity benefit beyond just replacing Slack — the ability to customize exactly what appears in each channel, without the noise that accumulates in generic Slack workspaces.
Compare team chat platforms on OSSAlt — features, self-hosting guides, and community health side by side.
See open source alternatives to Mattermost on OSSAlt.