Matrix Server Install via Docker

I've been asked a few times to setup a Matrix server as a potential means of communication with me vs Email or Telegram.   I finally had time to sit down, read through the docs and actually give it a run a couple of times.  I'm glad I was able to go through it, as I found a couple of potential "gotchas" for those wanting to do this project.

Starting Needs

  • A server that you'll make accessible from the internet.  (Home Server of a VPS like with Digital Ocean).
  • Docker, Docker-Comoose, and NGinX Proxy Manager installed (don't worry, we'll go through this as well).
  • Finally, a desire to understand the various and multitudinous settings available in the Matrix server configuration file.


I'll be using a Digital Ocean, $10 / month server (aka a droplet).  The server seems more than suitable for my needs in this case, and seems to handle the Matrix server with no issue.

Feel free to use a home server, and setup NGinX Proxy Manager (NPM) to route traffic from the internet through to the server on your home LAN if you wish.  The process will be the same, and only the routing to NPM will vary slightly.

Install Docker and Docker-Compose

I make a script of it, then run the script to install these more quickly as I generally work on an LTS (Long Term Support) version of Ubuntu.

sudo apt update
sudo apt install apt-transport-https ca-certificates curl software-properties-common -y
curl -fsSL | sudo apt-key add -

## for ubuntu 18.04
sudo add-apt-repository "deb [arch=amd64] bionic stable"

## for ubuntu 20.04
sudo add-apt-repository "deb [arch=amd64] focal stable"

sudo apt update
apt-cache policy docker-ce
sudo apt install docker-ce -y

## now set user as part of docker group
sudo usermod -aG docker ${USER}

## install docker-compose
sudo apt install docker-compose -y

Copy the text above into a new file. Take out the 18.04, or 20.04 line based on the version of Ubuntu you are using.

Then save the file as

This will make it simpler if you will be setting up multiple physical servers or machines that you want to run docker on.

Now just run the script with the command:

. ./

Enter your super user (sudo) password if prompted.

After the installation completes, you'll want to log out and back in, ro reboot your machine.

Install NGinX Proxy Manager

Create a new folder on the server, and simply call it something like "npm".

mkdir npm

Now, change into this directory, and create an empty file called docker-compose.yml.

cd npm

nano docker-compose.yml

Now, copy the following code into the file.

version: '3'
    image: 'jc21/nginx-proxy-manager:latest'
      - '80:80'
      - '81:81'
      - '443:443'
      DB_MYSQL_HOST: "db"
      DB_MYSQL_PORT: 3306
      DB_MYSQL_USER: "<a user name you want>"
      DB_MYSQL_PASSWORD: "<a password you want>"
      DB_MYSQL_NAME: "npm"
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
    image: 'jc21/mariadb-aria:10.4'
      MYSQL_ROOT_PASSWORD: '<a long, strong password you want>'
      MYSQL_DATABASE: 'npm'
      MYSQL_USER: '<the same username as above>'
      MYSQL_PASSWORD: '<the same password as in the section above>'
      - ./data/mysql:/var/lib/mysql

You can paste the code in the terminal using CTRL+Shift+V in Linux, or CMD+V with MacOS.

You need to change the items with "<>" on them to some actual data.   Make sure the username in each section matches.  Make sure the password (not the root password) in each section matches.  Finally, create a very strong root password.

Save the file with CTRL+O, then press Enter / Return to save.  Press CTRL+X to exit the nano editor.

Now, you can install and start NGinX Proxy Manager by putting the command:

docker-compose  up -d

int the terminal.

If everything goes well, you can go to the IP of your server on port 81and you'll see the NPM login screen.


Now enter the default username and password to login.

default user:
default password: changeme

Once logged in, change the default user email, then change the default password to a strong password.

Save your changes, log out and back in.

Let's Install Matrix!

We are going to head over to and use their base instructions to get started with our install.

Generate the Initial Configuration File

