Hi Tom,
i would recommend to not use the letsencrypt companion because it’s not easier if you’re new to this. The simplest setup would be to run postgres and Mattermost in Docker and nginx & certbot on the host. And you’ll get nginx updates from Ubuntu Security Team. Add an cronjob or systemd timer to renew the certs and you’re done. The companion will just save the cert creation and renewal for the price of Docker socket access (root) and you need to provide your custom nginx template anyway because Mattermost is using websockets and the companion will just setup an config with a reverse proxy.
Don’t forget to change foo.bar
in the compose file, nginx conf and certbot command to your desired domain.
Use this docker-compose file
version: "3"
services:
db:
container_name: postgres_mattermost
image: postgres:alpine
restart: unless-stopped
volumes:
- ./postgres:/var/lib/postgresql/data
- /etc/localtime:/etc/localtime:ro
environment:
POSTGRES_USER: mmuser
POSTGRES_PASSWORD: mmuser_password
POSTGRES_DB: mattermost
app:
depends_on:
- db
container_name: mattermost
image: mattermost/mattermost-team-edition:release-5.21
restart: unless-stopped
volumes:
- ./mattermost/config:/mattermost/config:rw
- ./mattermost/data:/mattermost/data:rw
- ./mattermost/logs:/mattermost/logs:rw
- ./mattermost/plugins:/mattermost/plugins:rw
- ./mattermost/client-plugins:/mattermost/client/plugins:rw
- /etc/localtime:/etc/localtime:ro
environment:
MM_SERVICESETTINGS_SITEURL: https://foo.bar
MM_SQLSETTINGS_DRIVERNAME: postgres
MM_SQLSETTINGS_DATASOURCE: postgres://mmuser:mmuser_password@db:5432/mattermost?sslmode=disable&connect_timeout=10
ports:
- "127.0.0.1:8065:8065"
Don’t forget to change the db username and password in both sections.
Afterwards create the needed folders (inside the folder where the compose file is lying or change the volume mappings)
$ mkdir -p postgres mattermost/{config,data,logs,plugins,client-plugins}
$ sudo chown -R 2000:2000 mattermost
Install nginx-full and certbot on the host and create a cert
$ sudo certbot certonly --standalone -d foo.bar
Drop the following config to /etc/nginx/sites-enabled/mattermost.conf
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 foo.bar;
listen 80;
listen [::]:80;
# ACME-challenge
location ^~ /.well-known/acme-challenge/ {
root /var/www/html;
}
# redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
return 301 https://$host$request_uri;
}
server {
server_name foo.bar;
listen 443 ssl http2;
listen [::]:443 ssl http2;
access_log /var/log/nginx/access.log;
# ssl
ssl_certificate /etc/letsencrypt/live/foo.bar/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/foo.bar/privkey.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
# curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam.pem
#ssl_dhparam /path/to/dhparam.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:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# HSTS (ngx_http_headers_module is required) (63072000 seconds)
add_header Strict-Transport-Security "max-age=63072000" always;
# other security headers (see https://securityheaders.com)
add_header Referrer-Policy 'strict-origin-when-cross-origin';
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options 'nosniff' 'always';
add_header X-Frame-Options 'SAMEORIGIN' 'always';
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
# verify chain of trust of OCSP response using Root CA and Intermediate certs
#ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;
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://localhost:8065;
}
location / {
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;
client_max_body_size 50M;
proxy_set_header Connection "";
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://localhost:8065;
}
}
You can verify the nginx conf with sudo nginx -t
and afterwards restart nginx sudo systemctl restart nginx
. For the autorenewal of the cert put the two snipets to /etc/systemd/system/
as certbot.service
:
[Unit]
Description=certbot renew
After=network.target
[Service]
Type=oneshot
ExecStart=certbot renew
[Install]
WantedBy=multi-user.target
and certbot.timer
:
[Unit]
Description=Run certbot renew
[Timer]
Persistent=true
OnCalendar=*-*-* 5:00:00
Unit=certbot.service
[Install]
WantedBy=timers.target
reload the daemon files and enable it
$ sudo systemctl daemon-reload
$ sudo systemctl enable --now certbot.timer
Spin up the containers and the setup should be up and running. If you want to harden your nginx create the dhparam file and point the ocsp stapling cert setting to the ssl bundle from Ubuntu (probably something like /etc/ssl/certs/ca-certificates.crt
)
Marco