Do your chats look like this? Do you always forget which contacts use which apps? Do you wish there was a way to have all your chats in just one place?
If you answered yes to any of those question: good news! In the following guide I'm going to show you how to use Matrix to achieve your dream of an all-in-one chat app, by using Matrix "bridges" (more on that later) and securing the connection with Cloudflare Tunnels.
The Matrix protocol can communicate with other apps through "bridges", and this allows us to use a Matrix compatible app to chat with everyone else across every other app.
Self-hosting a Matrix server isn't exactly known for being a walk in the park. This guide is aimed towards intermediate and advanced self-hosters. However we will self-host it using the matrix-docker-ansible-deploy playbook on Github, which makes the installation and the maintenance much easier - so don't fret! I will break things down as best as I can, so hopefully it will be as easy as stealing candy from a baby (don't do that!).
But what even is a Matrix bridge?
Simply put, it's a connection between Matrix and other platforms that allows Matrix to exchange messages and other data with them.
For example, by using a Whatsapp bridge, you would be able to chat with your contacts using your Whatsapp account, but on a Matrix supported app instead. That means your contacts wouldn't be able to tell the difference, as they are still texting you at your usual Whatsapp account inside the official app.
Below you can find more info about which ones are available and what chat features they currently support (and their possible limitations).
In this guide I will show you how to self-host your own secure Matrix server using an Ansible Playbook, that we will first configure on a local machine, and then deploy on our server through an SSH connection.
We will use Cloudflare Tunnels to setup the Matrix subdomains and to protect our SSH connection.
You will be able to select which bridges you want to install, and we will add federation support to be able to interact with users from other Matrix servers.
I will also show you how to implement the latest bleeding-edge Sliding sync proxy, which allows for a faster than ever messaging experience.
"Ansible Playbooks offer a repeatable, re-usable, simple configuration management and multi-machine deployment system, one that is well suited to deploying complex applications. If you need to execute a task with Ansible more than once, write a playbook and put it under source control. Then you can use the playbook to push out new configuration or confirm the configuration of remote systems."
"Federation is the process by which users on different servers can participate in the same room. For this to work, those other servers must be able to contact yours to send messages."
- A domain
- A Cloudflare account (free tier)
- A local computer and a server* (I recommend at least 2GB of ram** and 50gb of disk space)
*preferably both running Linux. This guide will assume they are, but you can adapt the commands to other OS's.
**memory usage increases the more bridges you activate.
Remember to change <example.com> with your own domain wherever it appears in this guide.
For this guide I'm assuming you already have your main domain added to Cloudflare.
Create a new Tunnel in the Zero Trust dashboard and install the
cloudflared connector in your server as shown in the Overview.
We are now going to add a new public hostname. We'll name it
matrix-ssh.<example.com>, and we will point it to localhost using the SSH service type.
Next up is a very important step, but how you configure it is up to you. Take some time to create a Cloudflare Access Application, and protect its access with an authentication method - I recommend a One-time PIN.
When you're happy with that, install
cloudflared on your local computer too.
~/.ssh/config on your local computer (or create it) and paste the block below, but change the domain as well as the path where cloudflared is installed if different:
If everything went well, you should be able to ssh into your server with
ssh root@matrix-ssh.<example.com>, and Cloudflare should open your browser to authenticate you based on how you setup the Access Application earlier.
Now all the ssh traffic to your server will be going securely through Cloudflare - congratulations!! You are free to block open SSH ports in your firewall.
Now that we can ssh into our server through Cloudflare, we are going to do that without the need to use a password. Let's implement a key-based authentication!
If you haven't already, generate a ssh key pair on your local computer:
Continue with the defaults. The keys will be stored in
~/.ssh. The private key will be called
id_rsa and the associated public key will be called
Copy your public key over to your server:
ssh-copy-id -i ~/.ssh/id_rsa.pub root@matrix-ssh.<example.com>
Now you should be able to ssh into your server without being asked for the password:
Configure the Playbook
On your local computer. clone the matrix-docker-ansible-deploy Github repository, and move inside it:
git clone https://github.com/spantaleev/matrix-docker-ansible-deploy.git
This is the directory from where we will configure our playbook - and also upgrade it in the future - before deploying it on the server.
Before proceeding, install
pwgen on your local computer, which you will need later.
Create the file
hosts inside the
inventory directory, and copy the following content:
- Insert your domain instead of
~/.ssh/id_rsaif you're using a different key or path
- Change path of
/usr/bin/cloudflaredif you installed it somewhere else
When you're done, test the connection to the server using Ansible on your local computer:
ansible -i inventory/hosts all -m ping -v
Create the directory
We are now going to add a new file called
vars.yml inside that directory.
- Insert your domain instead of
<create_secretkey>shows up, run
pwgen -s 64 1and insert the generated key
- Enable the bridges you want to use by changing their value from
Note that I have disabled TURN with
matrix_coturn_enabled: false because I won't be using voice/video calls. Enabling it is possible, but you’d have to expose your server from outside of Cloudflare.
Once you're happy with the configuration, you're ready to finally deploy your installation to the server!
On your local computer, inside the
matrix-docker-ansible-deploy directory, run:
This will take a while. In the meantime you can already proceed to the next step.
We are going to expose the Matrix Client (local port 81) and the Matrix Server (local port 8449) services through Cloudflare Tunnels. However, since each hostname can only point to a single service, we’ll trick the Matrix Server into thinking that it is running on the same hostname as the Matrix Client.
matrix.<example.com> hostname for the Matrix Client and point it to
matrix-fed.<example.com> hostname for the Matrix Server and point it to
http://localhost:8449, with HTTP Host Header
By overriding the HTTP Host Header, when a server connects to
matrix-fed.example.com, our Matrix Server will be served
When the installation finishes, you can proceed to create your account by running the following command on your local computer, with your username (
<insert_username) and password (
<your_password>) of choice.
ansible-playbook -i inventory/hosts setup.yml --extra-vars='username=<insert_username> password=<your_password> admin=yes' --tags=register-user
At long last, your Matrix server is finally ready (well almost, but it works already).
Go ahead and test it by logging in to a Matrix client, for example:
- In a browser, open https://app.schildi.chat/#/login
- Click Edit and insert
https://matrix.<example.com>, then click Continue
- Sign in with your username and password created above
We have created
matrix-fed.<example.com>, but now we need a way to tell other servers to connect to it. As stated in the Matrix Specification, We need to implement server discovery by adding two well-known files at the root of our main domain.
If you already have a way to serve files on your main domain, these are the two files you need to add (otherwise, skip to the next step):
Change <example.com> with your own domain.
If you already have an application running on your main domain, and can't serve files there, you can use Cloudflare Workers with custom routes to dynamically reply to those requests.
Go to Workers Routes in your Cloudflare Dashboard, and click the Manage Workers button.
Then 'Create Application', 'Create Worker' and 'Deploy' the default script which we will edit soon.
Go back to your applications and click on the one we just created, then click 'Quick Edit'.
Paste the following script provided by this blogpost, and insert your domain in the 1st and 3rd line:
Rename the application to something like
Then in the 'Triggers' tab of your application, scroll down to the 'Routes' section. Click on 'Add route' and insert
<example.com>/.well-known/matrix/* like this:
You're free to disable the default worker route.
Once you're done, verify that the well-known files are available in their respective path of your domain, and test if the server is correctly federated using Matrix Federation Tester your main domain.
If everything went smoothly... congratulations! You can now find and chat with other Matrix users, as well as join rooms on different servers. Feel free to send me a message to celebrate.
Now to enable the bridges you installed:
- Inside your Matrix client, find and add each bridge bot to your rooms by going to Direct Messages and starting a conversation with them (e.g. for Whatsapp start a new conversation with @whatsappbot:<example.com>)
- Send a
helpmessage to the bot, and you will be shown a list of commands to login (usually
login-qr) and perform other actions.
You can find the bots names in their respective documentation in this list
Sliding sync (Optional)
Sliding sync is the latest Matrix proxy which allows to sync messages even faster. It is currently still experimental and it requires a client that supports it.
As of now, the options to take advantage of Sliding sync are either by using a web client which supports it as a Labs option. or by using the Element X app which is currently being actively developed and far from being feature complete. Read the official blog post.
As you can see it's still very much in its early stages and you probably won't be seeing its benefits soon. However it's super simple to implement and it's worth to already have it for the future.
matrix-docker-ansible-deploy/inventory/host_vars/matrix.<example.com>/vars.yml on your local computer, and add the following variable:
Then edit the well-known file at
https://<example.com>/.well-known/matrix/client to the following:
or alternatively, if you used Cloudflare Workers:
As always, change <example.com> with your own domain.
When you're done, just re-run the installation again (
just setup-all) and your Sliding sync proxy will be available at the
To test it, just try to login using the Element X app or by inserting the proxy URL above in the Sliding sync Labs option of a compatible web client.
To upgrade services in the future, inside your
matrix-docker-ansible-deploy directory, run:
git pull #update files from the git repo
just setup-all #restart the services
It's a good idea to take a look at the changelog to see if there have been any backward-incompatible changes that you need to take care of.
If you want to be notified when new versions of Synapse are released, you can join the Synapse Homeowners room: #homeowners:matrix.org.
matrix-docker-ansible-deploy - for the Ansible playbook
Beeper self-host - for the vars.yml template
Appelman's blog post - for how to setup federation with Cloudflare Workers