First, we need to use our intended docker image to create an initial configuration file.  The command below will do this for you, but you need to have your intended URL for your Matrix server in mind.  Ideally, you'll have already setup an A record to point your URL to the public IP that will provided access via NGinX Proxy Manager to your server.

Simply replace the text "<your-intended-url>" with the actual URL.  In my case I used

docker run -it --rm --mount type=volume,src=synapse-data,dst=/data -e SYNAPSE_SERVER_NAME=<your-intended-url> -e SYNAPSE_REPORT_STATS=no matrixdotorg/synapse:latest generate

Once you run this command, the configuration file will be generated.  Usually you can find this file in /var/lib/docker/volumes/synapse-data/_data/homeserver.yaml.

Inside that file, we need to set several settings for the base server to be useful.

  1. Setup the SMTP info for Email (NOTE TLS above v1 will not function right now - waiting on an update)
  2. Setup to allow Registration, can't register through the UI without this adn without email setup.
  3. You also need a client to actually use this, but you can use, or a native client.

Searching with nano

If you'll be using the text editor nano, it's worth mentioning thta you can search by pressing CTRL+W and typing part of the word / phrase you want to search.  This is an exact match search as far as I can tell, so when typing phrases it must be exact.  

You can search for the same phrase again by pressing CTRL+W, then just pressing Enter to search for the previously searched word or phrase.

Server Name

Near the top of the homeserver.yaml fild you'll want to ensure that the server_name value is set your servers FQDN (full URL).  For instance, mine says "".

Allow Registration

Open the homeserver.yaml file and locate the ## Registration ## section.  At the bottom of that section remove the hastag / pound sign in front of the line enable_registration: true.

Setting this allows users to register for your Matrix server instance. You can disable this setting by putting the hashtag / pound sign back in place, or by setting the value to false.  This turns off user registration, and makes the server an Invite only server.  With Invite only there are other settings you'll need / want to set in order to identify which users can invite someone to your instance.

SMTP Setup

Once more, if your email smtp server / provider uses StartTLS, and it is TLS version 1.1 or later, you will not (at the time of writing) be able to utilize the email portion of Registration.  There is supposed to be a fix coming for this, but in my research it appears it's been coming for nearly a year now.

If, however your email server uses no encryption, or SSL / TLS 1.0, then you can setup SMTP to send email for registration, message notifications, etc.

Search for "SMTP" and find your way to the section titled "Configuration for sending emails from Synapse."  (HINT: I had to use CTRL+W 2 times to get there searching for SMTP).

In this section you'll need to uncomment the following lines:

smtp_port: 587 - and change the port to the correct port for you SMTP server or provider.

smtp_user: ""

smtp_pass: "your-email-users-password"

require_transport_security: true - This one you should only use if your server uses StartTLS, and you should understand the comment above this line clearly.

Finally, you can uncomment some of the other options below these settings if you like. Mostly they deal with notifications to your users.  Keep in mind that should you find that email is not working properly, and you decide to disable it, you need to disable all of the fields related to email including notification settings.

After making all of the settings changes you need, save with CTRL+O, press Enter / Return to confirm, then use CTRL+X to exit.

Start our Server

Now we can start and run our server with the command below.  Give it a few minutes to start the server completely. Note, you can change the left side of the -p (ports mapping) options to be any ports you are not currently using on your server as long as it's not mapped to port 80, 81, or 443 (as those are in use by NGinX Proxy Manager).

docker run -d --name synapse --mount type=volume,src=synapse-data,dst=/data -p 8008:8008 -p 4143:443 matrixdotorg/synapse:latest

As you are waiting you can use the command:

docker logs synapse

To see what's happening with the startup process, and monitor for any potential errors that may need to be fixed.

Once the loggins activity has settled, or a couple of minutes have passed try to access your server by its IP and port.  In my case I went to the public IP of my Digital Ocean droplet on port 8008, and was able to see the Matrix Server screen like below.

