Installing and configuring Matrix Synapse with Ansible and Docker

Matrix Synapse and Element — Ansible and Docker setup Docker

Want this installed for you? See the Matrix / Element setup service.

This guide covers a full Synapse installation on your own server (or VPS) and basic configuration of its features. Synapse is deployed with multiple Docker containers managed by the Ansible configuration system. Official documentation for this installation method is available on Github and Matrix.org.

Synapse is an open-source Matrix homeserver written and maintained by the Matrix.org Foundation. Matrix clients are listed here: https://matrix.org/clients/

I chose the Ansible + Docker Synapse deployment because it is the easiest way to install and configure additional Synapse dependencies and extensions, and it also installs nginx, SSL, and PostgreSQL automatically.

In short, Matrix is an open standard for internet communication used by messengers. It supports federation, encryption, voice and video calls, and video conferences. Integrations with Telegram, Discord, WhatsApp, and more are also possible — the full list is here: https://github.com/spantaleev/matrix-docker-ansible-deploy#bridges

Today you can use Matrix for private chats with friends and family, as a full replacement for WhatsApp/Telegram, or even for corporate communication — with one major difference from popular messengers:

  1. You can communicate via your own server with your own encryption keys and stronger protection against interception. Popular messengers use servers and metadata under the service operator’s control; on your own server you decide where accounts, media, and logs are stored
  2. Despite using your own server, you can still communicate with users on other Matrix servers (federation)
  3. You can set up a bridge and chat with users of any other messenger, such as Telegram or WhatsApp
  4. Less dependence on third-party infrastructure: accounts and room history live on your server (with E2EE, room contents are not readable by the server in plaintext)
  5. High-quality, highly stable audio and video when the Synapse host has sufficient resources
  6. Stronger protection against personal data collection and message theft
  7. Minimal network verification — you do not have to use your phone number or email to register (except on some public servers, which often require email). To get started on a public server, see the Join Matrix guide and pick one from the public server list.

In other words, Synapse lets you join the Matrix network with your own identifier @<username>:<your-domain>, all hosted on your own server or rented VPS.

All services run in Docker containers, which gives a predictable and up-to-date setup. Installation, updates, and some maintenance tasks are automated with Ansible.

Need a turnkey setup? See our service page: Matrix Synapse + Element on your VPS. Below is a self-hosted install using the official matrix-docker-ansible-deploy playbook (updated for 2026).

System requirements

Without Matrix RTC / Element Call (chat only):

4 GB RAM (or 2 GB + swap), 2 CPU cores (at least 3.4 GHz), 40 GB SSD or NVMe disk

With Matrix RTC / Element Call (LiveKit):

6 GB RAM (or 4 GB + swap), 2 CPU cores (at least 3.4 GHz)

Supported OS:

Debian 10+ (12 recommended)
Ubuntu 20.04+ (22.04 / 24.04 LTS recommended)
Rocky Linux / AlmaLinux (or other RHEL-like)
Arch Linux

I personally installed it only on Ubuntu 24.04 LTS and Debian 11–12.

A server with 2 GB RAM and no swap can also run Synapse, but only for personal voice calls (no video) and private chats (tested, with some limitations). Federated rooms with many subscriptions will completely overload such a server (you may need to reboot and urgently remove Synapse, then reinstall)

Buying a domain

Buy a domain for your Matrix server. For domains I recommend Timeweb Cloud.

Renting a VPS

For VPS rental I recommend the following providers:

Server — Timeweb Cloud. For Synapse, prefer a plan with a fast CPU.

Servers in Russia — Timeweb Cloud: VPS in Russian data centers; you can also buy a domain and manage DNS records there.

Configuring DNS records for the domain

After buying a domain and renting a server, immediately add the DNS records below. Do this as soon as possible, because DNS propagation can take from 3 hours to 3 days (usually less than a day).

The apex domain will not be used for Synapse itself, because it is usually reserved for the main site or blog. Synapse will use subdomains such as matrix.example.ru and element.example.ru

Replace example.ru with your domain prepared for Synapse.

Required DNS records for the domain:

Minimum records for a default install (replace example.ru with your domain, IP with the VPS address):

A matrix → server IP
CNAME element → matrix.example.ru

Optional: AAAA matrix → server IPv6.

Dimension / Jitsi CNAMEs and the _matrix-identity SRV record are not required for a basic install. Short IDs like @user:example.ru use /.well-known delegation (see below) or matrix_static_files_container_labels_base_domain_enabled.

Example DNS setup in a registrar control panel:

nastrojka dns

You can check DNS propagation here https://2ip.ru/dig/

Preparing the system

Update the system

apt update -y && 
apt upgrade -y

Harden the server and disable password login using the following checklist with an SSH key:

https://kiberlis.ru/pamyatka-po-bezopasnosti-vps-vds-servera-ubuntu-debian

Install the required dependencies (Python3-pip, Ansible, and pwgen for password generation):

apt install pipx
pipx ensurepath
pipx install ansible
apt install pwgen

