In this comprehensive tutorial, we will guide you through the process of installing and setting up a chat server using Matrix Synapse and Element on Debian 12. Matrix is an open standard for decentralized and end-to-end encrypted communication, providing a secure and reliable platform for chat and messaging. By hosting your own Matrix server, you can have full control over your data and ensure the privacy of your conversations.
Prerequisites
Before we begin, let’s ensure that we have all the necessary prerequisites in place:
- A server running Debian 12.
- A non-sudo user with root privileges.
- The uncomplicated Firewall (UFW) enabled and running.
- Fully Qualified Domain Names (FQDN) pointing to your server for Matrix, Element, and Coturn services.
Step 1: Configure Firewall
The first step is to configure the firewall to allow access to the necessary ports. By default, we need to open ports for HTTP, HTTPS, and Synapse.
Check the current status of the firewall:
sudo ufw status
Make sure to allow incoming traffic on ports 8448, 80, and 443:
sudo ufw allow 8448
sudo ufw allow http
sudo ufw allow https
Verify the updated firewall rules:
sudo ufw status
Step 2: Install Matrix Synapse
Next, we will install Matrix Synapse, a homeserver implementation of Matrix. This will act as the central component of our chat server.
To get started, add the Matrix 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 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 repository list:
sudo apt update
Install Matrix Synapse:
sudo apt install matrix-synapse-py3
During the installation process, you will be prompted to enter the server name, which will serve as your Matrix ID. Provide your Matrix domain name as the server name.
Additionally, you will be asked whether you want to send anonymized statistics about your homeserver back to Matrix. For privacy reasons, it is recommended to decline this option by typing ‘N’.
By default, Matrix Synapse’s service is enabled and started during the installation process. You can check the status of the service using the following command:
sudo systemctl status matrix-synapse
Step 3: Install and Configure PostgreSQL
To store account information and chat history, we will use PostgreSQL as the database for our Matrix server. We will install the latest version of PostgreSQL using its official APT repository.
First, add the PostgreSQL GPG key:
curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | sudo tee /usr/share/keyrings/postgresql-key.gpg > /dev/null
Next, add the APT repository to your sources list:
sudo sh -c 'echo "deb [signed-by=/usr/share/keyrings/postgresql-key.gpg arch=amd64] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
Update the system repository:
sudo apt update
Now, you can install PostgreSQL:
sudo apt install postgresql postgresql-contrib
During the installation, a default PostgreSQL user and database are created. However, we will create a new user and database specifically for our Matrix server.
Switch to the postgres
system account:
sudo -su postgres
Create a new user and a database for PostgreSQL:
createuser --pwprompt synapse createdb --encoding=UTF8 --locale=C --template=template0 --owner=synapse synapsedb
Exit the postgres
account:
exit
Step 4: Install Nginx
For production environments, it is recommended to run the Synapse server behind an Nginx proxy. We will install Nginx and configure it to act as a reverse proxy for our Matrix server.
Debian 12 ships with an older version of Nginx, so we will download the official Nginx repository to install the latest version.
Import Nginx’s signing key:
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg > /dev/null
Add the repository for Nginx’s stable version:
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/debian $(lsb_release -cs) nginx" | sudo tee /etc/apt/sources.list.d/nginx.list
Update the system repositories:
sudo apt update
Install Nginx:
sudo apt install nginx
Verify the installation:
sudo nginx -v
Start the Nginx server:
sudo systemctl start nginx
Check the status of the service:
sudo systemctl status nginx
Step 5: Install SSL
To secure the communication between clients and the server, we will install SSL certificates using Certbot and Let’s Encrypt. Certbot is a tool that automates the process of obtaining and renewing SSL certificates.
Debian 12 does not come with Snapd installed, so we need to install it first:
sudo apt install snapd -y
Ensure that Snapd is up to date:
sudo snap install core sudo snap refresh core
Install Certbot:
sudo snap install --classic certbot
Create a symbolic link to make the Certbot command accessible:
sudo ln -s /snap/bin/certbot /usr/bin/certbot
Check the Certbot version:
certbot --version
Generate an SSL certificate for your Matrix domain:
sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m test@shapehost.com -d matrix.example.com
This command will download the SSL certificate and save it to the /etc/letsencrypt/live/matrix.example.com
directory on your server.
Generate a Diffie-Hellman group certificate:
sudo openssl dhparam-dsaparam -out /etc/ssl/certs/dhparam.pem 4096
Verify the Certbot renewal scheduler service:
sudo systemctl list-timers
Perform a dry run to test the SSL certificate renewal process:
sudo certbot renew --dry-run
If there are no errors, your SSL certificate is set up correctly.
Step 6: Configure Matrix Synapse
Now, let’s configure the Matrix Synapse server. Instead of modifying the homeserver.yaml
file directly, we will create separate configuration files in the /etc/matrix-synapse/conf.d
folder for better management.
During the installation process, two configuration files were created in the /etc/matrix-synapse/conf.d
folder: report_stats.yaml
and server_name.yaml
. We will create additional configuration files and modify the existing ones as needed.
Create a new configuration file for the database:
sudo nano /etc/matrix-synapse/conf.d/database.yaml
Add the following lines to the file:
database: name: psycopg2 args: user: synapse password: 'your-password' database: synapsedb host: localhost cp_min:5 cp_max:10
Replace 'your-password'
with the password you created for the PostgreSQL user in Step 3.
Create a secret registration key:
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
This key allows anyone to register a new user, even if registration is disabled. Keep it secure.
To disable presence indicators and reduce CPU usage, create a new configuration file:
sudo nano /etc/matrix-synapse/conf.d/presence.yaml
Add the following line to the file:
presence: enabled:false
Restart the Synapse service to apply the changes:
sudo systemctl restart matrix-synapse
Create a new Matrix user:
register_new_matrix_user -c /etc/matrix-synapse/conf.d/registration_shared_secret.yaml http://localhost:8008
You will be prompted to enter a username, password, and choose whether to make the user an administrator. Since this is the first user we are creating, it is recommended to make them an administrator.
If you want to allow public registration, create a new configuration file:
sudo nano /etc/matrix-synapse/conf.d/registration.yaml
Add the following line to the file:
enable_registration:true
To enable email verification for registrations, use the following configuration:
registrations_require_3pid: - email email: smtp_host: test@shapehost.com smtp_port: 587 smtp_user: 'test@shapehost.com' smtp_pass: 'password' require_transport_security: true app_name: 'HowtoForge Example Chat' notif_from: "%(app)s <test@shapehost.com>"
Replace 'mail.example.com'
, '[test@shapehost.com]'
, and 'password'
with your email server details.
To disable email verification, use the following configuration:
enable_registration_without_verification:true
Restart Synapse to apply the changes:
sudo systemctl restart matrix-synapse
Step 7: Configure Nginx
We will now configure Nginx to act as a reverse proxy for our Matrix server.
Open the Nginx configuration file for editing:
sudo nano /etc/nginx/nginx.conf
Add the following line before the line include /etc/nginx/conf.d/*.conf;
:
server_names_hash_bucket_size 64;
Create a new file for the Synapse configuration:
sudo nano /etc/nginx/conf.d/synapse.conf
Add the following code to the file:
# 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_session_timeout 1d; ssl_session_cache shared:MozSSL:10m; ssl_session_tickets off; ssl_prefer_server_ciphers on; ssl_stapling on; ssl_stapling_verify on; ssl_dhparam /etc/ssl/certs/dhparam.pem; resolver 1.1.1.1 1.0.0.1 [2606:4700:4700::1111] [2606:4700:4700::1001] 8.8.8.8 8.8.4.4 [2001:4860:4860::8888] [2001:4860:4860::8844] valid=60s; resolver_timeout 2s; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; tcp_nopush on; gzip on; 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; # Increase client_max_body_size to match the max_upload_size defined in homeserver.yaml client_max_body_size 50M; } }
Save the file and exit the editor.
Verify the Nginx configuration file syntax:
sudo nginx -t
Restart the Nginx service to apply the changes:
sudo systemctl restart nginx
Step 8: Install Coturn
If you want to enable voice and video calling in your Matrix server, you will need to install Coturn, a Traversal Using Relays around NAT (TURN) server. This server helps with NAT traversal by relaying traffic between clients.
To install Coturn, run the following command:
sudo apt install coturn
Open the TURN and UDP ports in the firewall:
sudo ufw allow 3478 sudo ufw allow 5349 sudo ufw allow 49152:65535/udp
Generate an SSL certificate for Turn:
sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m test@shapehost.com -d turn.example.com
Generate an authentication secret for Coturn:
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 for editing:
sudo nano /etc/turnserver.conf
Add the following lines to the file, replacing turn_shared_secret
with the value of static-auth-secret
from the /etc/turnserver.conf
file:
use-auth-secret realm=turn.example.com cert=/etc/letsencrypt/live/turn.example.com/fullchain.pem pkey=/etc/letsencrypt/live/turn.example.com/privkey.pem no-tcp-relay 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
Save the file and exit the editor.
Restart Coturn to apply the configuration changes:
sudo systemctl restart coturn
Step 9: Access Matrix
Now that your Matrix server is up and running, you can access it using Element, a Matrix web client.
Open your web browser and navigate to https://app.element.io.
Click the “Sign in” button to proceed.
Under “Homeserver,” click the “Edit” link and enter your Matrix domain (e.g., matrix.example.com).
If the client detects your homeserver correctly, the boundary and text will turn green. Click “Continue” to proceed.
Click the “Sign in” button to log in. If this is your first time logging in, you will be prompted to create a secure and encrypted backup.
Select the “Enter a Security Phrase” option to create a security phrase that will be required every time you log in. Click “Continue” to proceed.
Enter a security phrase and click “Continue” to proceed. You will be asked to confirm it again on the next screen.
You will be given a set of security keys that you can use if you forget your security phrase. Click the “Download” button to save them.
Finally, enter your account password and click “Continue” to finish setting up the encrypted backup.
Congratulations! You have successfully accessed your Matrix server using Element.
Step 10: Install Element
Next, we will install Element, a Matrix web client, on your Debian 12 server.
Install the jq
package, which is a JSON text processor:
sudo apt install jq
Create a directory for Element:
sudo mkdir -p /var/www/element
Create a script to automatically update Element to the latest release:
sudo nano /var/www/element/update.sh
Add the following lines to the script:
#!/bin/sh set -e install_location="/var/www/element" latest="$(curl -s https://api.github.com/repos/vector-im/element-web/releases/latest | jq -r .tag_name)" cd "$install_location" [ ! -d "archive" ] && mkdir -p "archive" [ -d "archive/element-${latest}" ] && rm -r "archive/element-${latest}" [ -f "archive/element-${latest}.tar.gz" ] && rm "archive/element-${latest}.tar.gz" wget "https://github.com/vector-im/element-web/releases/download/${latest}/element-${latest}.tar.gz" -P "archive" tar xf "archive/element-${latest}.tar.gz" -C "archive" [ -L "${install_location}/current" ] && rm "${install_location}/current" ln -sf "${install_location}/archive/element-${latest}" "${install_location}/current" ln -sf "${install_location}/config.json" "${install_location}/current/config.json"
Save the file and exit the editor.
Make the script executable:
sudo chmod +x /var/www/element/update.sh
Run the script to download and extract the latest version of Element:
sudo /var/www/element/update.sh
Step 11: Configure Element
Now, let’s configure Element to connect to your Matrix server.
Copy the sample configuration file:
sudo cp /var/www/element/current/config.sample.json /var/www/element/config.json
Open the configuration file for editing:
sudo nano /var/www/element/config.json
Find the following lines:
"m.homeserver": { "base_url": "https://matrix-client.matrix.org", "server_name": "matrix.org" },
Replace the default Matrix homeserver address and server name with your own:
"m.homeserver": { "base_url": "https://matrix.example.com", "server_name": "example.com" },
If you want to use a custom brand name instead of “Element,” modify the following line:
"brand": "Element",
To disallow guest access to your Element server, set the following value to true
:
"disable_guests": true,
Save the file and exit the editor.
Generate an SSL certificate for the Element client:
sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m test@shapehost.com -d element.example.com
Create an Nginx configuration file for Element:
sudo nano /etc/nginx/conf.d/element.conf
Add the following lines to the file:
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; 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_session_timeout 1d; ssl_session_cache shared:MozSSL:10m; ssl_session_tickets off; ssl_prefer_server_ciphers on; ssl_stapling on; ssl_stapling_verify on; ssl_dhparam /etc/ssl/certs/dhparam.pem; resolver 1.1.1.1 1.0.0.1 [2606:4700:4700::1111] [2606:4700:4700::1001] 8.8.8.8 8.8.4.4 [2001:4860:4860::8888] [2001:4860:4860::8844] valid=60s; resolver_timeout 2s; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; }
Save the file and exit the editor.
Verify the Nginx configuration file syntax:
sudo nginx -t
Restart the Nginx service:
sudo systemctl restart nginx
Conclusion
Congratulations! You have successfully installed and configured a chat server using Matrix Synapse and Element on Debian 12. You now have full control over your communication platform, ensuring privacy and security for your conversations.
This tutorial has covered the step-by-step process of setting up a Matrix Synapse server, configuring Nginx as a reverse proxy, and installing Element as the web client. Additionally, we explored the installation and configuration of Coturn for voice and video calling, as well as SSL certificate management using Certbot.
By hosting your own chat server, you can enhance collaboration and communication within your organization while maintaining control over your data. Enjoy the benefits of decentralized and end-to-end encrypted communication with Matrix Synapse and Element.
For reliable and scalable cloud hosting solutions, including Linux SSD VPS, visit Shape.host to explore our services.
If you have any questions or encounter any issues, feel free to post them in the comments below. Happy chatting!