Install Mattermost on VPS: Self-Hosted Team Chat
Mattermost is an open-source team messaging platform that serves as a self-hosted alternative to Slack. It provides channels, direct messages, threads, file sharing, webhooks, and bot integrations — with one key advantage: all your data lives on your own VPS, never on a third-party server.
This guide walks through installing Mattermost on an Ubuntu/Debian VPS using PostgreSQL as the database backend and Nginx as a reverse proxy with SSL from Let's Encrypt.
Mattermost vs Slack Comparison
| Feature | Mattermost (Self-Hosted) | Slack (Cloud) |
|---|---|---|
| Cost | Free (VPS cost only) | $8–15/user/month |
| Data Privacy | Data on your own server | Data on Slack's cloud |
| Message History | Unlimited | Limited on Free plan |
| Customization | Fully customizable | Plan-limited |
| RAM Required | 2GB minimum | N/A (managed) |
System Requirements
- VPS running Ubuntu 22.04/24.04 or Debian 12 — at least 2GB RAM (4GB recommended)
- 2+ CPU cores
- 20GB+ disk space (for database and file attachments)
- A domain name pointed to your VPS IP address
- Ports 80 and 443 open in your firewall
Step 1 — Install PostgreSQL
Mattermost supports both MySQL and PostgreSQL, but the development team recommends PostgreSQL for better performance and stability.
# Update package list
sudo apt update && sudo apt upgrade -y
# Install PostgreSQL
sudo apt install -y postgresql postgresql-contrib
# Enable and start PostgreSQL
sudo systemctl enable --now postgresql
# Create a database user and database for Mattermost
sudo -u postgres psql <<EOF
CREATE USER mmuser WITH PASSWORD 'mmuser_password_change_this';
CREATE DATABASE mattermost WITH OWNER mmuser ENCODING 'UTF8' LC_COLLATE='en_US.UTF-8' LC_CTYPE='en_US.UTF-8' TEMPLATE=template0;
GRANT ALL PRIVILEGES ON DATABASE mattermost TO mmuser;
EOF
mmuser_password_change_this with a strong random password of at least 20 characters.Step 2 — Download and Install Mattermost
# Download Mattermost Team Edition (free)
cd /tmp
wget https://releases.mattermost.com/10.1.0/mattermost-10.1.0-linux-amd64.tar.gz
# Extract and move to /opt
tar -xzf mattermost-10.1.0-linux-amd64.tar.gz
sudo mv mattermost /opt/mattermost
# Create data directory for file attachments
sudo mkdir -p /opt/mattermost/data
# Create a dedicated system user (never run as root)
sudo useradd --system --user-group mattermost
sudo chown -R mattermost:mattermost /opt/mattermost
sudo chmod -R g+w /opt/mattermost
Step 3 — Configure Mattermost
sudo nano /opt/mattermost/config/config.json
Find and update the "SqlSettings" section:
"SqlSettings": {
"DriverName": "postgres",
"DataSource": "postgres://mmuser:mmuser_password_change_this@localhost/mattermost?sslmode=disable&connect_timeout=10",
...
}
And the "ServiceSettings" section:
"ServiceSettings": {
"SiteURL": "https://chat.yourdomain.com",
"ListenAddress": ":8065",
...
}
Step 4 — Create a systemd Service
sudo nano /etc/systemd/system/mattermost.service
[Unit]
Description=Mattermost Team Chat
After=network.target postgresql.service
[Service]
Type=notify
ExecStart=/opt/mattermost/bin/mattermost
TimeoutStartSec=3600
KillMode=mixed
Restart=always
RestartSec=10
WorkingDirectory=/opt/mattermost
User=mattermost
Group=mattermost
LimitNOFILE=49152
[Install]
WantedBy=multi-user.target
# Reload systemd and start Mattermost
sudo systemctl daemon-reload
sudo systemctl enable --now mattermost
# Check status
sudo systemctl status mattermost
Step 5 — Configure Nginx Reverse Proxy
sudo apt install -y nginx
sudo nano /etc/nginx/sites-available/mattermost
upstream backend {
server localhost:8065;
keepalive 32;
}
server {
listen 80;
server_name chat.yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name chat.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/chat.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/chat.yourdomain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
location ~ /api/v[0-9]+/(users/)?websocket$ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 600s;
}
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 50M;
}
}
sudo ln -s /etc/nginx/sites-available/mattermost /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
Step 6 — Obtain SSL Certificate
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d chat.yourdomain.com
sudo certbot renew --dry-run
sudo systemctl reload nginx
Step 7 — Create Your First Admin Account
Open https://chat.yourdomain.com in your browser:
- Click Create Account
- Enter your email and password — the first account automatically becomes System Admin
- Create your first team and invite members
- Go to System Console → Site Configuration for additional settings
Verify Mattermost Is Working Correctly
# Check service status
sudo systemctl status mattermost
# View recent logs
sudo journalctl -u mattermost -n 50 --no-pager
# Test the API endpoint
curl -s http://localhost:8065/api/v4/system/ping | python3 -m json.tool
# Check database migration status
sudo -u mattermost /opt/mattermost/bin/mattermost db migrate
# Verify Nginx config
sudo nginx -t && sudo systemctl status nginx
curl localhost:8065/api/v4/system/ping should return {"status":"OK"}. If it doesn't respond, Mattermost hasn't started yet — check logs with journalctl -u mattermost -f.Troubleshooting Common Issues
Error: "Failed to connect to database: pq: password authentication failed"
The password in config.json doesn't match the one set in PostgreSQL. Verify the DataSource string and reset the password if needed.
# Reset the PostgreSQL password
sudo -u postgres psql -c "ALTER USER mmuser WITH PASSWORD 'new_password';"
# Update config.json with the new password
sudo nano /opt/mattermost/config/config.json
sudo systemctl restart mattermost
Error: "address already in use :8065"
Port 8065 is occupied by another process. Identify and stop it before starting Mattermost.
# Find which process is using port 8065
sudo ss -tlnp | grep 8065
sudo lsof -i :8065
# Kill the offending process (replace PID with actual process ID)
sudo kill -9 <PID>
sudo systemctl start mattermost
Error: "WebSocket connection failed" in browser
Nginx is missing the WebSocket Upgrade headers or your firewall is blocking WebSocket connections.
# Check Nginx config has the WebSocket location block
sudo grep -n "websocket" /etc/nginx/sites-available/mattermost
# Check Nginx error log
sudo tail -50 /var/log/nginx/error.log
# Reload after fixing config
sudo nginx -t && sudo systemctl reload nginx
Error: "SiteURL must not be blank" or push notifications not working
The SiteURL in config.json is either empty or set to http://localhost:8065 instead of your actual domain.
# Fix SiteURL in config.json
sudo nano /opt/mattermost/config/config.json
# Change to: "SiteURL": "https://chat.yourdomain.com"
sudo systemctl restart mattermost
Error: File upload fails or "413 Request Entity Too Large"
Nginx's default upload limit is too small. Increase client_max_body_size in the Nginx config and update Mattermost's file size limit too.
# Edit Nginx config
sudo nano /etc/nginx/sites-available/mattermost
# In the location / block: client_max_body_size 100M;
# Update Mattermost file size limit in config.json
# "FileSettings": { "MaxFileSize": 104857600 } # 100MB in bytes
sudo nginx -t && sudo systemctl reload nginx
sudo systemctl restart mattermost
Frequently Asked Questions
How many users does the free Mattermost Team Edition support?
Mattermost Team Edition (free) has no user limit — you can run it for large teams. The differences from Enterprise Edition are advanced features like SSO/SAML, compliance exports, and advanced analytics, none of which are available in the free tier.
How do I upgrade Mattermost to a newer version?
Download the new tarball, stop the service, back up your data, extract the new files over the existing installation (preserving data/ and config/), then restart the service. Always read the release notes first — some versions require database migrations.
How do I back up a Mattermost installation?
Back up two things: (1) the PostgreSQL database with pg_dump mattermost > backup.sql and (2) the /opt/mattermost/data/ directory that stores all file attachments. Run backups daily and store copies off the primary VPS.