Hi there,
as it is hard to find documentation on how to run Matermost behind Traefik v2, I share my configuration here, hoping to make the life of other sys-admins less stressful.
I still have some question. It would be great if they will be answered.
Traefik
Static configuration
global:
checkNewVersion: true
entryPoints:
web:
address: :80
websecure:
address: :443
api:
debug: true
providers:
docker:
exposedByDefault: false
network: bridge_proxy_traefikv2
log:
level: DEBUG
filePath: /var/log/traefik-log.log
accessLog:
filePath: /var/log/traefik-access.log
certificatesResolvers:
tlsChallenge_letsencrypt:
acme:
email: my.secret@gmail.com
storage: /etc/ssl/certs/letsencrypt/acme.json
tlsChallenge: {}
Mattermost
docker-compose file
version: "3"
services:
db:
build: db
container_name: mattermost_db
read_only: true
restart: unless-stopped
volumes:
- ./volumes/db/var/lib/postgresql/data:/var/lib/postgresql/data
- /etc/localtime:/etc/localtime:ro
environment:
- POSTGRES_USER=mmuser
- POSTGRES_PASSWORD=mmuser_password
- POSTGRES_DB=mattermost
# uncomment the following to enable backup
# - AWS_ACCESS_KEY_ID=XXXX
# - AWS_SECRET_ACCESS_KEY=XXXX
# - WALE_S3_PREFIX=s3://BUCKET_NAME/PATH
# - AWS_REGION=us-east-1
networks:
- mattermost
app:
build: app
# change `build:app` to `build:` and uncomment following lines for team edition or change UID/GID
# context: app
# args:
# - edition=team
# - PUID=1000
# - PGID=1000
container_name: mattermost_app
restart: unless-stopped
volumes:
- ./volumes/app/mattermost/config:/mattermost/config:rw
- ./volumes/app/mattermost/data:/mattermost/data:rw
- ./volumes/app/mattermost/logs:/mattermost/logs:rw
- ./volumes/app/mattermost/plugins:/mattermost/plugins:rw
- ./volumes/app/mattermost/client-plugins:/mattermost/client/plugins:rw
- /etc/localtime:/etc/localtime:ro
environment:
# set same as db credentials and dbname
- MM_USERNAME=mmuser
- MM_PASSWORD=mmuser_password
- MM_DBNAME=mattermost
# use the credentials you've set above, in the format:
# MM_SQLSETTINGS_DATASOURCE=postgres://${MM_USERNAME}:${MM_PASSWORD}@db:5432/${MM_DBNAME}?sslmode=disable&connect_timeout=10
- MM_SQLSETTINGS_DATASOURCE=postgres://mmuser:mmuser_password@db:5432/mattermost?sslmode=disable&connect_timeout=10
# in case your config is not in default location
#- MM_CONFIG=/mattermost/config/config.json
networks:
- mattermost
web:
build: web
container_name: mattermost_web
read_only: true
restart: unless-stopped
ports:
#- "80:80"
#- "443:443"
- "80" # http
#- "443" # https
- "40080:80"
- "40443:443"
volumes:
# This directory must have cert files if you want to enable SSL
- ./volumes/web/cert:/cert:ro
- /etc/localtime:/etc/localtime:ro
# Uncomment for SSL
# environment:
# - MATTERMOST_ENABLE_SSL=true
labels:
- traefik.enable=true
- traefik.docker.network=bridge_proxy_traefikv2
#---HTTP ROUTER SECTION
- traefik.http.routers.mattermost.rule=Host(`chat.fairbnb.community`)
#---HTTP SECTION
- traefik.http.routers.mattermost.entrypoints=web
- traefik.http.routers.mattermost.middlewares=mattermost_redirect2https
#---HTTPS ROUTER SECTION
- traefik.http.routers.mattermost_secure.rule=Host(`chat.fairbnb.community`)
#---HTTPS SECTION
- traefik.http.routers.mattermost_secure.entrypoints=websecure
#---TLS SECTION
- traefik.http.routers.mattermost_secure.tls.certresolver=tlsChallenge_letsencrypt
#---MIDDLEWARE SECTION redirect http to https
- traefik.http.middlewares.mattermost_redirect2https.redirectscheme.scheme=https
# - "traefik.http.services.mattermost.LoadBalancer.server.port=8000"
# - "traefik.enable=true"
# - "traefik.docker.network=public-web"
# - "traefik.http.routers.mattermost_http.entryPoints=web"
# - "traefik.http.routers.mattermost_http.rule=Host(`mattermost.google.com`)"
# - "traefik.http.routers.mattermost_https.entryPoints=websecure"
# - "traefik.http.routers.mattermost_https.rule=Host(`mattermost.google.com`)"
# - "traefik.http.routers.mattermost_https.tls.certresolver=basic"
# - "traefik.http.middlewares.https_redirect.redirectscheme.scheme=https"
networks:
- traefik
- mattermost
networks:
traefik:
external:
name: bridge_proxy_traefikv2
mattermost:
external:
name: bridge_mattermost
For additional settings see:
- mattermost-docker/docker-stack-traefik.yml at master · mattermost/mattermost-docker · GitHub
- https://github.com/naturalis/docker-mattermost
- Reddit - Dive into anything
- https://github.com/beeperdeeper089/useful-docker/tree/master/Stacks
If you only activate TLS in Traefik, it sends a minimum header as shown in the response of whoami
whoami response
Hostname: 25a.....
IP: 127.0.0.1
IP: 172.20.0.5
RemoteAddr: 172.20.0.3:38662
GET / HTTP/1.1
Host: whoami.xxx.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.5
Cookie: ajs_user_id=%22wbzw8rfz57dz7gf41mn9z35n4r%22; ajs_group_id=null; ajs_anonymous_id=%2200000000000000000000000000%22
Dnt: 1
Te: trailers
Upgrade-Insecure-Requests: 1
X-Forwarded-For: 185.001.002.003
X-Forwarded-Host: whoami.xxx.com
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: 3eac5....
X-Real-Ip: 185.001.002.003
but there are more option propagated in
- Configure NGINX as a proxy for Mattermost server — Mattermost documentation
- https://docs.mattermost.com/install/config-proxy-apache2.html?highlight=proxy
Appache
recommended configuration
# Set web sockets
RewriteEngine On
RewriteCond %{REQUEST_URI} /api/v[0-9]+/(users/)?websocket [NC,OR]
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC,OR]
RewriteCond %{HTTP:CONNECTION} ^Upgrade$ [NC]
RewriteRule .* ws://127.0.0.1:8065%{REQUEST_URI} [P,QSA,L]
<Location />
Require all granted
ProxyPass http://127.0.0.1:8065/
ProxyPassReverse http://127.0.0.1:8065/
ProxyPassReverseCookieDomain 127.0.0.1 mysubdomain.mydomain.com
</Location>
NGINX
recommended configuration
server {
listen 80;
server_name mattermost.example.com;
location ~ /api/v[0-9]+/(users/)?websocket$ {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
client_max_body_size 50M;
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;
client_body_timeout 60;
send_timeout 300;
lingering_timeout 5;
proxy_connect_timeout 90;
proxy_send_timeout 300;
proxy_read_timeout 90s;
proxy_pass http://backend;
}
location / {
client_max_body_size 50M;
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;
}
}
so what about the following settings. Are the absolutely neccessary or only optional?
proxy_set_header X-Frame-Options SAMEORIGIN;
proxy_pass http://backend;
location ~ /api/v[0-9]+/(users/)?websocket$
- chache settings