Installing and configuring the Matrix Synapse + PostgreSQL + Admin UI + Element WEB server. Ubuntu 20 LTS

Having shoveled a lot of different guides on the net, I did not find a single fully and completely working one. As a result, I will try to debut on Habré with my personal guide for those who are faced with the same task: installing a secure and encrypted messenger on their server.

And so let’s get started.

Installation

First of all, let’s update our system:

apt update
apt upgrade

Install additional dependencies

apt install net-tools python3-dev python3-pip libpq-dev mc aptitude htop apache2-utils lsb-release wget apt-transport-https
pip install psycopg2

Connect matrix.org repositories for Ubuntu/Debian x64 architecture available at https://packages.matrix.org/debian/.

wget -O /usr/share/keyrings/matrix-org-archive-keyring.gpg https://packages.matrix.org/debian/matrix-org-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/matrix-org-archive-keyring.gpg] https://packages.matrix.org/debian/ $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/matrix-org.list
apt update

Install Matrix Synapse

apt install matrix-synapse-py3

During the installation process, do not forget to set the name of our server.

Matrix configuration files are located in /etc/matrix-synapse
I propose to edit it immediately to suit our needs.

vim /etc/matrix-synapse/homeserver.yaml

original file
# Configuration file for Synapse.
#
# This is a YAML file: see [1] for a quick introduction. Note in particular
# that *indentation is important*: all the elements of a list or dictionary
# should have the same indentation.
#
# [1] https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html
#
# For more information on how to configure Synapse, including a complete accounting of
# each option, go to docs/usage/configuration/config_documentation.md or
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html
#
# This is set in /etc/matrix-synapse/conf.d/server_name.yaml for Debian installations.
# server_name: "SERVERNAME"
pid_file: "/var/run/matrix-synapse.pid"
listeners:
  - port: 8008
    tls: false
    type: http
    x_forwarded: true
    bind_addresses: ['::1', '127.0.0.1']
    resources:
      - names: [client, federation]
        compress: false
database:
  name: sqlite3
  args:
    database: /var/lib/matrix-synapse/homeserver.db
log_config: "/etc/matrix-synapse/log.yaml"
media_store_path: /var/lib/matrix-synapse/media
signing_key_path: "/etc/matrix-synapse/homeserver.signing.key"
trusted_key_servers:
  - server_name: "matrix.org"
Edited file
# Configuration file for Synapse.
#
# This is a YAML file: see [1] for a quick introduction. Note in particular
# that *indentation is important*: all the elements of a list or dictionary
# should have the same indentation.
#
# [1] https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html
#
# For more information on how to configure Synapse, including a complete accounting of
# each option, go to docs/usage/configuration/config_documentation.md or
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html
#
# This is set in /etc/matrix-synapse/conf.d/server_name.yaml for Debian installations.
# server_name: "SERVERNAME"
pid_file: "/var/run/matrix-synapse.pid"
listeners:
  - port: 8008
    tls: false
    type: http
    x_forwarded: true
    bind_addresses: ['127.0.0.1']
    resources:
      - names: [client]
        compress: false
database:
  name: psycopg2
  txn_limit: 10000
  args:
    user: matrix
    password: YOUR-MATRIX-DB-USER-PASSWORD
    database: matrix
    host: localhost
    port: 5432
    cp_min: 5
    cp_max: 10
log_config: "/etc/matrix-synapse/log.yaml"
media_store_path: /var/lib/matrix-synapse/media
signing_key_path: "/etc/matrix-synapse/homeserver.signing.key"
trusted_key_servers:
  - server_name: "matrix.YOUR-DOMAIN.COM"
suppress_key_server_warning: true
max_upload_size: 100M
enable_registration: false
registration_shared_secret: "Registration-Shared-Secret"
search_all_users: true
prefer_local_users: true
turn_uris: ["turn:matrix.YOUR-DOMAIN.COM?transport=udp","turn:matrix.YOUR-DOMAIN.COM?transport=tcp"]
turn_shared_secret: "Turn-Shared-Secret"
turn_user_lifetime: 86400000
admin_users:
  - "@admin:matrix.YOUR-DOMAIN.COM"

Let’s take a look at the changes we’ve made.

  1. bind_addresses: [‘127.0.0.1’] – leave the ability to connect to Matrix Synapse only via localhost.

  2. names: [client] – we use only local authentication for users.

  3. database: – completely change the section and configure it to work with PostgreSQL.

  4. server_name: “matrix.YOUR-DOMAIN.COM” – the domain of your Matrix Synapse server.

  5. max_upload_size: 100M – limit the maximum size of uploaded files.

  6. enable_registration: false – disable registration for security reasons.

  7. registration_shared_secret: “Registration-Shared-Secret” – we write a long random value, it’s better to use a generator and generate a key of 32-64 characters.

  8. search_all_users: true – allow user search in clients.

  9. turn_uris: [“turn:matrix.YOUR-DOMAIN.COM?transport=udp”,”turn:matrix.YOUR-DOMAIN.COM?transport=tcp”] – we immediately add settings for the turn server, we will install the server itself later.

  10. turn_shared_secret: “Turn-Shared-Secret” – write a long random value, it’s better to use a generator and generate a key of 32-64 characters.