Reboot the server:

reboot

As an alternative way to install Ansible, you can also follow the official documentation https://docs.ansible.com/ansible/latest/installation_guide/installation_distros.html#installing-ansible-on-debian

Installing Matrix Synapse

Downloading the installation files

Download the installation files to the server

git clone https://github.com/spantaleev/matrix-docker-ansible-deploy.git

Configuring the Ansible playbook

Loading the base configuration template

In this guide we run the Ansible playbook directly on the server, so copy the configuration template into the Synapse config directory and set the SSH connection details in matrix-docker-ansible-deploy/inventory/hosts

Enter the installation directory

cd matrix-docker-ansible-deploy

Create a directory for your server configuration (replace example.ru with your domain)

mkdir -p inventory/host_vars/matrix.example.ru

Copy the vars.yml and hosts configuration templates (replace example.ru with your domain)

cp examples/vars.yml inventory/host_vars/matrix.example.ru/
cp examples/hosts inventory/hosts

Configuring Ansible SSH access to the server

To edit the server connection config file, run:

nano inventory/hosts

The file contents should look like this if you followed the security checklist, because it uses an SSH key instead of a password and a non-default SSH port:

[matrix_servers]
matrix.example.ru ansible_host=IP-сервера ansible_ssh_user=root ansible_ssh_port=ПОРТ-SSH ansible_ssh_private_key_file=~/.ssh/id_rsa

Replace example.ru with the domain you purchased earlier.

In ansible_host, set your server’s public IP address.

In ansible_ssh_user, set the SSH username (default is root, which I kept; it can be a non-root user). If you use sudo, append -K to the Ansible install commands

In ansible_ssh_port, set your SSH port (default is 22, but I changed it and recommend you do the same per the security checklist)

In ansible_ssh_private_key_file, set the SSH private key path (default ~/.ssh/id_rsa; the checklist uses the same path)

If you are not using an SSH key and did not change the SSH port, the contents look like this (not our case, because we care about security):

[matrix_servers]
matrix.example.ru ansible_host=IP-сервера ansible_ssh_user=root

Generating keys for Matrix Synapse

Generate keys for the Matrix Synapse configuration in advance — you will need 10 keys. Generate them with the following command and save them in a notepad on your computer:

pwgen -s 64 1

Configuring the main Synapse parameters

The main Synapse parameters are in vars.yml at matrix-docker-ansible-deploy/inventory/host_vars/matrix.example.ru

To edit vars.yml, run the following command (replace example.ru with your domain):

nano inventory/host_vars/matrix.example.ru/vars.yml

You can use the ready-made vars.yml template below — fully replace the file contents and fill in your own values.

Replace example.ru with your domain and insert the previously generated keys instead of ‘большой ключ’.

The template uses the apex domain rather than a subdomain so you get clean addresses like @login:example.com without the matrix prefix.

#Обязательное
matrix_playbook_migration_validated_version: v2026.05.18.0
matrix_domain: example.com
matrix_homeserver_implementation: synapse
matrix_homeserver_generic_secret_key: 'большой ключ'
matrix_playbook_reverse_proxy_type: playbook-managed-traefik
devture_systemd_docker_base_ipv6_enabled: true
postgres_connection_password: 'большой ключ'


# If example.ru can be served by Matrix (no separate site) — enable /.well-known from the Matrix host.
# If a site already uses example.ru — comment this out and configure /.well-known on that web server.
matrix_static_files_container_labels_base_domain_enabled: true
traefik_config_certificatesResolvers_acme_email: 'ssl@example.com'
#matrix_nginx_proxy_base_domain_serving_enabled : true

#Активация админ-панели
matrix_ketesa_enabled: true

# Element Call / Matrix RTC (LiveKit). Optional for chat-only.
#matrix_rtc_enabled: true
#matrix_element_call_enabled: true

This configuration template includes:

  • Synapse homeserver — the Matrix Synapse server
  • PostgreSQL — database
  • Traefik — reverse proxy (ports 80/443/8448), SSL via Let’s Encrypt
  • Let’s Encrypt — automatic SSL certificates via Traefik
  • Element Web — web Matrix client at element.example.ru, preconfigured for your server (replace example.ru with your domain)
  • Exim — outbound mail for Matrix notifications (can relay via external SMTP)
  • Ketesa / Element Admin — web admin panel (if enabled in vars.yml)
  • Optional: Matrix RTC / Element Call (LiveKit) for modern calls
  • Optional: matrix-registration — invite-based signup
  • Optional: Coturn — only if you enable classic TURN separately
  • Always compare your vars.yml with examples/vars.yml and the CHANGELOG after upgrades

After filling the template with your data, start the installation. If you do not need something, delete or comment out that line in the config file.

Running the Matrix Synapse installation

Install ansible-core:

pipx install ansible-core

Reboot the server:

reboot

Install the Ansible roles required for Synapse:

rm -rf roles/galaxy &&
ansible-galaxy install -r requirements.yml -p roles/galaxy/ --force

