How to setup Nginx

Hey everyone,

I have a clean installation of Mattermost server up and running with all the default values (I want to learn first and then I will start a clean installation with custom user and password in Postgres for example) now I want to setup Nginx right now the way to access to my Mattermost server is with http://ip:8065 or http://admin.domain.mx:8065 (I already do a DNS A record in my domain) but I want to understand how to setup Nginx and maybe at the end of this process could access to my server by https://admin.domain.mx (HTTPS and with no port :8065) if this is secure.

An extra step, I want to have multiple instances of Mattermost server just like this post Is there a way to deploy multiple instances of Mattermost in one VPS?

Hey,

since you’re using the docker version, this is going to be a bit of work, but basically, all you’d have to do is spin up an additional container and configure it properly and make sure the containers do not interfere with each other.
So if you’re currently running docker-compose -f docker-compose.yml -f docker-compose.without-nginx.yml up -d, you will just have to change this command a bit, but let’s start from the beginning.
If you encounter error messages or problems at one step, let me know before continuing.

For the sake of simplicity, we will assume that the current docker setup you have is the main setup, so this one will contain of three containers:

  • Mattermost application (container-name mattermost)
  • PostgreSQL database (container-name postgres_mattermost)
  • nginx reverse proxy (container-name nginx_mattermost)

Additional domains will just consist of a postgresql and a mattermost containers with separate names.

Disclaimer: I haven’t tested all that, just writing it out of my head, so there’s a chance for fuzziness.

  1. Stop your current environment
    docker-compose -f docker-compose.yml -f docker-compose.without-nginx.yml down

  2. Make sure your system is reachable from the internet on port 80 and admin.domain.mx points to the public IP of your server so we can create the SSL certificates

  3. In your .env file, you will see two configuration options for CERT_PATH and KEY_PATH. We will only need one of them for the multihost setup, so open the file and modify this part of it to look like this:

#CERT_PATH=./volumes/web/cert/cert.pem
#KEY_PATH=./volumes/web/cert/key-no-password.pem
#GITLAB_PKI_CHAIN_PATH=<path_to_your_gitlab_pki>/pki_chain.pem
CERT_PATH=./certs/etc/letsencrypt/
#KEY_PATH=./certs/etc/letsencrypt/live/${DOMAIN}/privkey.pem
  1. Open your docker-compose.nginx.yml file and modify the `volumes:´ section to look like this:
    volumes:
      - ${NGINX_CONFIG_PATH}:/etc/nginx/conf.d:ro
      - ${NGINX_DHPARAMS_FILE}:/dhparams4096.pem
      - ${CERT_PATH}:/certs:ro
      - shared-webroot:/usr/share/nginx/html
  1. Remove the file nginx/conf.d/default.conf and place the following files in this directory instead:
    httpredirect.conf · GitHub
    domain.conf.template · GitHub

Verify that the directory looks like this then:

# ls nginx/conf.d -1
domain.conf.template
httpredirect.conf

Once that’s done, your preparation works are completed and the following steps need to be repeated for every domain you want to host (nginx-wise).

# the name of this application, only letters and numbers, please. The first one will be `mattermost`, this will be your main instance
export APPNAME=mattermost
export DOMAIN=admin.domain.mx

# generate a free Let's Encrypt certificate for this domain
# you will be asked some questions for e-mail addresses and stuff the first time you run it.
# if successful, you should see a respective message at the end telling you that the certificate files
# have been created properly
chmod 755 scripts/issue-certificate.sh
scripts/issue-certificate.sh -d $DOMAIN -o ${PWD}/certs` 

# clone the template to a working configuration, replacing the values
sed -e 's/__APPNAME__/'$APPNAME'/g' -e 's/__DOMAIN__/'$DOMAIN'/g' nginx/conf.d/domain.conf.template > nginx/conf.d/$APPNAME.conf

This should, in theory, be all that’s necessary.
You can now try to start the environment using the following command:

docker-compose -f docker-compose.yml -f docker-compose.nginx.yml up -d

If you encountered errors at some point, please provide the console log (command you typed, message you received) so I can look at it.
Once the first instance is running, we’ll go ahead and create a second one.

About the ‘volumes’ part what I have is this:

volumes:
  - ${NGINX_CONFIG_PATH}:/etc/nginx/conf.d:ro
  - ${NGINX_DHPARAMS_FILE}:/dhparams4096.pem
  - ${CERT_PATH}:/cert.pem:ro
  - ${KEY_PATH}:/key.pem:ro
  - shared-webroot:/usr/share/nginx/html

so I have to remove the - ${KEY_PATH}:/key.pem:ro and for the - ${CERT_PATH} i have to change the last part of cert.pem:ro to /certs:ro

I suposse thats okay so I just copy and paste your changes so I leave it as:

volumes:
  - ${NGINX_CONFIG_PATH}:/etc/nginx/conf.d:ro
  - ${NGINX_DHPARAMS_FILE}:/dhparams4096.pem
  - ${CERT_PATH}:/certs:ro
  - shared-webroot:/usr/share/nginx/html

Yes, that‘s correct.

I’m in this last part

So, the export APPNAME=mattermost and export DOMAIN=admin.domain.mx this where should be replaced? I think the app name and domain should be replaced in the last step right? for the files domain.conf.template?

For the free lets encrypt I should use https://letsencrypt.org/ ?

And after having that files
is this a command? 'cripts/issue-certificate.sh -d $DOMAIN -o ${PWD}/certs (what is the PWD?)

By the way, my hosting provider give me for free https so my current site already have certificate for *.domain.mx so my site is https://domain.mx already so… this help at any chance or do I need another certificate?

Correct, so leave mattermost as it is for now, we will have the main instance called mattermost. And if you want to access your mattermost installation with the name “https://mattermost.mycoolweb.site”, then you would use:

export DOMAIN=mattermost.mycoolweb.site

I don’t think that you’re being asked this question - the script will automatically default to letsencrypt.org, you do not need to do anything manually. When you run the scripts/issue-certificate.sh ... command, this script will automatically create the free let’s encrypt certificate for you and save it to your server.

If you already have a certificate, you can skip the command scripts/issue-certificate.sh ..., but the template’s I created are prepared for the let’s encrypt paths now. Anyways, if you already have the certificates, you should have Base64 encoded .crt or .pem files. Not sure what there names are, but usually, you will have the .key file, the .crt file and an intermediate chain file (sometimes called .chain). You will have to cat the .crt and the .chain (or intermediate) file together into a fullchain.pem file and use the .key as privkey.pem.

So let’s assume you have the three files certificate.crt, certificate.chain and certificate.key, then you would run the following commands (in your docker directory):

mkdir -p certs/etc/letsencrypt/live/$DOMAIN
cat /path/to/your/certificate.crt /path/to/your/certificate.chain > certs/etc/letsencrypt/live/$DOMAIN/fullchain.pem
cp /path/to/your/certificate.key certs/etc/letsencrypt/live/$DOMAIN/privkey.pem

This is not pretty, but it helps to work around the fact that my templates have been prepared for Let’s Encrypt usage.

Sorry for my silly question, it all makes sense there are just a lot of things I’m learning and I fall into these types of questions before I screw it up

I will use your templates I dont want to explore other paths

I cant run this command
image

Ah, sorry - it’s not executable by default.

chmod 755 scripts/issue-certificate.sh

and then try again.

Everything seems to be okay, I got the last msgs about next steps to auto renew the certificate, I want to make sure that I dont need to do anything extra or do I need to follow User Guide — Certbot 1.29.0 documentation

We‘ll be fine for the next 90 days, so let‘s focus on the other things first :slight_smile:

Youre right, thats a future problem lets focus in the other things first

It seems to be working but If I go to admin.domain.mx is not working even if I go to my public ip is not working

image

I just restart and its still not working
image

Please post the output of:

docker ps
docker logs <id-of-nginx-container> | tail -50
docker logs <id-of-mattermost-container> | tail -50

image

You need to replace <id-of-the…> with the actual IDs. Your nginx container is restarting, so we need to see its logs:

docker logs ca57a4f8b3e4 | tail -50

Sorry about that, and I just send you the logs in PM but the error is about BIO_new_file() no such file or directory

Thanks, I will fix that tomorrow (already late here) and will send you updated instructions. Sorry, will test that on my end before I send it again.

Don’t worry, I understand completely, I’ll also send you the logs of the other files that I don’t replace the name so that you have everything complete tomorrow.

Again thank you very much, I really appreciate all your effort, I’m really learning a lot!!

OK, found the error, sorry.
I fixed the template already so the easiest would be if you run these steps now:

export APPNAME=mattermost
export DOMAIN=admin.yourdomain.mx
docker-compose -f docker-compose.yml -f docker-compose.nginx.yml down
sed -i -e 's!^CERT_PATH.*!CERT_PATH=./certs/etc/letsencrypt/!' .env
cd nginx/conf.d
rm $APPNAME.conf
rm domain.conf.template
wget https://gist.githubusercontent.com/anx-ag/64ed6712f3a545bcf0aa9fd03cc41e2c/raw/78edf25673cccf3c443ebd967c5eaec6067e7524/domain.conf.template
sed -e 's/__APPNAME__/'$APPNAME'/g' -e 's/__DOMAIN__/'$DOMAIN'/g' domain.conf.template > $APPNAME.conf
cd ../..
docker-compose -f docker-compose.yml -f docker-compose.nginx.yml up -d