..

Definitive guide for self hosting matrix

There are lots of guides on the web about hosting a matrix server but none of them are complete or atleast up to date.

For that reason, I want to make a simple to follow guide for self hosting a matrix server using docker.

Some background

Matrix usernames are very similar to that of an email. Something like @user:example.org. Now, if your TLD is already occupied, it cannot be used to host the synapse server. For that reason, we will host it on a subdomain and still use TLD.

Two important things to consider.

Note: For the rest of the guide, we will use those addresses (hcrypt.net and matrix.hcrypt.net) in the configuration.

For those unaware, federation is how other servers talk to each other so that you can join any public room

The next thing is that for the federation to work, we need something called as delegate.

Delegation is a Matrix feature allowing a homeserver admin to retain a server_name of example.com so that user IDs, room aliases, etc continue to look like *:example.com, whilst having federation traffic routed to a different server and/or port (e.g. synapse.example.com:443).

For that, we want https://hcrypt.net/.well-known/matrix/server to respond with something like this:

{
    "m.server": "matrix.hcrypt.net:443"
}

We can add this using a reverse proxy such as nginx or caddy.

Configure server

First, we need to generate homeserver.yaml config file. For that, create a directory:

mkdir matrix
cd matrix

After that, generate the config:

docker run -it --rm -v "./data:/data" \
    -e SYNAPSE_SERVER_NAME=hcrypt.net -e SYNAPSE_REPORT_STATS=no \
    matrixdotorg/synapse:latest generate

We won’t be changing it because the default config is good enough. We will stick to sqlite as our database because I think it’s very solid even for heavy production use.

After that, in the same folder, create element-config.json and paste this:

{
    "default_server_name": "hcrypt.net",
    "default_server_config": {
        "m.homeserver": {
            "base_url": "https://matrix.hcrypt.net"
        },
        "m.identity_server": {
            "base_url": "https://vector.im"
        }
    },
    "uisi_autorageshake_app": "element-auto-uisi",
    "show_labs_settings": true,
    "room_directory": {
        "servers": ["matrix.org", "gitter.im"]
    },
    "enable_presence_by_hs_url": {
        "https://matrix.org": false,
        "https://matrix-client.matrix.org": false
    }
}

We are pretty much done. Now, use the following compose file:

services:
  element:
    image: vectorim/element-web:latest
    container_name: element
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:80"
    volumes:
      - ./matrix/element-config.json:/app/config.json

  synapse:
    image: matrixdotorg/synapse:latest
    container_name: synapse
    restart: unless-stopped
    ports:
      - "127.0.0.1:8008:8008"
      - "127.0.0.1:8448:8448"
    volumes:
     - ./matrix/data:/data

And then spin up the containers:

docker compose up -d

Now, if you are using caddy or nginx or NPM, create the domains accordingly.

Create user

To create the user, we get a shell inside the container:

sudo docker exec -it synapse /bin/bash

And then run:

register_new_matrix_user -c /data/homeserver.yaml

You can now start using matrix! Let’s make sure federation is working.

Federation

Now, we need to create delegation as mentioned in the beginning.

For NPM users, you can paste this in Advanced Settings of your TLD proxy host:

add_header Access-Control-Allow-Origin *;

location /.well-known/matrix/server {
    return 200 '{"m.server": "matrix.hcrypt.net:443"}';
    default_type application/json;
    add_header Access-Control-Allow-Origin *;
}

location /_synapse/metrics{
  try_files $uri = 404;
}

For normal nginx, you can paste the same thing under the server block.

After that, restart the containers and check the federation at https://federationtester.matrix.org (use your server_name for testing). If everything is correct, you should see a success message.