Install the Ansible Galaxy collections community.general, ansible.posix, and community.docker:

ansible-galaxy collection install community.general
ansible-galaxy collection install ansible.posix
ansible-galaxy collection install community.docker

Install. If the user in hosts is not root and you need a sudo password, append -K to the command (and to all subsequent commands)

ansible-playbook -i inventory/hosts setup.yml --tags=install-all,ensure-matrix-users-created,start

Next you can run a configuration check

ansible-playbook -i inventory/hosts setup.yml --tags=self-check

If you use an SSH password instead of a key for deploy commands, add –ask-pass

ansible-playbook -i inventory/hosts setup.yml --tags=install-all,ensure-matrix-users-created,start --ask-pass

If you hit errors, Matrix Synapse Ansible may have been updated and you may need to refresh this template against examples/vars.yml (please mention that in the comments). Always read error messages carefully to rule out simple mistakes.

Documentation and additional Matrix Synapse Ansible settings

Registering the first user and making them an administrator

To create a user with administrator rights, run:

ansible-playbook -i inventory/hosts setup.yml --extra-vars='username=логин password=пароль admin=yes' --tags=register-user

Dimension (removed from the playbook)

The playbook used to install Dimension (integrations / widgets, including Jitsi). That component is unmaintained and removed from matrix-docker-ansible-deploy — do not set it up on new servers.

If you still have Dimension from an old install, remove it manually:

systemctl disable --now matrix-dimension.service
rm -rf /matrix/dimension
/matrix/postgres/bin/cli-non-interactive -c 'DROP DATABASE matrix_dimension;'

For calls use Element Call + Matrix RTC (LiveKit) — next section. Docs: configuring-playbook-dimension.md.

Enabling calls (Element Call / Matrix RTC)

The modern path for audio/video in Element Web and Element X is Matrix RTC (LiveKit Server + LiveKit JWT Service). Jitsi via Dimension is obsolete.

Add to vars.yml:

matrix_rtc_enabled: true

# Optional standalone Element Call web UI
#matrix_element_call_enabled: true

Redeploy:

ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,start

Open LiveKit firewall ports when calls are enabled: 7881/tcp, 7882/udp, 3479/udp, 5350/tcp, 30000:30020/udp.

Docs: Matrix RTC, Element Call.

Invite-based registration

This feature is already enabled in your configuration template. To create an invite link, use:

ansible-playbook -i inventory/hosts setup.yml 
--tags=generate-matrix-registration-token 
--extra-vars="one_time=yes ex_date=2027-12-31"

Set one_time=”no” if you need an invite without an expiration date. I recommend “yes” and setting ex_date= in the same format as in the sample command

After running the command above, you will get a registration link for your friends.

Admin panel

Available at (trailing / is required):

https://matrix.example.ru/synapse-admin/

Firewall rules

Firewall rules used (align them with rules already on the system — see the security checklist, section 5):

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 443/udp
sudo ufw allow 8448/tcp
sudo ufw allow 8448/udp
sudo ufw allow YOUR-SSH-PORT/tcp
# If Matrix RTC / Element Call (LiveKit) is enabled:
sudo ufw allow 7881/tcp
sudo ufw allow 7882/udp
sudo ufw allow 3479/udp
sudo ufw allow 5350/tcp
sudo ufw allow 30000:30020/udp
sudo ufw enable

Check the status:

sudo ufw status verbose

Base-domain /.well-known delegation

If example.ru already hosts a website and you did not enable matrix_static_files_container_labels_base_domain_enabled, configure delegation manually so clients and federation know Matrix for example.ru lives on matrix.example.ru.

Example nginx snippet on the website host:

location /.well-known/matrix {
    proxy_pass https://matrix.example.ru/.well-known/matrix;
    proxy_set_header X-Forwarded-For $remote_addr;
}

Federation check: federationtester.matrix.org. Playbook docs: Server Delegation.

Updates and maintenance

The playbook does not auto-upgrade services. Periodically update the git repo and Ansible roles, then re-run. Watch the CHANGELOG (breaking changes and matrix_playbook_migration_validated_version).

Announcements: #homeowners:matrix.org. Support: #matrix-docker-ansible-deploy:devture.com.

cd matrix-docker-ansible-deploy
git pull
rm -rf roles/galaxy && ansible-galaxy install -r requirements.yml -p roles/galaxy/ --force
# Or: just update / just roles

ansible-playbook -i inventory/hosts setup.yml --tags=install-all,start
# If you disabled components in vars.yml, prefer setup-all:
# ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,start

PostgreSQL major upgrades are manual — follow the playbook docs.

Removing Synapse

To remove Synapse, run:

sh /matrix/bin/remove-all

then copy and paste the confirmation text “Yes, I really want to remove everything!”

Categories: Docker Security Web apps Messengers
Subscribe to new posts (RSS)

No email, no trackers — just the update feed.

Also available in Russian

Rate this article
Leave a comment