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.
bind_addresses: [‘127.0.0.1’] – leave the ability to connect to Matrix Synapse only via localhost.
names: [client] – we use only local authentication for users.
database: – completely change the section and configure it to work with PostgreSQL.
server_name: “matrix.YOUR-DOMAIN.COM” – the domain of your Matrix Synapse server.
max_upload_size: 100M – limit the maximum size of uploaded files.
enable_registration: false – disable registration for security reasons.
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.
search_all_users: true – allow user search in clients.
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.
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.