Install Matrix and Element with Your Domain, and Use Nginx to Multiplex Port 443

This tutorial uses the Ubuntu 20.04 system. It is recommended to use the Ubuntu operating system with version 20.04 or higher.

This guide will help you set up Matrix (Synapse) and Element with your domain using Docker and Nginx. Follow these steps to create the necessary directories, set up PostgreSQL, configure Synapse, and integrate Element.

Install Docker

Update the package index and install necessary dependencies to add a new HTTPS repository:

apt update

apt install apt-transport-https ca-certificates curl gnupg-agent software-properties-common

Import the GPG key for the repository:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

Add the Docker APT repository to the system:

add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

Install the latest version of Docker:

apt update

apt install docker-ce docker-ce-cli containerd.io

Prevent Docker from being automatically updated:

apt-mark hold docker-ce

Create Data Directories

Create directories for Synapse and PostgreSQL data.

mkdir -p /data/synapse/data
mkdir -p /data/synapse/postgres

Set Up PostgreSQL

Use PostgreSQL 12.5 with the postgres:12.5-alpine image. Pull the image and initialize the PostgreSQL database, mounting the volume to the directory created earlier.

docker run --name postgres12 -v /data/synapse/postgres:/var/lib/postgresql/data -e POSTGRES_PASSWORD=[PostgreSQL_PASSWORD] -d postgres:12.5-alpine

Create a Synapse user for database connection.

docker exec -it postgres12 createuser -U postgres --pwprompt synapse_user

Enter PostgreSQL:

docker exec -it postgres12 psql -U postgres

Create a Synapse database:

CREATE DATABASE synapse
 ENCODING 'UTF8'
 LC_COLLATE='C'
 LC_CTYPE='C'
 template=template0
 OWNER synapse_user;

Modify PostgreSQL Configuration

Edit the pg_hba.conf file to update the authentication methods.

vim /data/synapse/postgres/pg_hba.conf

Add the following configurations:

local   all    all    trust
host    all    all    127.0.0.1/32    trust
host    all    all    ::1/128    trust
local   replication    all    trust
host    replication    all  127.0.0.1/32  trust
host    replication    all    ::1/128    trust
host    all    all     all    md5

Set Up Synapse

Pull the Synapse Docker image and generate the configuration files:

docker run -it --rm \
    -v /data/synapse/data:/data \
    -e SYNAPSE_SERVER_NAME=[your_matrix_domain_name] \
    -e SYNAPSE_REPORT_STATS=yes \
    matrixdotorg/synapse:latest generate

Edit the homeserver.yaml configuration file:

vim /data/synapse/data/homeserver.yaml

Update the configuration as follows:

server_name: "[your_matrix_domain_name]"
pid_file: /data/homeserver.pid
listeners:
  - port: 8008
    tls: false
    type: http
    x_forwarded: true
    resources:
      - names: [client, federation]
        compress: false
database:
  name: psycopg2
  args:
    user: synapse_user
    password: [your_postgreSQL_password]
    database: synapse
    host: db
    cp_min: 5
    cp_max: 10
log_config: "/data/[your_matrix_domain_name].log.config"
media_store_path: /data/media_store
registration_shared_secret: "[auto_generated]"
report_stats: true
macaroon_secret_key: "[auto_generated]"
form_secret: "[auto_generated]"
signing_key_path: "/data/[your_matrix_domain_name].signing.key"
trusted_key_servers:
  - server_name: "matrix.org"

Docker Compose Configuration

Create and edit the docker-compose.yml file:

vim /data/synapse/docker-compose.yml

Add the following content:

version: '3'
services:
  db:
    restart: always
    image: postgres:12.5-alpine
    shm_size: 1024mb
    networks:
      - internal_network
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "postgres"]
    volumes:
      - ./postgres:/var/lib/postgresql/data

  synapse:
    build: .
    image: matrixdotorg/synapse
    restart: always
    ports:
      - "127.0.0.1:8008:8008"
    depends_on:
      - db
    networks:
      - external_network
      - internal_network
    volumes:
      - ./data:/data

  element-web:
    image: vectorim/element-web
    container_name: "matrix_element-web"
    restart: unless-stopped
    ports:
      - '8009:80'
    networks:
      - external_network
      - internal_network

networks:
  external_network:
  internal_network:
    internal: true

Nginx Configuration

Edit Main Nginx Configuration

Edit the Nginx configuration file to enable SSL pre-read.

vim /etc/nginx/nginx.conf

Add the following at the end:

stream {
    map $ssl_preread_server_name $name {
        [your_matrix_domain_name] domain1;
        [your_element_domain_name] domain2;
    }
    upstream domain1 {
        server 127.0.0.1:18008;
    }
    upstream domain2 {
        server 127.0.0.1:18009;
    }
    server {
        listen 443 reuseport;
        proxy_pass $name;
        ssl_preread on;
    }
}

Matrix Nginx Configuration

Create and edit the Nginx site configuration for Matrix:

vim /etc/nginx/sites-enabled/[your_matrix_domain_name]

Add the following content:

server {
    listen 18008 ssl;
    server_name [your_matrix_domain_name];
    ssl_certificate /etc/nginx/certs/[your_matrix_domain_name].pem;
    ssl_certificate_key /etc/nginx/certs/[your_matrix_domain_name].key;
    location / {
      proxy_pass http://127.0.0.1:8008/;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Element Nginx Configuration

Create and edit the Nginx site configuration for Element:

vim /etc/nginx/sites-enabled/[your_element_domain_name]

Add the following content:

server {
    listen 18009 ssl;
    server_name [your_element_domain_name];
    ssl_certificate /etc/nginx/certs/[your_element_domain_name].pem;
    ssl_certificate_key /etc/nginx/certs/[your_element_domain_name].key;
    location / {
      proxy_pass http://127.0.0.1:8009/;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Create Symbolic Links

Create symbolic links for the Nginx configurations:

ln -s /etc/nginx/sites-available/[your_matrix_domain_name] /etc/nginx/sites-enabled/

ln -s /etc/nginx/sites-available/[your_element_domain_name] /etc/nginx/sites-enabled/

Test and Reload Nginx

Check the Nginx configuration for syntax errors and reload it:

nginx -t
nginx -s reload

Start Synapse and Element

Navigate to the Synapse directory and start the services using Docker Compose:

cd /data/synapse
docker-compose up -d

docker-compose restart
docker-compose down

Create a New User (Optional)

To create a new user if registration is not open to the public:

docker exec -it synapse-synapse-1 bash

register_new_matrix_user -c /data/homeserver.yaml https://[your_matrix_domain_name]

Following these steps will set up your Matrix (Synapse) and Element environment. Ensure to replace placeholders with your actual domain names, passwords, and other specific configurations.