Install and configure PostgreSQL

apt install postgresql

We will limit PostgreSQL to only the localhost interface, all for the same security reasons.
In the file /etc/postgresql/’YOU-POSTGRE-VERSION-NUMBER’/main/postgresql.conf set the parameter listen_addresses = ‘localhost’

vim /etc/postgresql/12/main/postgresql.conf

Let’s switch to the postgres user and set up the user and database for Matrix Synapse.

su - postgres

createuser matrix

createdb --encoding=UTF8 --locale=C --template=template0 --owner=matrix matrix

psql

postgres=# ALTER USER matrix with PASSWORD 'YOUR-MATRIX-DB-USER-PASSWORD';

postgres=# \q

exit

Now you can enable and start the Matrix Synapse service itself

systemctl enable matrix-synapse

systemctl start matrix-synapse

NGINX proxy and configuring certificates

We need NGINX in order to safely hide all the components of our installation.
We also need certbot to get the Lets Encrypt certificate.

apt install nginx python3-certbot-nginx

Now we will generate 3 certificates that we will need in the future:

certbot --nginx -d element.YOUR-DOMAIN.COM

certbot --nginx -d matrix.YOUR-DOMAIN.COM

certbot --nginx -d matrix-admin.YOUR-DOMAIN.COM

Now let’s configure nginx proxy so that all our services become available from the network.

