The Way to Your Own Cloud (Part 9) – The own Teams chat

Chat, file upload, video conferencing – for anyone wanting to move away from Slack or Microsoft Teams, Mattermost is an excellent open-source alternative.

With Mattermost, you can run a fully featured team communication platform on your own server – keeping chat histories, files, and images private.

Note: In this article, I focus on installing on an Intel/AMD system. Mattermost currently does not provide ARM builds (e.g., for Raspberry Pi) – in that case, you would need to compile it yourself.

Setup

Mattermost uses PostgreSQL by default.

First, create a dedicated database user and database:

sudo -u postgres psql
CREATE USER mmuser WITH PASSWORD '<STRONG-PASSWORD>';

CREATE DATABASE mattermostdb OWNER mmuser;

GRANT ALL PRIVILEGES ON DATABASE mattermostdb TO mmuser;

Create the application’s root directory under /opt/mattermost:

sudo mkdir -p /opt/mattermost

cd /opt/mattermost

For security reasons, it’s recommended to use a random port:

echo $(shuf -i 1024-65535 -n 1)

Now create the docker-compose.yaml file inside the Mattermost directory
(adjust password, domain, and port as needed):

services:
  mattermost:
    image: localhost:5000/mattermost/mattermost-team-edition:latest
    container_name: mattermost
    restart: unless-stopped
    environment:
      - MM_SQLSETTINGS_DRIVERNAME=postgres
      - MM_SQLSETTINGS_DATASOURCE=postgres://mmuser:<STRONG-PASSWORD>@host.docker.internal:5432/mattermostdb?sslmode=disable&connect_timeout=10
      - MM_SERVICESETTINGS_SITEURL=https://<CLOUD-DOMAIN>:<RANDOM-PORT>
    ports:
      - "8065:8065"
    volumes:
      - ./data:/mattermost/data
    extra_hosts:
      - "host.docker.internal:host-gateway"

Before starting the service, load the official Docker image into your local registry:

docker pull mattermost/mattermost-team-edition:latest
docker tag mattermost/mattermost-team-edition:latest localhost:5000/mattermost/mattermost-team-edition:latest
docker push localhost:5000/mattermost/mattermost-team-edition:latest

Now start the service:

docker compose up -d

To make Mattermost accessible from outside, NGINX needs a new configuration under /etc/nginx/sites-available/mattermost:

server {
    listen <RANDOM-PORT> ssl;
    server_name <CLOUD-DOMAIN>;

    ssl_certificate /etc/letsencrypt/live/<CLOUD-DOMAIN>/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/<CLOUD-DOMAIN>/privkey.pem;

    client_max_body_size 100M;

    location / {
        proxy_pass http://localhost:8065;
        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;
    }
}

Activate the configuration and restart NGINX:

sudo ln -s /etc/nginx/sites-available/mattermost /etc/nginx/sites-enabled/
sudo systemctl restart nginx

Open the selected port in the firewall:

sudo ufw allow <RANDOM-PORT>
sudo ufw reload

You can now perform the initial setup via https://<CLOUD-DOMAIN>:<RANDOM-PORT>.

Apps

Mattermost offers free clients for all major operating systems on its homepage: https://mattermost.com/apps/.

Quick & Dirty

DB_PASS='STRONG_PASSWORD'
DOMAIN='cloud.example.com'
PORT=$(shuf -i 1024-65535 -n 1)

sudo -u postgres psql <<EOF
CREATE USER mmuser WITH PASSWORD '$DB_PASS';
CREATE DATABASE mattermostdb OWNER mmuser;
GRANT ALL PRIVILEGES ON DATABASE mattermostdb TO mmuser;
\q
EOF

sudo mkdir -p /opt/mattermost
cd /opt/mattermost

cat <<EOF > docker-compose.yaml
services:
  mattermost:
    image: localhost:5000/mattermost/mattermost-team-edition:latest
    container_name: mattermost
    restart: unless-stopped
    environment:
      - MM_SQLSETTINGS_DRIVERNAME=postgres
      - MM_SQLSETTINGS_DATASOURCE=postgres://mmuser:$DB_PASS@host.docker.internal:5432/mattermostdb?sslmode=disable&connect_timeout=10
      - MM_SERVICESETTINGS_SITEURL=https://$DOMAIN:$PORT
    ports:
      - "8065:8065"
    volumes:
      - ./data:/mattermost/data
    extra_hosts:
      - "host.docker.internal:host-gateway"
EOF

docker pull mattermost/mattermost-team-edition:latest
docker tag mattermost/mattermost-team-edition:latest localhost:5000/mattermost/mattermost-team-edition:latest
docker push localhost:5000/mattermost/mattermost-team-edition:latest

docker compose up -d

sudo tee /etc/nginx/sites-available/mattermost >/dev/null <<EONGX
server {
    listen $PORT ssl;
    server_name $DOMAIN;

    ssl_certificate /etc/letsencrypt/live/$DOMAIN/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/$DOMAIN/privkey.pem;

    client_max_body_size 100M;

    location / {
        proxy_pass http://localhost:8065;
        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;
    }
}
EONGX

sudo ln -sf /etc/nginx/sites-available/mattermost /etc/nginx/sites-enabled/
sudo systemctl restart nginx

sudo ufw allow $PORT
sudo ufw reload

echo "Mattermost is running at: https://$DOMAIN:$PORT"