Create a Chat Server Using Matrix Synapse and Element on Ubuntu 22.04
Introduction
Matrix is a set of open APIs for decentralized and end-to-end encrypted communication. It works across a collection of federation servers to deliver Instant messages, Voice over IP (VoIP), and Internet of Things (IoT) communication in real time. It uses homeservers to store the account information and chat history. Federation works like email, which means you can either use a server hosted by somebody or host your Matrix server that provides greater control over your data. The decentralized nature of servers ensures that if one server hosting a chat goes offline, the communication continues on other servers.
Synapse is a popular homeserver implementation of Matrix written in Python and created by the Matrix.org team. This guide will teach you to install Matrix Synapse and Element web client on a Ubuntu 22.04 server.
Prerequisites
- Deploy a Ubuntu 22.04 server with at least 2 GB of RAM and one vCPU core.
- Create a non-root user with sudo privileges.
- Update the server.
- Create subdomains
matrix.example.com
,element.example.com
, andcoturn.example.com
pointing to your server.
1. Configure Firewall
Matrix Synapse needs HTTP and HTTPS ports to work.
Open them using the Uncomplicated Firewall (UFW).
$ sudo ufw allow http
$ sudo ufw allow https
Open port 8448, as required by Matrix.
$ sudo ufw allow 8448
Check the firewall status to confirm.
$ sudo ufw status
2. Install Matrix Synapse
Download and import the GPG key.
$ sudo wget -O /usr/share/keyrings/matrix-org-archive-keyring.gpg https://packages.matrix.org/debian/matrix-org-archive-keyring.gpg
Add the Matrix official APT repository.
$ echo "deb [signed-by=/usr/share/keyrings/matrix-org-archive-keyring.gpg] https://packages.matrix.org/debian/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/matrix-org.list
Update the system repositories list.
$ sudo apt update
Install Matrix Synapse.
$ sudo apt install matrix-synapse-py3
Enter your Matrix domain name during installation as the server name. You can change it later in the /etc/matrix-synapse/conf.d/server_name.yaml
file. Enter N
to stop the reporting of anonymized statistics.
3. Install and Configure PostgreSQL
Synapse supports SQLite database by default which isn't suitable for a production environment because of performance issues.
Install PostgreSQL server.
$ sudo apt install postgresql postgresql-contrib
Log in to the PostgreSQL shell.
$ sudo -su postgres psql
Create a Synapse SQL user.
# CREATE ROLE syanpse LOGIN PASSWORD 'yourpassword`;
Create a Synapse Database.
# CREATE DATABASE synapsedb OWNER synapse LOCALE 'C' ENCODING 'UTF-8' TEMPLATE template0;
Exit the shell.
# exit
4. Install Nginx
Ubuntu 22.04 ships with an older version of Nginx. Add the official Nginx repository to install the latest version.
$ curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
$ echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg arch=amd64] \
http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
sudo tee /etc/apt/sources.list.d/nginx.list
Update the system repository list.
$ sudo apt update
Install Nginx.
$ sudo apt install nginx
Start the Nginx server.
$ sudo systemctl start nginx
5. Install SSL
Issue the following commands to ensure that you have the latest version of snapd
required to install Certbot.
$ sudo snap install core
$ sudo snap refresh core
Install Certbot.
$ sudo snap install --classic certbot
Create a symlink for Certbot to the /usr/bin
directory.
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
Issue the SSL Certificate.
$ sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m name@example.com -d matrix.example.com
Generate a Diffie-Hellman group certificate.
$ sudo openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096
Do a dry run of the SSL renewal process to ensure it works.
$ sudo certbot renew --dry-run
6. Configure Synapse
You can configure Snypase using the /etc/matrix-synapse/homeserver.yaml
file, but you shouldn't use it in a production environment because it gets overwritten during an APT update.
You should configure Synapse by creating files in /etc/matrix-synapse/conf.d/
directory.
Create a database configuration file.
$ sudo nano /etc/matrix-synapse/conf.d/database.yaml
Paste the following lines in the editor. Replace yourpassword
with the database user set in Step 3.
database:
name: psycopg2
args:
user: synapse
password: 'yourpassword'
database: synapsedb
host: localhost
cp_min: 5
cp_max: 10
Save the file by pressing Ctrl+X, then Y.
Create a registration key and store it in the /etc/matrix-synapse/conf.d/registration_shared_secret.key
file.
$ echo "registration_shared_secret: '$(cat /dev/urandom | tr -cd '[:alnum:]' | fold -w 256 | head -n 1)'" | sudo tee /etc/matrix-synapse/conf.d/registration_shared_secret.yaml
Create a new Matrix user. Type yes
to set it as administrator.
$ register_new_matrix_user -c /etc/matrix-synapse/conf.d/registration_shared_secret.yaml http://localhost:8008
Synapse doesn't allow public registration by default. Create a configuration file to enable it.
$ sudo nano /etc/matrix-synapse/conf.d/registration.yaml
Paste the following line.
enable_registration: true
Synapse requires verification for new users. To enable email verification, paste the following lines.
registrations_require_3pid:
- email
email:
smtp_host: mail.example.com
smtp_port: 587
# If mail server has no authentication, skip these 2 lines
smtp_user: 'noreply@example.com'
smtp_pass: 'password'
# Optional, require encryption with STARTTLS
require_transport_security: true
app_name: 'Example Chat' # defines value for %(app)s in notif_from and email subject
notif_from: "%(app)s <noreply@example.com>"
You can disable user verification using the following code.
enable_registration_without_verification: true
Save the file by pressing Ctrl+X, then Y.
Synapse shows the user's online status by default which can cause high CPU usage. To disable the status, create a new configuration file.
$ sudo nano /etc/matrix-synapse/conf.d/presence.yaml
Paste the following lines.
presence:
enabled: false
Save the file by pressing Ctrl+X, then Y.
Restart Synapse to apply the changes.
$ sudo systemctl restart matrix-synapse
7. Configure Nginx
Open the Nginx configuration file.
$ sudo nano /etc/nginx/nginx.conf
Add the following line before the line /etc/nginx/conf.d/*.conf
.
server_names_hash_bucket_size 64;
Save the file by pressing Ctrl+X, then Y.
Create an Nginx configuration file for Synapse.
$ sudo nano /etc/nginx/conf.d/synapse.conf
Paste the following lines.
# enforce HTTPS
server {
# Client port
listen 80;
listen [::]:80;
server_name matrix.example.com;
return 301 https://$host$request_uri;
}
server {
server_name matrix.example.com;
# Client port
listen 443 ssl http2;
listen [::]:443 ssl http2;
# Federation port
listen 8448 ssl http2 default_server;
listen [::]:8448 ssl http2 default_server;
access_log /var/log/nginx/synapse.access.log;
error_log /var/log/nginx/synapse.error.log;
# TLS configuration
ssl_certificate /etc/letsencrypt/live/matrix.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/matrix.example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/matrix.example.com/chain.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
location ~ ^(/_matrix|/_synapse/client) {
proxy_pass http://localhost:8008;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
# Nginx by default only allows file uploads up to 1M in size
# Increase client_max_body_size to match max_upload_size defined in homeserver.yaml
client_max_body_size 50M;
}
}
Save the file by pressing Ctrl+X, then Y.
Verify the configuration file syntax.
$ sudo nginx -t
Restart the Nginx server.
$ sudo systemctl restart nginx
8. Install Coturn
You need to install a Traversal Using Relays around NAT (TURN) server to use video and voice calls.
Install Coturn.
$ sudo apt install coturn
Open the TURN and UDP ports.
$ sudo ufw allow 3478
$ sudo ufw allow 5349
$ sudo ufw allow 49152:65535/udp
Issue an SSL certificate for Coturn.
$ sudo certbot certonly --nginx -d coturn.example.com
Back up the default configuration file.
$ sudo mv /etc/turnserver.conf /etc/turnserver.conf.bak
Generate an authentication secret and store it in the configuration file.
$ echo "static-auth-secret=$(cat /dev/urandom | tr -cd '[:alnum:]' | fold -w 256 | head -n 1)" | sudo tee /etc/turnserver.conf
Open the Coturn configuration file.
$ sudo nano /etc/turnserver.conf
Paste the following lines below the authentication secret.
use-auth-secret
realm=coturn.example.com
cert=/etc/letsencrypt/live/coturn.example.com/fullchain.pem
pkey=/etc/letsencrypt/live/coturn.example.com/privkey.pem
# VoIP is UDP, no need for TCP
no-tcp-relay
# Do not allow traffic to private IP ranges
no-multicast-peers
denied-peer-ip=0.0.0.0-0.255.255.255
denied-peer-ip=10.0.0.0-10.255.255.255
denied-peer-ip=100.64.0.0-100.127.255.255
denied-peer-ip=127.0.0.0-127.255.255.255
denied-peer-ip=169.254.0.0-169.254.255.255
denied-peer-ip=172.16.0.0-172.31.255.255
denied-peer-ip=192.0.0.0-192.0.0.255
denied-peer-ip=192.0.2.0-192.0.2.255
denied-peer-ip=192.88.99.0-192.88.99.255
denied-peer-ip=192.168.0.0-192.168.255.255
denied-peer-ip=198.18.0.0-198.19.255.255
denied-peer-ip=198.51.100.0-198.51.100.255
denied-peer-ip=203.0.113.0-203.0.113.255
denied-peer-ip=240.0.0.0-255.255.255.255
denied-peer-ip=::1
denied-peer-ip=64:ff9b::-64:ff9b::ffff:ffff
denied-peer-ip=::ffff:0.0.0.0-::ffff:255.255.255.255
denied-peer-ip=100::-100::ffff:ffff:ffff:ffff
denied-peer-ip=2001::-2001:1ff:ffff:ffff:ffff:ffff:ffff:ffff
denied-peer-ip=2002::-2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff
denied-peer-ip=fc00::-fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
denied-peer-ip=fe80::-febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff
# Limit number of sessions per user
user-quota=12
# Limit total number of sessions
total-quota=1200
Save the file by pressing Ctrl+X, then Y.
Restart Coturn to apply the settings.
$ sudo systemctl restart coturn
Create a Synapse configuration file for Coturn.
$ sudo nano /etc/matrix-synapse/conf.d/turn.yaml
Paste the following lines in the editor. Replace the turn_shared_secret
value with the value of the static-auth-secret
variable from the \etc\turnserver.conf
file.
turn_uris: [ "turn:coturn.example.com?transport=udp", "turn:coturn.example.com?transport=tcp" ]
turn_shared_secret: 'static-auth-secret'
turn_user_lifetime: 86400000
turn_allow_guests: True
Save the file by pressing Ctrl+X, then Y.
Restart Synapse to apply the configuration.
$ sudo systemctl restart matrix-synapse
9. Use Matrix
You can use Synapse using any of the available Matrix clients. Element is the most popular client and is available as a web app, desktop, and mobile app.
Add your homeserver
address https://matrix.example.com
while logging in. Use the credentials you created in step 6. Create a secure backup for your encrypted messages and data using a security key or a phrase after logging in.
If you want to host your instance of Element web client, follow the instructions below.
10. Install Element
Install JSON text processor.
$ sudo apt install jq
Create a public directory for Element.
$ sudo mkdir -p /var/www/element
Switch to the directory.
$ cd /var/www/element
Grab the latest version of Element from its GitHub releases page.
$ latest="$(curl -s https://api.github.com/repos/vector-im/element-web/releases/latest | jq -r .tag_name)"
Download Element.
$ sudo wget https://github.com/vector-im/element-web/releases/download/${latest}/element-${latest}.tar.gz
Extract the archive.
$ sudo tar xf element-${latest}.tar.gz
Create another directory as a soft link.
$ sudo ln -s element-${latest} current
To update Element in the future, run the following command to update the soft link after extracting the archive.
$ sudo ln -nfs element-${latest} current
11. Configure Element
Switch to the current
directory.
$ cd current
Create the Element configuration file using the sample.
$ sudo cp config.sample.json config.json
Open the configuration file.
$ sudo nano config.json
Edit the base_url
and server_name
attributes referencing your matrix subdomain and the base domain.
"m.homeserver": {
"base_url": "https://matrix.example.com",
"server_name": "matrix.element.com"
},
Change the brand name if you want to customize the website title.
"brand": "My Example Chat",
Edit the disable_guests
variable to disallow Guests from using Element.
"disable_guests": true,
Save the file by pressing Ctrl+X, then Y.
Generate an SSL certificate for the Element client.
$ sudo certbot certonly --nginx -d element.example.com
Create and open the file /etc/nginx/conf.d/element.conf
for editing.
$ sudo nano /etc/nginx/conf.d/element.conf
Paste the following lines in it.
server {
listen 80;
listen [::]:80;
server_name element.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name element.example.com;
root /var/www/element/current;
index index.html;
access_log /var/log/nginx/element.access.log;
error_log /var/log/nginx/element.error.log;
add_header Referrer-Policy "strict-origin" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
# TLS configuration
ssl_certificate /etc/letsencrypt/live/element.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/element.example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/element.example.com/chain.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
}
Save the file by pressing Ctrl+X, then Y.
Verify the Nginx configuration file syntax.
$ sudo nginx -t
Restart the Nginx server.
$ sudo systemctl restart nginx
You can access Element via the URL https://element.example.com
.
Conclusion
Following this guide, you have installed a Matrix Synapse server and an Element client on a Ubuntu 22.04 server. For more information, check out the following resources.