Comment out include /etc/nginx/sites-enabled/*; in nginx config file

vim /etc/nginx/nginx.conf

Now let’s set up nginx proxy for matrix, matrix-admin and element

vim /etc/nginx/conf.d/matrix.conf

matrix.conf
server {
    listen 80;
        listen [::]:80;
    server_name matrix.YOUR-DOMAIN.COM;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name matrix.YOUR-DOMAIN.COM;

    ssl_certificate /etc/letsencrypt/live/matrix.YOUR-DOMAIN.COM/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/matrix.YOUR-DOMAIN.COM/privkey.pem;

    location ~* ^(/|/_matrix|/_synapse/client) {
        proxy_pass http://localhost:8008;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $host;
        client_max_body_size 100M;
    }
}

server {
    listen 8448 ssl http2 default_server;
    listen [::]:8448 ssl http2 default_server;
    server_name matrix.YOUR-DOMAIN.COM;

    ssl_certificate /etc/letsencrypt/live/matrix.YOUR-DOMAIN.COM/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/matrix.YOUR-DOMAIN.COM/privkey.pem;
    location / {
        proxy_pass http://localhost:8008;
        proxy_set_header X-Forwarded-For $remote_addr;
    }
}

vim /etc/nginx/conf.d/matrix-admin.conf

matrix-admin.conf
server {
    listen 80;
        listen [::]:80;
    server_name matrix-admin.YOUR-DOMAIN.COM;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name matrix-admin.YOUR-DOMAIN.COM;

    ssl_certificate /etc/letsencrypt/live/matrix-admin.YOUR-DOMAIN.COM/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/matrix-admin.YOUR-DOMAIN.COM/privkey.pem;

    location / {
        allow 1.1.1.1; #Allowed IP
        allow 8.8.8.8/24; #Allowed Subnet
        deny all;
        proxy_pass http://localhost:8088/;
        proxy_set_header X-Forwarded-For $remote_addr;
    }
}

vim /etc/nginx/conf.d/element.conf

element.conf
server {
    listen 80;
        listen [::]:80;
    server_name element.YOUR-DOMAIN.COM;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name element.YOUR-DOMAIN.COM;

    ssl_certificate /etc/letsencrypt/live/element.YOUR-DOMAIN.COM/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/element.YOUR-DOMAIN.COM/privkey.pem;

    add_header X-Frame-Options SAMEORIGIN;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header Content-Security-Policy "frame-ancestors 'self'";

    location / {
        proxy_pass http://localhost:8080;
        proxy_set_header X-Forwarded-For $remote_addr;
    }
}

Check the nginx configuration for errors

nginx -t

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

systemctl enable nginx

systemctl restart nginx

Now our Matrix Synapse is up and running for text messaging and file sharing.
Let’s create the first user from the command line and make it an admin.

systemctl restart matrix-synapse

register_new_matrix_user -c /etc/matrix-synapse/homeserver.yaml http://localhost:8008

Now let’s install and configure coturn for video and audio calls

apt install coturn

Set up coturn. Uncomment and install the following settings:

vim /etc/turnserver.conf

turnserver.conf
listening-port=3478
fingerprint
use-auth-secret
static-auth-secret=Turn-Shared-Secret #Мы еге генерировали ранее во время настройки Matrix Synapse
realm=matrix.YOUR-DOMAIN.COM
# consider whether you want to limit the quota of relayed streams per user (or total) to avoid risk of DoS.
user-quota=100 # 4 streams per video call, so 100 streams = 25 simultaneous relayed calls per user.
total-quota=1200
no-tcp-relay # VoIP traffic is all UDP. There is no reason to let users connect to arbitrary TCP endpoints via the relay.
syslog
no-multicast-peers

In the /etc/default/coturn file, uncomment the #TURNSERVER_ENABLED=1 line, if the line is commented out, the TURN server will not start.

vim /etc/default/coturn

systemctl enable coturn

systemctl start coturn

Install Element web based on docker container

For this we need docker.

apt install docker.io docker-compose

Now let’s prepare config.json for our Element WEB for minimal customization: we will immediately write down the address of our Matrix Synapse server and disable the unnecessary. We will use only local authentication.

mkdir /opt/element-web

cd /opt/element-web

vim /opt/element-web/config.json

config.json
{
    "default_server_config": {
        "m.homeserver": {
            "base_url": "https://matrix.YOUR-DOMAIN.COM",
            "server_name": "matrix.YOUR-DOMAIN.COM"
        },
        "m.identity_server": {
            "base_url": "https://vector.im"
        }
    },
    "disable_custom_urls": true,
    "disable_guests": true,
    "disable_login_language_selector": false,
    "disable_3pid_login": true,
    "brand": "Element",
    "integrations_ui_url": "https://scalar.vector.im/",
    "integrations_rest_url": "https://scalar.vector.im/api",
    "integrations_widgets_urls": [
        "https://scalar.vector.im/_matrix/integrations/v1",
        "https://scalar.vector.im/api",
        "https://scalar-staging.vector.im/_matrix/integrations/v1",
        "https://scalar-staging.vector.im/api",
        "https://scalar-staging.riot.im/scalar/api"
    ],
    "bug_report_endpoint_url": "https://element.io/bugreports/submit",
    "uisi_autorageshake_app": "element-auto-uisi",
    "default_country_code": "GB",
    "show_labs_settings": false,
    "features": {},
    "default_federate": false,
    "default_theme": "light",
    "room_directory": {
        "servers": ["YOUR-DOMAIN.COM"]
    },
    "enable_presence_by_hs_url": {
        "https://matrix.YOUR-DOMAIN.COM": true
    },
    "terms_and_conditions_links": [
        {
            "url": "https://element.io/privacy",
            "text": "Privacy Policy"
        },
        {
            "url": "https://element.io/cookie-policy",
            "text": "Cookie Policy"
        }
    ],
    "privacy_policy_url": "https://element.io/cookie-policy"
}

It’s time to create and run the Element WEB docker container.

docker run -d --name element-web --restart always -p 127.0.0.1:8080:80 -v /opt/element-web/config.json:/app/config.json vectorim/element-web:latest

Synapse-admin installation

First we need to go to the /opt folder and clone the git repository. We will assemble the container ourselves for the same minimal customization.

cd /opt

git clone https://github.com/Awesome-Technologies/synapse-admin.git

Now let’s make the necessary settings in docker-compose.yml

vim /opt/synapse-admin/docker-compose.yml

docker-compose
version: "3"

services:
  synapse-admin:
    container_name: synapse-admin
    hostname: synapse-admin
    #image: awesometechnologies/synapse-admin:latest
    build:
     context: .

    # to use the docker-compose as standalone without a local repo clone,
    # replace the context definition with this:
    # context: https://github.com/Awesome-Technologies/synapse-admin.git

     args:
    # if you're building on an architecture other than amd64, make sure
    # to define a maximum ram for node. otherwise the build will fail.
    #   - NODE_OPTIONS="--max_old_space_size=1024"
    # default is .
    #   - PUBLIC_URL=/synapse-admin
    # You can use a fixed homeserver, so that the user can no longer
    # define it himself
       - REACT_APP_SERVER=https://matrix.YOUR-DOMAIN.COM
    ports:
      - "127.0.0.1:8088:80"
    restart: unless-stopped

Now let’s build our container.

cd /opt/synapse-admin/

docker-compose up -d

If you are afraid of a warning message, do not pay attention, in my case this in no way affected the performance of the admin panel.

Let’s check what we got

https://matrix.YOUR-DOMAIN.COM

https://matrix-admin.YOUR-DOMAIN.COM

https://element.YOUR-DOMAIN.COM

Conclusion

This guide has been tested on Ubuntu 20 LTS and Ubuntu 22 LTS.

This is my debut on Habré, so please do not judge strictly.

I hope this guide will help someone with saving time and will be useful.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *