Last time I wrote about how to set up your very own personal Matrix stack with everything you need - the Synapse servers, Element web client, and Synapse Admin. This time I will show how to set up a few bridges - that is, components that connect Matrix to other chat platforms and services. They will generally let you send and receive messages from other services directly to and from Matrix.
This time the "technical stuff" will be a bit less complex. While there are a few gotchas, we don't need to expose anything to the internets, so we needn't configure any webservers, domains, or anything else.
When I first decided to give Matrix a spin, I only expected to use it little, since none of my friends or communities use it. But after I added bridges for Whatsapp, Facebook Messenger, and Discord, I ended up using it daily - while also being able to ditch the apps for those three. Those are the bridges we will set up today.
An added benefit: Not only can I now just open one window and chat with my contacts on any of the four platforms [i.e. WA, FB, DC, and Matrix (MX) itself] - I also can do it from a web app simultaneously on multiple computers. Which is something I just couldn't do before, because Whatsapp doesn't let you log into multiple browsers (or computers) at once.
I won't go into the details, but the gist of it is: Matrix servers (in this case, Synapse) allow registrations of "Application Services" as a way of extending the server's functionality. They're not plugins in the usual sense of the word - they live alongside the MX server and communicate with it via HTTP.
Unlike standard clients though, they have special powers - they can reserve namespaces in which to create rooms or puppet users, monitor room events, etc.
There are various kinds of bridges, depending on what they can do. I won't go into any of those, either; I'll just say that all the bridges mentioned here can import your contacts into Matrix, initiate and sync direct messages and group chats, download avatars and images, forward reactions, and other fancy features. (Side note: Facebook introduced reactions with arbitrary emoji. They haven't been rolled out for me yet, but the bridge did support them - so I could use them from Matrix, but not the official Messenger app.)
On the "client" side of the bridges - WA, FB, or DC often don't really expose an API, so the bridges impersonate a web app when communicating with the service they're bridging into. Authenticating with them is sometimes more complicated than just logging into a service, but it's nothing more difficult than finding and copying cookie values.
You don't need anything besides Docker (and -compose). The Whatsapp bridge's readme shows you how to run an emulated Whatsapp on your server so you don't need to have your phone connected to WA at all (remember WA's web and desktop apps only work as long as your phone has an active internet connection). I chose not to do this and only run Whatsapp on my phone.
Just as last time, I've always gone with the default SQLite database instead of additional dependencies. After a few months of usage, no bridge's DB is bigger than 10 megabytes.
The compose file is pretty straightforward. I'm not exposing ports, since I won't be hosting these separately - instead, I'll add this to the compose file from the previous post, which also holds the entire Matrix stack. Since the only component that needs to see the bridges' ports is the Synapse server, it will do so over the default network and there's no need to expose them.
These are the new bits to add:
version: "3" services: messenger_bridge: image: dock.mau.dev/tulir/mautrix-facebook:latest restart: unless-stopped volumes: - messenger_bridge_files:/data whatsapp_bridge: image: dock.mau.dev/tulir/mautrix-whatsapp:latest restart: unless-stopped volumes: - whatsapp_bridge_files:/data discord_bridge: image: sorunome/mx-puppet-discord:latest restart: unless-stopped environment: - CONFIG_PATH=/data/config.yaml - REGISTRATION_PATH=/data/discord-registration.yaml volumes: - discord_bridge_files:/data volumes: discord_bridge_files: whatsapp_bridge_files: messenger_bridge_files:
By default, Docker exposes each service on its default network under the service's specified name. Turns out my snake_case names are unpalatable when it comes to the network. (I got stuck on this for a while until I realized what the problem was.) It's solved easily enough, by adding aliases for the bridge services to the Synapse section. Let's modify the Synapse config, add the
services: synapse: image: matrixdotorg/synapse:latest restart: unless-stopped environment: - SYNAPSE_CONFIG_PATH=/data/homeserver.yaml volumes: - synapse_files:/data ports: - 33333:8008 links: - "messenger_bridge:messenger-bridge" - "whatsapp_bridge:whatsapp-bridge" - "discord_bridge:discord-bridge"
This basically says that the
messenger_bridge service should also be available at the
messenger-bridge network address.
All the bridges are set up with the same basic idea: you create the container, modify the configs, and run the bridge container. It generates the Application Registration file you need to register with Synapse and exits.
docker-compose.yml file is in a folder called
matrix. So to create all the containers and edit the config for the Messenger bridge, I run:
docker-compose up --no-start docker volume inspect matrix_messenger_bridge_data
Check where the container's Mountpoint is and edit the
config.yaml file as needed. This is where you set things like the homeserver's address/domain, the bridge's local port, etc.
Once that's done, start the bridge:
docker-compose up messenger_bridge
You should see something like this:
Starting matrix_messenger_bridge_1 ... done Attaching to matrix_messenger_bridge_1 messenger_bridge_1 | INFO [alembic.runtime.migration] Context impl SQLiteImpl. (some parts omitted for brevity) messenger_bridge_1 | INFO [alembic.runtime.migration] Running upgrade 905a91536747 -> 2162f7ae5365, Store encryption state event in db messenger_bridge_1 | Registration generated and saved to /data/registration.yaml messenger_bridge_1 | Didn't find a registration file. messenger_bridge_1 | Generated one for you. messenger_bridge_1 | Copy that over to synapses app service directory. matrix_messenger_bridge_1 exited with code 0
This generated the registration file we needed:
registration.yml. Copy it somewhere handy, perhaps also rename it to something more descriptive (like
messenger_bridge_registration.yaml), since there's going to be more of them.
id: messenger as_token: x923secretstuff hs_token: g33secretstuff namespaces: users: - exclusive: true regex: '@facebook_.+:zble.sk' group_id: messenger - exclusive: true regex: '@messenger:zble\.sk' url: http://messenger_bridge:32020 sender_localpart: gfu3secretstuff rate_limited: false
The contents of this file have been generated based on the
config.yaml file - that's where the port in URL comes from, for example. Also notice the URL says "messenger_bridge" - this won't work. It took me a while to figure out where the problem is, but the Docker network doesn't like the underscore in that name. That's why we've added the
links section to the Synapse server, above. (Yes, of course you could just name the container differently, but that would break my naming scheme and I don't wanna.) After the links are set up, you only need to change it to "messenger-bridge" instead.
Do this analogously for all the bridges, then continue with:
The bridge containers are configured and ready, and all of the files generated. The only remaining step is registering them with Synapse.
So copy the config files to where the Synapse's config file (
homeserver.yaml) is and add or edit the
# A list of application service config files to use # app_service_config_files: - /data/messenger_bridge_registration.yaml - /data/whatsapp_bridge_registration.yaml - /data/discord-registration.yaml
(Just a reminder, if you can't find where the files are on your drive, inspect the
synapse_files volume and look for the Mountpoint.)
When all that is done, restart the Synapse container and start all the bridges.
docker-compose stop synapse docker-compose up -d
If everything worked, the bot users should now be responding to messages from within Matrix. You will still need to log in with them etc, but that's best described in their own docs, linked above.
This is the final compose file in its entirety:
``` version: "3" services: synapse: image: matrixdotorg/synapse:latest restart: unless-stopped environment: - SYNAPSE_CONFIG_PATH=/data/homeserver.yaml volumes: - synapse_files:/data ports: - 32000:8008 links: - "messenger_bridge:messenger-bridge" - "whatsapp_bridge:whatsapp-bridge" - "discord_bridge:discord-bridge" synapse_admin: image: awesometechnologies/synapse-admin:latest restart: unless-stopped ports: - 32001:80 riot: image: vectorim/riot-web:latest restart: unless-stopped volumes: - riot_files:/app ports: - 32002:80 messenger_bridge: image: dock.mau.dev/tulir/mautrix-facebook:latest restart: unless-stopped volumes: - messenger_bridge_files:/data whatsapp_bridge: image: dock.mau.dev/tulir/mautrix-whatsapp:latest restart: unless-stopped volumes: - whatsapp_bridge_files:/data discord_bridge: image: sorunome/mx-puppet-discord:latest restart: unless-stopped environment: - CONFIG_PATH=/data/config.yaml - REGISTRATION_PATH=/data/discord-registration.yaml volumes: - discord_bridge_files:/data volumes: synapse_files: riot_files: discord_bridge_files: whatsapp_bridge_files: messenger_bridge_files:
I found these bridges to be really useful. I don't really need any of the apps on my phone anymore, and only need one app on the PC.
It isn't always a smooth ride, and isn't totally feature-complete: for instance, if you want to make actual voicecalls via Discord, you still need to do it via the official client. (But I don't really do that often, so it's not a problem.)
As usual, the biggest issues are with Facebook: since my bridge is hosted on a VM in a different country, I get locked out of my account (because "SoMEoNe Is HAcKiNg ME fRoM NeThErLanDs aGaIn hurr durr") quite often. That could probably be remedied by hosting the bridge in my home, but frankly, I use Messenger less and less these days, so I'm not sure I'll ever bother.
And all of the bridges have great communities - when I got stuck, I always found help in their Matrix chatrooms or on Github.