If you see this, then you are on your way.  As stated before, we need a client to actually chat through our server, but we'll get to that.  First let's setup our URL routing for our server.

Setup a Host in NGinX Proxy Manager

You should be able to access NGinX Proxy Manager by going to your URL on port 81, like and log into NPM.

We want to add a new Host, so click the Add Host button. In the form, enter the URL of your matrix site.  For me, I entered "".

Next, you'll want to enter the IP of the docker0 interface.  You can find this in the terminal by typing the command:

ip addr show docker0

Make note of the IPv4 address (usually, but not always, so double check).

Enter that IP address into the IP field.  Next enter 8008 (or the port that you mapped to the container port 80) in the port field.

Enable the settings for Cache Assets, Block Common Explits, and Websockets Support.  Then Save.

We can now click on our URL in the grid, to open a new tab and make sure we see the Matrix Server site page again.  NOTE: This is not yet SSL encrypted...we are just testing to ensure it's proxying as expected.  If you don't see your server page, double check all of your settings.  

Once you have the server page showing up, we need to get an SSL certificate to encrypt access to our server.

Since we mapped port 4143 on the host to 443 on the container, we need to make an entry into the "Custom Locations" tab in NPM.  Click the 3 vertical dot icon at the right end of your entry, and select 'Edit'.  Now move to the "Custom Locations" tab, and click the 'Add Location' button.

In the form, enter the same URL in the "Definte Location" field, then choose https from the "Scheme" field.  Now enter the same IP (probably into the IP Address field, and the port 4143 (or whatever port you chose for the host) into the port field.

Now move to the "SSL" tab, and select 'Request a New Certificate' from the "SSL Certificate" drop-down.

Enable "Force SSL", ensure your email is entered for the TOS of LetsEncrypt, and enable the I Agree toggle.  Click 'Save' and wait for a few seconds.  If the pop-up for closes with no errors you should be set.

Now click on your URL in the grid row again, adn it should open a new tab showing your Matrix server page, but now you should see the SSL lock icon in the address bar.  If you get an error, check  your settings, and try again.

Register an Account on your Server

Feel free to use the Element app, or the Element web app (  I am using a native client called Fractal.  Whatever you choose, you need to select to Create an Account.  Then you need to make sure to change the server to your server instance.  

Enter a Username and Password (and email if you've setup email), and register your account.

If you are taken to a confirmation screen, you should be set, and sent right to your server.  If not, and you come back to the Create an Account form, then something may be set incorrectly on the server (and I would guess it's email).

Once you've registered, you can create a room and start chatting (assuming you haven't disabled thos capabilities in your settings for non-admins).  

That's right, you are not an admin yet on your own server (most likely).  So we need to remedy thtat.

Make yourself and Admin

Time to head back to your terminal.  We need to do some SQLite magic here and make our user an Admin.  It's not hard, don't worry.

First, make sure you have SQLite3 installed.   Type sqlite3 into your terminal.  If it says its an unknown command or not found, then you need to install it. If you're using Debian or Ubuntu or one of their variants, you can install it with

sudo apt install sqlite3

Once you know you have sqlite3 installed and ready, we need to go back to the folder /var/lib/docker/volumes/synapse-data/_data/

cd /var/lib/docker/volumes/synapse-data/_data/

Now we need to get into the sqlite shell for the file homeserver.db.  So we use the command

sqlite3 homeserver.db

Now we'll search for our user in the database with the command:

SELECT * FROM users;

and make note of our username.  I will look like


Copy it by highlighting it, and useing CTRL+Shift+C, then use the command

UPDATE users SET admin=1 WHERE name='@your-user:your-server-url';

You can paste the user into the line with CTRL+Shift+V.  

Now re-run the command to search, and you should see that a 0 is now a 1 out to the right.

SELECT * FROM users;

Should show something lke


Finally type .quit and press Enter to exit the SQLite shell.

Now you can go back to your client and you'll be an admin.

You, may now have others register for your instance, and start chatting away! Congratulations!