How to Deploy Self-hosted Mattemost Server | Docker Swarm
Prerequisites:
- Linux Server
- Docker installed and swarm mode initiated
- Webserver (example: nginx)
- Mysql8 Database
How to setup mysql8 db:
https://blog.kafana.dev/simple-mysql-8-setup-docker-swarm/
How to setup nginx webserver:
https://blog.kafana.dev/how-to-setup-nginx-docker-swarm/
Mattermost | Docker Swarm
This is an example using docker swarm. I'll use mysql8 database and nginx as a webserver running also in docker swarm, but in separated stacks.
sudo mkdir /webapps
sudo chown $USER:$USER /webapps
cd /webapps
mkdir -p /webapps/mattermost/{Dockerfile-folder,mattermost-data} && cd mattermost/Dockerfile-folder
Create Dockerfile
nano Dockerfile
FROM ubuntu:20.04
RUN apt-get update && apt-get upgrade -y && apt-get install -y \
nano wget curl net-tools procps sudo telnet iputils-ping
ENV DEBIAN_FRONTEND noninteractive
# Create user with sudo privileges
RUN useradd -ms /bin/bash --system --user-group -u 1000 durbok && \
usermod -aG sudo durbok
# New added for disable sudo password
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
VOLUME /opt/mattermost
# Set as default user
USER durbok
RUN mkdir -p /opt/mattermost
RUN sudo chown -R durbok:durbok /opt/mattermost && sudo chmod -R g+w /opt/mattermost
WORKDIR /opt/mattermost
ENV DEBIAN_FRONTEND teletype
CMD ["/opt/mattermost/bin/mattermost"]
I am storing my images in selfhosted app called harbor, but you can use dockerhub or something similar.
docker build harbor.urdomain.com/kafana/mattermost:latest .
docker push harbor.urdomain.com/kafana/mattermost:latest
cd ../
Download mattermost server https://mattermost.com/deploy/?ref=download
wget https://releases.mattermost.com/6.5.0/mattermost-6.5.0-linux-amd64.tar.gz
tar xvf mattermost-6.5.0-linux-amd64.tar.gz
rm mattermost-6.5.0-linux-amd64.tar.gz
mv mattermost mattermost-data/
nano docker-compose.yml
version: "3.7"
services:
prod:
image: harbor.urdomain.com/kafana/mattermost:latest
networks:
- durbok-net
deploy:
placement:
constraints:
- node.role == manager
replicas: 1
restart_policy:
condition: on-failure
volumes:
- ./mattermost-data/mattermost:/opt/mattermost
networks:
durbok-net:
external: true
Edit config.json
nano /mattermost-data/mattermost/config/config.json
Most important is to change:
"ServiceSettings": {
"SiteURL": "https://mattermost.urdomain.com",
"ListenAddress": ":8065",
and
"SqlSettings": {
"DriverName": "mysql",
"DataSource": "mattermost:password@tcp(mysql8_prod:3306)/mattermost?charset=utf8mb4,utf8\u0026writeTimeout=30s",
This part is connection to mysql database which, in my case, is a docker container called mysql8_prod. It can be IP address or AWS RDS endpoint.
Username and database are called mattermost, however you can name yours as you please.
Nginx config
upstream backend {
server mattermost_prod:8065;
keepalive 32;
}
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=mattermost_cache:10m max_size=3g inactive=120m use_temp_path=off;
server {
server_name mattermost.urdomain.com;
location ~ /api/v[0-9]+/(users/)?websocket$ {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
client_max_body_size 150M;
# proxy_set_header Host $http_host;
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_set_header X-Frame-Options SAMEORIGIN;
proxy_buffers 256 16k;
proxy_buffer_size 16k;
client_body_timeout 60;
send_timeout 300;
lingering_timeout 5;
proxy_connect_timeout 90;
proxy_send_timeout 300;
proxy_read_timeout 90s;
proxy_http_version 1.1;
proxy_pass http://backend;
}
location / {
client_max_body_size 150M;
proxy_set_header Connection "";
proxy_set_header Host $http_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_set_header X-Frame-Options SAMEORIGIN;
proxy_buffers 256 16k;
proxy_buffer_size 16k;
proxy_read_timeout 600s;
proxy_cache mattermost_cache;
proxy_cache_revalidate on;
proxy_cache_min_uses 2;
proxy_cache_use_stale timeout;
proxy_cache_lock on;
proxy_http_version 1.1;
proxy_pass http://backend;
}
listen 443 ssl http2;
ssl_certificate /etc/nginx/ssl/ur-ssl.pem;
ssl_certificate_key /etc/nginx/ssl/ur-ssl.key;
# include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
ssl_session_timeout 1d;
# Enable TLS versions (TLSv1.3 is required upcoming HTTP/3 QUIC).
ssl_protocols TLSv1.2 TLSv1.3;
# Enable TLSv1.3's 0-RTT. Use $ssl_early_data when reverse proxying to
# prevent replay attacks.
#
# @see: https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_early_data
ssl_early_data on;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:5m;
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security max-age=15768000;
# OCSP Stapling ---
# fetch OCSP records from URL in ssl_certificate and cache them
# ssl_stapling on;
# ssl_stapling_verify on;
}
server {
if ($host = mattermost.urdomain.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80 default_server;
server_name mattermost.urdomain.com;
return 404; # managed by Certbot
}
docker stack deploy -c docker-compose.yml mattermost
Reload nginx.
Done.