Introduction

This book contains the documentation for all my Matrix bridges. The book is built using mdBook. The source code is available in the mautrix-docs repo.

Troubleshooting & FAQ

Debugging setup issues should be done in the Matrix rooms for the bridges (linked in the READMEs), rather than in GitHub issues. Additionally, this page will collect some of the most common issues.

Why is the bridge bot not accepting invites?

If the bridge starts up successfully, but inviting the bot doesn't work and the logs don't show any errors, it usually means the homeserver isn't sending events to the appservice. There are a few potential reasons this can happen:

  • There was a misconfiguration in the appservice address/hostname/port config or the homeserver can't reach the appservice for some other reason. The homeserver logs should contain errors in this case (grep for transactions in Synapse's homeserver.log).
    • Note that grepping for transactions will show some data even when it's working correctly. If it shows nothing at all, something is broken.
  • The bridge was down for longer than a few minutes and the homeserver backed off. The homeserver should retry after some time. If it still doesn't work after an hour or so (exact backoff depends on how long the bridge was down), check the homeserver logs.
  • Synapse messed up and silently broke the appservice. This is quite rare, but This is becoming relatively common, you should check matrix-org/synapse#1834 if nothing else works.

pip failed building wheel for python-olm

fatal error: olm/olm.h: no such file or directory

When building with end-to-bridge encryption, you must have a C compiler, python3 dev headers and libolm3 with dev headers installed.

If you want to build without encryption:

  • For Python bridges, don't install the e2be optional dependency.
  • For Go bridges, either build with -tags nocrypto or disable cgo with the CGO_ENABLED=0 env var.

fatal error: olm/pk.h: no such file or directory

libolm2 is too old, you need libolm3.

fatal error: pyconfig.h: no such file or directory

python3-dev is required.

error: command 'gcc' failed: No such file or directory

build-essential is required.

End-to-bridge encryption

The bridge can optionally encrypt messages between Matrix users and the bridge to hide messages from the homeserver. Using Postgres is strongly recommended when using end-to-bridge encryption.

To enable it, you must install the bridge with dependencies:

  • For Python-based bridges, install the e2be optional dependency.
  • For Go-based bridges, make sure the bridge is built with libolm.

After that, simply enable the option in the config (bridgeencryption). If you only set allow: true, the bridge won't enable encryption on its own, but will work in encrypted rooms. If you set default: true, the bridge will automatically enable encryption in new portals.

Legacy instructions

Shared secret login

Prior to mautrix-telegram v0.9.0 / mautrix-python v0.8.0, you had to configure login_shared_secret. In new versions, you only need a homeserver with MSC2778 support, i.e. Synapse 1.22 or later.

Registration file workaround

In mautrix-telegram v0.8.0 release candidates, you had to manually apply a workaround for MSC2190. In newer versions (mautrix-telegram v0.8.0+, mautrix-python v0.5.0-rc3+) the workaround is applied automatically to all newly generated registration files. For old registration files, you can either regenerate the file or apply the workaround manually:

  1. Change sender_localpart in the registration to something else. Any random string will do.
  2. Add a new entry in the users array for the bridge bot (the previous value of sender_localpart). If you used the default telegrambot, the result should look something like this:
    namespaces:
        users:
        - exclusive: true
          regex: '@telegram_.+:your.homeserver'
        - exclusive: true
          regex: '@telegrambot:your.homeserver'
    
  3. Using the as_token, make a call to register the bot user. It's fine if this says the user is already in use. This step only applies to new bridges, but new bridges don't need to do this workaround.
    $ curl -H "Authorization: Bearer <as_token>" -d '{"username": "telegrambot"}' -X POST https://your.homeserver/_matrix/client/r0/register?kind=user
    

Double puppeting

You can replace the Matrix ghost of your remote account with your Matrix account. When you do so, messages that you send from other clients will be sent from your Matrix account instead of the default ghost user.

Also, in servers that don't support MSC2409 (i.e. Synapse before v1.22), it is the only way to enable bridging of ephemeral events, such as presence, typing notifications and read receipts. All of my Python-based bridges support MSC2409. However, mautrix-whatsapp does not, and therefore double puppeting is still the only way to enable bridging of ephemeral events.

Manually

Double puppeting can only be enabled after logging into the bridge. As with the normal login, you must do this in a private chat with the bridge bot.

  1. Log in on the homeserver to get an access token, for example with the command
    $ curl -XPOST -d '{"type":"m.login.password","identifier":{"type": "m.id.user", "user": "example"},"password":"wordpass","initial_device_display_name":"a fancy bridge"}' https://example.com/_matrix/client/r0/login
    
    Alternatively, you can get an existing access token from your client (Settings -> Help & About in Element Web/Desktop). However, this means double puppeting will break if you log out of that client.
  2. Send login-matrix <access token> to the bridge bot. For the Telegram bridge, send login-matrix without the access token, then send the access token in a separate message.
  3. After logging in, the default Matrix ghost of your remote account should leave rooms and your account should join all rooms the ghost was in automatically.

Automatically

Instead of requiring everyone to manually enable double puppeting, you can give the bridge access to log in on its own. This makes the process much smoother for users, and removes problems if the access token getting invalidated, as the bridge can simply automatically relogin.

  1. Set up matrix-synapse-shared-secret-auth on your Synapse.
  2. Add the login shared secret to bridgelogin_shared_secret_map in the config file under the correct server name.
    • In Go-based bridges (WhatsApp and iMessage) and in past versions of Python-based bridges, the field is called login_shared_secret, as double puppeting was only supported for local users.
  3. The bridge will now automatically enable double puppeting for all local users when they log into the bridge.

Bridge setup

These instructions are for a simple virtualenv-based setup. You can also set up with Docker, or set up systemd to run the bridge with this virtualenv setup.

Requirements

  • Python 3.7 or higher with pip and virtualenv.
  • A Matrix homeserver that supports application services (e.g. Synapse)
  • A PostgreSQL server (which you should already have for Synapse).
  • If installing optional dependencies, see the optional dependencies page.
  • mautrix-telegram: Telegram app ID and hash (get from my.telegram.org).
  • mautrix-signal: An instance of signald.
  • mautrix-amp: Node 15 or higher with yarn (for puppet script).

Production setup

  1. Create a directory for the bridge.
  2. Set up a virtual environment.
    1. Create with virtualenv -p /usr/bin/python3 . (note the dot at the end)
      • You should not use a subdirectory for the virtualenv in this production setup. The pip install step places some required files at the root of the environment.
    2. Activate with source ./bin/activate
  3. Install the bridge with pip install --upgrade mautrix-$bridge[all]
    • [all] at the end will install all optional dependencies. This includes end-to-bridge encryption, which requires libolm3. See the optional dependencies page for more info.
    • If you want the master branch instead of a release, use pip install --upgrade git+https://github.com/tulir/mautrix-$bridge.git#egg=mautrix-$bridge[all].
  4. Copy example-config.yaml to config.yaml.
  5. Update the config to your liking. You'll at least need to change the homeserver settings and permissions. If you miss something that's required, the bridge will refuse to start and tell you what's missing.
  6. Generate the appservice registration with python -m mautrix_$bridge -g. You can use the -c and -r flags to change the location of the config and registration files. They default to config.yaml and registration.yaml respectively.
  7. Add the path to the registration file (registration.yaml by default) to your Synapse's homeserver.yaml under app_service_config_files. Restart Synapse to apply changes.
  8. For mautrix-telegram and mautrix-hangouts only: Initialize the database with alembic upgrade head. If you have a custom config path, use alembic -x config=/path/to/config.yaml upgrade head.
  9. For mautrix-amp only: Set up the puppet script:
    1. Navigate to puppet and run yarn --production to install dependencies.
    2. Start the puppet script with yarn start.
  10. Run the bridge python -m mautrix_$bridge.

Upgrading

  1. Make sure you're in the virtualenv (source ./bin/activate).
  2. Run the bridge install command again (install step #2).
  3. Update the database with the command in install step #7.

Development setup

  1. Clone the repository.
  2. Optional, but strongly recommended: Set up a virtual environment.
    1. Create with virtualenv -p /usr/bin/python3 .venv
    2. Activate with source .venv/bin/activate
  3. Install dependencies with pip install -r requirements.txt
    • Optionally, add -r optional-requirements.txt to install optional dependencies. Some of the optional dependencies may need additional native packages. See the optional dependencies page for more info.
  4. Continue from step #3 of production setup.

Upgrading

  1. Make sure you're in the virtualenv (source ./bin/activate).
  2. Pull changes from Git.
  3. Update dependencies with pip install --upgrade -r requirements.txt.
    • If you installed optional dependencies, run the same pip command as when installing them, but with --upgrade
  4. Update the database with the command in install step #7.

Bridge setup with Docker

The Signal bridge requires a second docker container for signald. Instructions for setting up everything can be found on the Signal-specific Bridge setup with Docker page

The Android Messages bridge requires a second docker container for the puppet script.

Requirements

  • Docker
  • A Matrix homeserver that supports application services (e.g. Synapse)

Setup

Docker images are hosted on dock.mau.dev. Available docker tags are generally :latest, :git tag, :git commit-amd64 and :git commit-arm64. The latest and git tag specific docker tags are manifests that contain both amd64 and arm64 images.

  1. Create a directory for the bridge and cd into it: mkdir mautrix-$bridge && cd mautrix-$bridge.
    N.B. The docker image will chown its /data directory to UID 1337. The commands below mount the working directory as /data, so make sure you always run them in the correct directory.
  2. Pull the docker image with docker pull dock.mau.dev/tulir/mautrix-$bridge:<version>. Replace <version> with the version you want to run (e.g. latest or v0.6.0).
  3. Run the container for the first time, so it can create a config file for you:
    docker run --rm -v `pwd`:/data:z dock.mau.dev/tulir/mautrix-$bridge:<version>
    
  4. Update the config to your liking. You'll at least need to change the homeserver settings, appservice address and permissions.
  5. Generate the appservice registration by running the container again, same command as above.
  6. Add the path to the registration file to your Synapse's homeserver.yaml under app_service_config_files. Restart Synapse to apply changes.
  7. Run the bridge:
    docker run --restart unless-stopped -v `pwd`:/data:z dock.mau.dev/tulir/mautrix-$bridge:<version>
    
    Additionally, you should either add the bridge to the same Docker network as Synapse with --network=synapsenet, or expose the correct port with -p <port>:<port>.

Upgrading

  1. Pull the new version (setup step 1)
  2. Start the new version (setup step 7)

Docker compose

Create a directory as in step #0 and create docker-compose.yml that contains something like this:

version: "3.7"

services:
  mautrix-$bridge:
    container_name: mautrix-$bridge
    image: dock.mau.dev/tulir/mautrix-$bridge:<version>
    restart: unless-stopped
    volumes:
    - .:/data

Follow the rest of the Docker setup, but use compose commands instead of the raw docker commands: docker-compose up -d to start, docker-compose stop to stop and docker-compose pull to update.

Bridge setup with systemd

  1. Create a user for the bridge:
    $ sudo adduser --system mautrix-$bridge --home /opt/mautrix-$bridge
    
  2. Set up the bridge with the normal virtualenv setup. Make sure you use that user and home directory for the bridge.
  3. Create a systemd service file at /etc/systemd/system/mautrix-$bridge.service:
    [Unit]
    Description=mautrix-$bridge bridge
    
    [Service]
    # N.B. If you didn't create a user with the correct home directory, set this
    #      to the directory where config.yaml is (e.g. /opt/mautrix-$bridge).
    WorkingDirectory=~
    ExecStart=/opt/mautrix-$bridge/bin/python -m mautrix_$bridge
    User=mautrix-$bridge
    
    [Install]
    WantedBy=multi-user.target
    

Optional dependencies

Usage

Production setup

The pip install URLs in the production setup guide include [all] at the end by default, which means all optional dependencies will be installed by default.

If you only want specific optional dependencies, replace the all with a comma-separated list of the pip extra names (e.g. postgres,speedups).

If you don't want any optional dependencies, just remove the [all].

Development setup

To install all optional dependencies, use pip install --upgrade -r optional-requirements.txt.

To install specific optional dependencies, install the packages listed "Required packages" from the table of optional dependencies below. You can also check the expected versions of the packages from optional-requirements.txt.

Docker

The docker images contain all optional dependencies. Currently they can't be easily disabled.

List of optional dependencies

The symbol means you must also enable the feature in the config. Required packages in parentheses indicate a large dependency of the other packages.

All Python bridges

pip extra nameRequired packagesDescription
metricsprometheus_clientPrometheus metrics.
e2beasyncpg
python-olm
pycryptodome
unpaddedbase64
End-to-bridge encryption support (see native dependency below).

N.B. python-olm requires libolm3 with dev headers, Python dev headers, and a C compiler. This means libolm-dev, python3-dev and build-essential on Debian 11+ and Ubuntu 19.10+. On older Debian-based distros, install libolm-dev from backports.

If you want to avoid the dev headers, you can install the libolm3 package without -dev and get a pre-compiled python-olm from gitlab.matrix.org's PyPI registry:

pip install python-olm --extra-index-url https://gitlab.matrix.org/api/v4/projects/27/packages/pypi/simple

mautrix-telegram

pip extra nameRequired packagesDescription
speedupscryptg
cchardet
aiodns
brotli
Speed up some things, e.g. by using native crypto code.
webp_convertPillowWebP <-> PNG conversion for stickers. Also requires libwebp.
hq_thumbnailsmoviepy (numpy)High quality thumbnails for Telegram->Matrix gifs and videos. If you want to use an existing ffmpeg installation for moviepy, set the FFMPEG_BINARY environment variable before starting the bridge. If it's not set, a ffmpeg binary will be downloaded automatically.
qr_loginqrcode
Pillow
Telegram login by scanning a QR code from another device.
postgrespsycopg2Postgres database support

mautrix-facebook

pip extra nameRequired packagesDescription
animated_stickersPillowFinds the dimensions of stickers bridged from Facebook.

mautrix-hangouts

pip extra nameRequired packagesDescription
postgrespsycopg2Postgres database support

mautrix-instagram

pip extra nameRequired packagesDescription
imageconvertPillowConvert images from Matrix into JPEG so Instagram would accept them.

mautrix-signal

pip extra nameRequired packagesDescription
formattednumbersphonenumbersFormat phone numbers nicely before using as displaynames.
qrlinkqrcode
Pillow
Generate QR codes required for linking as a secondary device.
stickerssignalstickers-clientEnable bridging of Signal stickers to Matrix.

Manhole

This feature is currently only present in mautrix-telegram, but it's intended to be extended to all other Python-based bridges eventually.

The "manhole" allows server administrators to access a Python shell on a running bridge. This is a very powerful mechanism for administration and debugging.

To enable it, update the config and restart the bridge: set manhole -> enabled to true and manhole -> whitelist to the list of system UIDs you want to allow connecting. After that, send open-manhole <uid> to the bridge bot on Matrix as a bridge admin user to open the manhole for the given UID.

When the manhole is open, you can open a connection with nc -NU /var/tmp/mautrix-telegram.manhole in your normal shell. Optionally, install rlwrap and use rlwrap nc instead of nc to get a nicer prompt. To use rlwrap with Docker, run it on the host: rlwrap docker exec -i nc -NU /var/tmp/mautrix-telegram.manhole. Alternatively, you can mount the socket to the host and connect with the hosts netcat and rlwrap.

To close the connection, use Ctrl+C or exit(). To close the manhole, use the close-manhole management command or use bridge.manhole.close() inside the manhole.

Inside the manhole, bridge refers to the main class instance. Refer to the source code to see how everything works. The manhole supports top-level await expressions similar to python -m asyncio.

mautrix-telegram

Welcome to the mautrix-telegram docs!

Use the sidebar to find the relevant pages. Things that are the same for all bridges, like setting up the bridge, are right below the "Python-based bridges" header. Things specific to mautrix-telegram are under this page.

These docs are mostly targeted towards people who are hosting the bridge themselves. If you don't want to host it yourself, you can use a public instance. When using public instances, refer to their instructions and support rooms.

If you run a public instance and wish to list it here, please make a pull request.

Discussion

Matrix room: #telegram:maunium.net

Telegram chat: t.me/mautrix_telegram (bridged to Matrix room)

Authentication

Logging in

As logging in requires you to send the phone code and possibly also your 2FA password, make sure to run the commands in a management room (i.e. a room with no other users than you and the appservice bot).

If you have 2-factor auth enabled or if you are logging in with a bot token, you should use the web login, as otherwise the homeserver database will likely contain your password/token in plaintext form.

  1. Start a chat with the bridge bot (@telegrambot:example.com by default)
  2. Initiate the login process with login.
  3. The bot should tell you to use the web interface or login in-Matrix. If you have enabled both login modes in the config, the bot will give you both options.
  4. Choose the login method you want and follow the instructions under that heading, then go to the "Finally" section.

In-Matrix login

  1. Send your phone number to the room.
  2. The bot should prompt you to send your auth code to the room: send it once it does.
  3. If you have two-factor authentication enabled, again wait for the prompt and then send your password to the room.

Web login

New in version 0.2.0

  1. Click the link sent by the bot, enter your phone number and click "Request code".
  2. Enter your code and click "Sign in".
  3. If you have two-factor authentication enabled, enter your password and click "Sign in" again.

Bot token

New in version 0.3.0

You can also log in with your own relay bot. This is more limited than real accounts, but it means you can appear as yourself on Telegram without giving the bridge access to your real account.

In-Matrix

  1. Send your bot token to the room.

Web

  1. Click the link sent by the bot and click "Use bot token".
  2. Enter your bot token and click "Sign in".

Finally: If all went well, the bot should inform you of a successful login, and the bridge should start creating portal rooms for all your Telegram groups and invite you to them. The bridge won't automatically create rooms for private chats: see "Private messages" at the bottom of Creating and managing chats

Registering

New in version 0.2.0

As with login, you shouldn't register in a room with other users. Registering via the web UI is not currently possible.

Please note that Telegram might not like users who register using 3rd party clients. To avoid getting banned, it is recommended to register with a real phone number (i.e. not an online SMS service) using an official client (web/desktop/android/ios).

Registration has not been tested, but it should work like this:

  1. Request a Telegram auth code with register <phone number> <full name for Telegram>
  2. The bot should prompt you to send your auth code to the room: send it once it does.
  3. The bot should inform you of a successful registration, after which you can join groups with your own name or start private chats.

Logging out

Simply run the logout management command.

Creating and managing chats

Group chats and channels

New Matrix rooms for existing Telegram chats

New portal rooms for existing Telegram chats should be created when:

  1. The bridge is (re)started
  2. The user logs in to Telegram
  3. A message or an invite is received in the Telegram chat

If a portal room is somehow broken, you can tell the bridge to forget it using the command delete-portal. The portal room will be recreated when one of the conditions above is fulfilled. Note that automatic portal creation at startup/login is only for group chats. Private chat portals are only created when you receive a message or start a chat.

New Telegram chats for existing Matrix rooms

You can use the create command to create a new Telegram chat for an existing Matrix room.

Before running the command, make sure you have invited your appservice bot to the room, given the bot PL 100 and removed PL 100 from everyone else. As of 0.2.0, the bridge will function even without power levels.

Existing Telegram chats to existing Matrix rooms

New in version 0.2.0

Get the ID of the Telegram chat with the /id command of the relay bot. If you don't have/want a relay bot, figure out another way to get the telegram chat ID, and make sure it's prefixed (-100 for channels and - for chats). Then, run bridge <chat ID> in the room you want to bridge. Again, make sure that the appservice bot is in the room and the power levels are correct like in the previous section.

Matrix ⟷ Telegram mappings

Most Matrix actions are mapped to their Telegram counterparts. Joining, leaving, inviting and kicking are mapped as-is.

Basic power level bridging is implemented. However, there may be some issues that require restarting the bridge to properly sync the power levels. Also, the power level requirements are currently hardcoded as follows:

  • Normal groups
    • PL 0 = normal user
    • PL 50 = admin
    • PL 95 = creator
  • Supergroups and channels
    • PL 0 = normal user
    • PL 50 = moderator (i.e. admin who can't add other admins)
    • PL 75 = admin
    • PL 95 = creator

Private messages

Creating portals

There are three ways to create private chat portals:

  1. Create a room and invite the Matrix puppet of the Telegram user. The puppet should join and send confirmation of the portal creation.
  2. Use the pm command.
  3. Send or receive a message on another Telegram client.

Matrix ⟷ Telegram mappings

Most non-messaging Matrix actions are ignored in private chat portals. However, Leaving the portal will cause the portal room to be cleaned up and forgotten.

Bot commands

Initiating chats with bots is no different from initiating chats with real Telegram users.

New in version 0.2.0: The bridge will translate Matrix->Telegram bot commands at the start of the message from !command to /command.

Please note that when messaging a bot for the first time, it may expect you to run /start first. The bridge does not do this automatically.

Management commands

These commands can be used to interact with the bridge and Telegram in ways not supported by native Matrix actions.

Management commands only work if the bridge bot is in the room. This means that private chat portals do not currently support management commands.

If the room you send the command to does not have users other than you and the bridge bot, you do not have to prefix commands, i.e. you can literally write help to get the help message. If the room has more users, you must use the command prefix (!tg by default). For example: !tg help. The command prefix is always allowed even if it's not required.

Generic bridge commands

CommandUsage
helpShow this help message.
cancelCancel an ongoing action (such as login).
versionView the bridge name and version.

Authentication

Commands to authenticate with Telegram.

CommandUsage
login [mxid]Get instructions on how to log in. Admins can use the mxid parameter to log in as another user.
register <phone> <full name>Register to Telegram.
logoutLog out from Telegram.
login-matrixReplace your Telegram account's Matrix puppet with your own Matrix account.
ping-matrixPings the server with the stored matrix authentication.
pingCheck if you're logged into Telegram.
ping-botGet info of the message relay Telegram bot.
username <new username>Change your Telegram username.
session <list|terminate> [hash]View or delete other Telegram sessions.

Creating portals

Commands to make connections to Telegram chats.

CommandUsage
bridge [id]Bridge the current Matrix room to the Telegram chat with the given ID. The ID must be the prefixed version that you get with the /id command of the Telegram-side bot.
create [type]Create a Telegram chat of the given type for the current Matrix. type is either group, supergroup or channel. Defaults to group
pm <identifier>Open a private chat with the given Telegram user. identifier is either the internal ID, the username or the phone number of the Telegram user. N.B. The phone numbers you start chats with must already be in your contacts.
join <link>Join a chat with an invite link. link is a complete t.me invite link, e.g. https://t.me/telegram

Portal management

Commands to manage the Telegram chats linked to portals. These can only be used in portal rooms and will directly affect the Telegram chat linked to the portal.

Most of these commands require some admin privileges in the Telegram chat: The bot will inform you if you do not have sufficient permissions.

CommandUsage
invite-linkGet a Telegram invite link to the current chat.
upgradeUpgrade a normal Telegram group to a supergroup.
group-name <name|->Change the username of a supergroup/channel. To disable, use a dash (-) as the name.
delete-portalRemove all users from the current portal room and forget the portal. Only works for group chats; to delete a private chat portal, simply leave the room.
unbridgeRemove puppets from the current portal room and forget the portal.

Portal configuration

Some bridge settings can be set on a per-portal basis. The !tg config command is used for that.

CommandUsage
helpView this help text.
viewView the current config data.
defaultsView the default config values.
set <key> <value>Set a config value.
unset <key>Remove a config value.
add <key> <value>Add a value to an array.
del <key> <value>Remove a value from an array.

Miscellaneous things

CommandUsage
search [-r|--remote] <query>Search your contacts or the Telegram servers for users.
sync [chats|contacts|me]Synchronize your chat portals, contacts and/or own info.
sync-stateFetch Matrix room state to ensure the bridge has up-to-date info.
idGet the ID of the Telegram chat where this room is bridged.
play <play ID>Play a Telegram game.
caption <caption>Set a caption for the next image or file you send.

Administration

Bridge admin commands that do advanced things.

CommandUsage
filter-mode <whitelist|blacklist>Change whether the bridge will allow or disallow bridging rooms by default.
filter <whitelist|blacklist> <chat ID>Allow or disallow bridging a specific chat.
clean-roomsClean up unused portal/management rooms.
set-pl <level> [mxid]Set a temporary power level without affecting Telegram.
clear-db-cache <portal|puppet|user>Clear internal database caches
reload-user [mxid]Reload and reconnect a user

Relay bot

New in version 0.2.0

The bridge supports using a Telegram bot to relay messages for unauthenticated users, allowing Matrix users who are not logged into their Telegram account to chat with Telegram users.

Setup

  1. If you haven't yet, create a new bot on Telegram by chatting with @BotFather. Make sure you disable privacy mode using BotFather's /setprivacy command in order to allow the bot to read messages in groups.
  2. Configure the bridge to use the bot you created by setting the token you got from BotFather in the telegrambot_token field in the bridge's config.
  3. Restart the bridge and check status with the !tg ping-bot command on Matrix.
  4. Invite the relaybot to groups where you want it to bridge messages from unauthenticated Matrix users. If you're logged in to the bridge, you can use !tg ping-bot, click the user pill and click invite directly. If not, you can add the bot on the Telegram side.

If the room was created by the bridge and you don't have invite permissions, you can either use !tg set-pl to give yourself permissions, or !invite <mxid> to invite users through the bridge bot.

Creating relaybot portals from Telegram

You can also create portals from Telegram if you have the relay bot set up and have allowed creating portals from telegram in the config (bridgerelaybotauthless_portals). Simply invite the relay bot to your Telegram chat and use the /portal command. If the chat is public, the bot should create the portal and reply with a room alias. If the chat is private, you'll need to invite Matrix users manually with /invite <mxid>.

Message format configuration

The format of messages and membership events that the bot sends to Telegram can be configured both bridge-wide and per-room. Per-room configs can be managed using the !tg config command.

For example, to disable bridging of membership events in a room, you can run

!tg config set state_event_formats join: ''
leave: ''
name_change: ''

which sets the state_event_formats config option to an object containing the empty strings join, leave and name_change.

Commands

CommandUsage
/invite [mxid]Invite a Matrix user to the portal room.
/portalCreate the portal if it does not exist and get the join info.
/idGet the prefixed ID of the chat that can be used with !tg bridge and !tg filter in Matrix

If you have your own Telegram bot for the bridge, you can copy this to the /setcommands BotFather command:

invite - Invite a Matrix user to the portal room.
portal - Create the portal if it does not exist and get the join info.
id - Get the prefixed ID of the chat that can be used with `!tg bridge` and `!tg filter` in Matrix

Provisioning API

New in version 0.3.0

The provisioning API can be used to sign in and out, and to create and remove bridges. It is primarily intended for integration managers, such as Dimension.

You can find the API spec at https://spec.mau.fi/mxtg-provisioning/

Migrating from Telematrix

New in version 0.3.0

When migrating from Telematrix, you'll need to configure mautrix-telegram to use the same user ID format and bridge bot username. Other options, such as the AS token, port, etc.. don't need to be the same.

The database migration script is located in mautrix_telegram/scripts/telematrix_import. It can be ran using

$ python -m mautrix_telegram.scripts.telematrix_import [arguments...]

The script has three arguments:

  • -b / --bot-id (required) - The internal numeric user ID of the relay bot. This can be fetched from https://api.telegram.org/bot<BOT TOKEN>/getMe
  • -c / --config - The path to the mautrix-telegram config. Used for the database path and might be used for other values in the future (e.g. auto-fetching the bot id). Defaults to config.yaml.
  • -t / --telematrix-database - The URL of the telematrix database. Defaults to sqlite database.db

DBMS migration

New in version 0.3.0

The bridge includes a simple script for migrating between database management systems. It simply reads the data from one database and inserts it into another database.

The script is located in mautrix_telegram/scripts/dbms_migrate. It can be ran using

$ python3 -m mautrix_telegram.scripts.dbms_migrate -f <source db> -t <target db>

Both <source db> and <target db> are full database URLs, e.g. sqlite:///mautrix-telegram.db and postgres://user:password@localhost/mautrixtelegram

Steps:

  1. Stop the bridge
  2. Update the database URI in the config
  3. Initialize the new database with alembic upgrade head
    • Inside Docker, you need to be in /opt/mautrix-telegram/ and you need to pass the path to the config with alembic -x config=/data/config.yaml upgrade head
  4. Run the database migration script
  5. Start the bridge again

mautrix-facebook

Welcome to the mautrix-facebook docs!

Use the sidebar to find the relevant pages. Things that are the same for all bridges, like setting up the bridge, are right below the "Python-based bridges" header. Things specific to mautrix-facebook are under this page.

Discussion

Matrix room: #facebook:maunium.net

Authentication

  1. Open a private chat with the bridge bot. Usually @facebookbot:your.server

Web-based login

New in version 0.2.1

The bridge includes a web-based login interface to prevent the bridge and homeserver from seeing your Facebook password. The web interface must be enabled in the config to use this method (appservice->public). After web login is enabled, send login with no parameters to the bridge bot, click the link it gives, and use the login form on the website to log in.

In-Matrix login

  1. Send login <email> to the bridge bot.
    • N.B. Prior to v0.2.1, the syntax is login <email> <password>, rather than sending the password in a separate message.
  2. Send your password to the room.
  3. If you have 2FA enabled, the bot will ask you to send the 2FA token.
  4. Recent chats should now get portals automatically. Other chats will get portals as you receive messages.

Note that in some cases, Facebook might decide your account has suspicious activity and block you until you do some tasks like adding a phone number or resetting your password. In most cases, enabling two-factor authentication solves this. If that doesn't help, hosting the bridge at home or making it proxy all traffic through a residential IP can help further reduce suspiciousness. The bridge can run separately from Synapse, e.g. on a Raspberry Pi. It can also use the http_proxy environment variable for all Facebook traffic.

Upgrading to v0.2.0

Version 0.2.0 of the bridge includes some major breaking changes:

  • It uses a completely different Messenger API, which means that all users will have to log in again to keep using the bridge. Logging in happens using email and password instead of stealing cookies like before.
    • v0.2.1 includes a web-based login interface that encrypts your password in-browser to prevent the bridge from seeing it.
  • There are database schema changes that can not be reversed. Taking a backup before upgrading is recommended. Additionally, only PostgreSQL is supported, see below for SQLite migration instructions.

SQLite migration

If you're using SQLite and want to keep your existing portal rooms, you must migrate the database to Postgres first. If you don't care about keeping existing portal rooms, you can use clean-rooms for cleaning up old portals and enable backfilling in the config to get message history in the new portals.

The bridge includes a simple script similar to mautrix-telegram's DBMS migration:

$ python -m mautrix_facebook.db.legacy_migrate -f <source db> -t <target db>

Both <source db> and <target db> are full database URLs, e.g. sqlite:///mautrix-facebook.db and postgres://user:password@localhost/mautrixfacebook

Steps:

  1. Stop the bridge and update to v0.2.0
  2. Update the database URI in the config
  3. Initialize the new database with alembic upgrade head
  4. Run the database migration script
  5. Start the bridge again

mautrix-hangouts

Welcome to the mautrix-hangouts docs!

Use the sidebar to find the relevant pages. Things that are the same for all bridges, like setting up the bridge, are right below the "Python-based bridges" header. Things specific to mautrix-hangouts are under this page.

Discussion

Matrix room: #hangouts:maunium.net

Authentication

  1. Open a private chat with the bridge bot. Usually @hangoutsbot:your.server.
  2. Send login.
  3. Open the link sent by the bot and follow the instructions.
    • Automatic login may not work. If it does not, reload the page and select the "Manual login" checkbox before starting. Manual login involves logging into your Google account normally and then manually getting the OAuth token from browser cookies with developer tools.
  4. Recent chats should now get portals automatically. Other chats will get portals as you receive messages.

mautrix-twitter

Welcome to the mautrix-twitter docs!

Use the sidebar to find the relevant pages. Things that are the same for all bridges, like setting up the bridge, are right below the "Python-based bridges" header. Things specific to mautrix-twitter are under this page.

Discussion

Matrix room: #twitter:maunium.net

Authentication

  1. Open a private chat with the bridge bot. Usually @twitterbot:your.server.
  2. Log into Twitter in a private browser window.
  3. Send login-cookie to start the login.
  4. The bot will send you these instructions to extract required cookies. Follow the steps to log into the bridge:
    1. Press F12 to open developer tools.
    2. Select the "Application" (Chrome) or "Storage" (Firefox) tab.
    3. In the sidebar, expand "Cookies" and select https://twitter.com.
    4. In the cookie list, find the auth_token row and double click on the value then copy the value and send it to the room.
    5. Repeat the previous step with the ct0 row.
  5. Recent chats should now get portals automatically. Other chats will get portals as you receive messages.

mautrix-signal

Welcome to the mautrix-signal docs!

Use the sidebar to find the relevant pages. Things that are the same for all bridges, like setting up the bridge, are right below the "Python-based bridges" header. Things specific to mautrix-signal are under this page.

Discussion

Matrix room: #signal:maunium.net

Authentication

  1. Open a private chat with the bridge bot. Usually @signalbot:your.server

Linking as secondary device

  1. Go to "Linked Devices" in the Signal app settings and add a new device.
  2. Send link to the bridge bot.
  3. Scan the QR code the bridge sends you.

Registering as the primary device

  1. Send register <phone> to the bridge bot. The phone should be in the international format with no spaces.
  2. Once you get the SMS verification code, send it to the bridge.
  3. To be able to participate in v2 groups, set a profile name with set-profile-name <name>.

CAPTCHA

Refer to the signald docs on dealing with captcha required errors. The bridge supports the same --captcha parameter as signaldctl, but it must be passed before the phone number instead of after (e.g. !signal register --captcha 03AOLTBLR... +12024561414). The signalcaptcha:// part must not be included.

Signal bridge setup with Docker

Requirements

  • Docker
  • Docker Compose, or knowledge how to read a docker-compose file and run the docker containers yourself.
  • A Matrix homeserver that supports application services (e.g. Synapse)

Notes

  • These instructions use the dock.mau.dev/maunium/signald image instead of docker.io/finn/signald for signald, as the former has a more recent version of Java and a sane default data directory. The upstream image has been updated to match the maunium image.
  • By default, the bridge runs as root. You can run it as a different user, but make sure you chown all the files and make signald run as the same user.

Setup

  1. Create a directory for the bridge and cd into it: mkdir mautrix-signal && cd mautrix-signal.
  2. Create docker-compose.yml that contains something like this:
    version: "3.7"
    
    services:
      mautrix-signal:
        container_name: mautrix-signal
        image: dock.mau.dev/tulir/mautrix-signal
        restart: unless-stopped
        volumes:
        - ./bridge:/data
        - ./signald:/signald
        depends_on:
        - signald
      signald:
        container_name: signald
        image: docker.io/finn/signald
        restart: unless-stopped
        volumes: 
        - ./signald:/signald
      db:
        image: postgres:13-alpine
        restart: unless-stopped
        environment:
          POSTGRES_USER: mautrixsignal
          POSTGRES_DATABASE: mautrixsignal
          POSTGRES_PASSWORD: foobar
        volumes:
        - ./db:/var/lib/postgresql/data
    
  3. Run docker-compose up -d signald to start signald and make sure it doesn't crash.
  4. Run docker-compose up mautrix-signal to make the bridge generate a config file for you.
  5. Update the config to your liking.
    • As usual, you'll at least need to change the homeserver settings and add yourself to the permissions section.
    • Only postgres is supported as the bridge database, so configure that too. If you use the docker-compose example above directly, use postgres://mautrixsignal:foobar@db/mautrixsignal as the database URI (but change the password to something else than foobar).
    • Additionally, you need to update the paths in the signal section:
      • socket_path is /signald/signald.sock.
      • outgoing_attachment_dir should be /signald/attachments (if you can figure out how, you could even use a shared tmpfs for that directory to avoid unencrypted files being temporarily stored on disk).
      • avatar_dir is /signald/avatars.
  6. Generate the appservice registration by running the container again, same command as above.
  7. Add the path to the registration file to your Synapse's homeserver.yaml under the app_service_config_files section.
  8. Restart Synapse to apply changes.
  9. Run docker-compose up -d to start the bridge.

Upgrading

  1. docker-compose pull
  2. docker-compose up -d

Relay mode

New in version 0.2.0

The bridge supports relaying messages for unauthenticated users through another user's Signal account.

  1. Enable relay mode by setting bridgerelayenabled to true. Also make sure that the users you want to invite have at least the relay level in the permissions section.
  2. Log into the bridge normally using the relaybot account.
    • If you want a separate Signal account for the relaybot while using your own account for your own Matrix user, you should make a dedicated Matrix account for the relaybot. If you do this, make sure to run the next command using the new Matrix account too.
  3. Run !signal set-relay in the chats where you want to use the relaybot.
  4. Use !signal set-pl 100 to be able to modify room settings and invite others.

If you want to bridge existing rooms, you'll have to manually update the mxid column in the portal table to point to the room you want bridged.

mautrix-instagram

Welcome to the mautrix-instagram docs!

Use the sidebar to find the relevant pages. Things that are the same for all bridges, like setting up the bridge, are right below the "Python-based bridges" header. Things specific to mautrix-instagram are under this page.

Discussion

Matrix room: #instagram:maunium.net

Authentication

  1. Open a private chat with the bridge bot. Usually @instagrambot:your.server
  2. Send login <email> <password>
  3. If you have 2FA enabled, the bot will ask you to send the 2FA code. If you don't have 2FA enabled, Instagram will likely ask you to confirm the login, in which case the bot will ask you to send the confirmation code.
  4. Recent chats should now get portals automatically. Other chats will get portals as you receive messages.

mautrix-whatsapp

Welcome to the mautrix-whatsapp docs!

How The Components Fit Together

Diagram of components: matrix, bridge, whatsapp, clients (Image by Азат)

This bridge is the component labeled "mautrix-whatsapp bot".

Discussion

Matrix room: #whatsapp:maunium.net

In case you need to upload your logs somewhere, be aware that they contain your contacts' and your phone numbers. Strip them out with | sed -r 's/[0-9]{10,}/📞/g'

WhatsApp bridge setup

This page contains instructions for setting up the bridge by running the executable yourself. You may also want to look at the other ways to run the bridge:

Requirements

Compilation (optional)

  • Go 1.13+ (download & installation instructions at https://golang.org/dl/)
  • Olm dev headers and a C/C++ compiler (if you want end-to-bridge encryption)

Runtime

  • A Matrix homeserver that supports application services (e.g. Synapse)
  • A WhatsApp client running on a phone or in an emulated Android VM.
  • libolm3 (if you compiled manually and want end-to-bridge encryption)
  • ffmpeg (if you want to send gifs from Matrix)

Installation

You may either compile the bridge manually or download a prebuilt executable from the mau.dev CI.

Compiling manually

  1. Clone the repo with git clone https://github.com/tulir/mautrix-whatsapp.git
  2. Enter the directory (cd mautrix-whatsapp)
  3. Run ./build.sh to fetch Go dependencies and compile (build.sh will simply call go build with some additional flags).
    • If you want end-to-bridge encryption, make sure you have a C/C++ compiler and the Olm dev headers (libolm-dev on debian-based distros) installed. Note that libolm3 is required, which means you have to use backports on Debian stable.
    • If not, use ./build.sh -tags nocrypto to disable encryption.

Downloading a prebuilt executable

  1. Go to https://mau.dev/tulir/mautrix-whatsapp/pipelines?scope=branches&page=1
  2. Find the entry for the master branch and click the download button on the right-hand side in the list.
    • The builds are all static with olm included, but SQLite may not work. Postgres is recommended anyway.
  3. Extract the downloaded zip file into a new directory.

Configuring and running

  1. Copy example-config.yaml to config.yaml
  2. Update the config to your liking.
    • You need to make sure that the address and domain field point to your homeserver.
    • You will also need to add your user under the permissions section.
  3. Generate the appservice registration file by running ./mautrix-whatsapp -g.
    • You can use the -c and -r flags to change the location of the config and registration files. They default to config.yaml and registration.yaml respectively.
  4. Add the path to the registration file (registration.yaml by default) to your synapse homeserver.yaml under app_service_config_files. You will then need to restart the synapse server. Remember to restart it every time the registration file is regenerated.
  5. Run the bridge with ./mautrix-whatsapp.

Updating

If you compiled manually, pull changes with git pull and recompile with go build.

If you downloaded a prebuilt executable, simply download a new one and replace the old one.

Finally, start the bridge again.

WhatsApp bridge setup with Docker

Requirements

  • Docker
  • A Matrix homeserver that supports application services (e.g. Synapse)

Setup

Docker images are hosted on dock.mau.dev

  1. Create a directory for the bridge and cd into it: mkdir mautrix-whatsapp && cd mautrix-whatsapp.
    N.B. The docker image will chown its /data directory to UID 1337. The commands below mount the working directory as /data, so make sure you always run them in the correct directory.
  2. Pull the docker image with docker pull dock.mau.dev/tulir/mautrix-whatsapp:latest.
  3. Run the container for the first time, so it can create a config file for you:
    docker run --rm -v `pwd`:/data:z dock.mau.dev/tulir/mautrix-whatsapp:latest
    
  4. Update the config to your liking. Don't forget to change the address and domain to match those of your server, and add yourself to the permissions section.
  5. Generate the appservice registration by running the container again, same command as above.
  6. Add the path to the registration file (registration.yaml by default) to your Synapse's homeserver.yaml under the app_service_config_files section.
  7. Restart Synapse to apply changes.
  8. Run the bridge:
    docker run --restart unless-stopped -p 29318:29318 -v `pwd`:/data:z dock.mau.dev/tulir/mautrix-whatsapp:latest
    
    N.B. If using postgres database hosted at localhost/127.0.0.1 (outside the container), then use --network=host to avoid errors like dial tcp 127.0.0.1:5432: connect: connection refused

Upgrading

  1. Pull the new version (setup step 1)
  2. Start the new version (setup step 7)

WhatsApp bridge setup with systemd

  1. Create a user for the bridge:
    $ sudo adduser --system mautrix-whatsapp --home /opt/mautrix-whatsapp
    
  2. Set up the bridge with the normal setup. Make sure you use that user and home directory for the bridge.
  3. Create a systemd service file at /etc/systemd/system/mautrix-whatsapp.service:
    [Unit]
    Description=mautrix-whatsapp bridge
    
    [Service]
    Type=exec
    User=mautrix-whatsapp
    WorkingDirectory=/opt/mautrix-whatsapp
    ExecStart=/opt/mautrix-whatsapp/mautrix-whatsapp
    Restart=on-failure
    RestartSec=30s
    
    # Optional hardening to improve security
    ReadWritePaths=/opt/mautrix-whatsapp
    NoNewPrivileges=yes
    MemoryDenyWriteExecute=true
    PrivateDevices=yes
    PrivateTmp=yes
    ProtectHome=yes
    ProtectSystem=strict
    ProtectControlGroups=true
    RestrictSUIDSGID=true
    RestrictRealtime=true
    LockPersonality=true
    ProtectKernelLogs=true
    ProtectKernelTunables=true
    ProtectHostname=true
    ProtectKernelModules=true
    PrivateUsers=true
    ProtectClock=true
    SystemCallArchitectures=native
    SystemCallErrorNumber=EPERM
    SystemCallFilter=@system-service
    
    [Install]
    WantedBy=multi-user.target
    

Android VM setup

This page documents how to setup WhatsApp in an Android Virtual Machine. It could be useful if you cannot or don't want to run WhatsApp on a mobile phone.

If you're running WhatsApp already and are OK with your current setup, then you can ignore this page and just connect mautrix-whatsapp to your existing WhatsApp instance.

Requirements

You'll need a working Android SDK. You can use the Android Studio suite or only the command-line tools.

Currently the Android SDK appears to only work with OpenJDK8 (not 11), which will need to be installed.

WhatsApp in the in the Android VM will need to scan a QR-code via webcam. We can do this by passing the emulator a real webcam (which needs to be able to see the emulator screen) or a virtual one (e.g. v4l2loopback).

Android Virtual Device

Let's create an AVD (Android Virtual Device), get its webcam working and install WhatsApp.

Create the AVD

WhatsApp currently requires Android 2.3.3 (API 10) or newer. If you wish to install WhatsApp through the play store, choose a System Image supporting Google APIs.

The AVD will be created in ~/.android/avd/, regardless of the method you use to create it.

Using Android Studio

Android Studio offers an AVD Manager interface to create, configure and run AVDs.

Via command line

It's also possible to create an emulated android device from command line, using avdmanager from the Android SDK:

Install the required SDK components

Change the version and architecture as required. If your host has KVM support you should use the x86 target. If you don't have KVM support (running in certain VPS systems) then you will need to use the ARM targets.

./tools/bin/sdkmanager --install platform-tools
./tools/bin/sdkmanager --install "platforms;android-24"
./tools/bin/sdkmanager --install "system-images;android-24;default;armeabi-v7a"

Once you have the SDK setup you can create a VM.

./tools/bin/avdmanager create avd -n AVD_NAME -k SDK_ID

Run the AVD using the Android Emulator:

./emulator/emulator -show-kernel -no-boot-anim -avd AVD_NAME

Set up the webcam

Android Emulator seems to support different ways to feed custom images/videos to the Android Webcam, but somehow the only one that worked for me is passing it the host's camera (i.e. using webcam0 camera mode).

webcam0 seems to always be connected to the device /dev/video0. In case you wish to use a different device (e.g. /dev/video2), rename it to /dev/video0:

# needed if you want to feed /dev/video2 to the AVD
sudo mv /dev/video0 /dev/video0.original
sudo mv /dev/video2 /dev/video0

Set the back-camera mode to webcam0, either using the AVD Manager GUI (enable Show Advanced Settings) or by running the emulator from command line:

./emulator/emulator -avd AVD_NAME -camera-back webcam0

Use v4l2loopback to create a virtual camera

Install the v4l2loopback module and load it:

modprobe v4l2loopback

This should create a new /dev/video* file. If needed, rename it as /dev/video0.

Feed your desktop into this virtual webcam, e.g. using:

ffmpeg -f x11grab -s 640x480 -i :0.0+10,20 -vf format=pix_fmts=yuv420p -f v4l2 /dev/video0

You can test whether it's working by watching your webcam (e.g. with mplayer tv:// -tv driver=v4l2:device=/dev/video0).

The AVD's webcam should now show a piece of your desktop. When mautrix-whatsapp (or WhatsApp Web) shows you the QR-code, just move its window onto the shared desktop area.

Boot the AVD

You can boot the AVD using the AVD Manager GUI, or calling the emulator via command line:

./emulator/emulator -avd AVD_NAME [options]

Some useful options include:

  • -no-audio and -no-window, to disable audio and video for the VM. With these the emulator can run headless.
  • -show-kernel, display the console boot text instead of showing the boot GUI
  • -no-snapshot, to cold boot the AVD (i.e. it will ignore some cache).
  • -memory MB, to reduce the amount of RAM passed to the AVD. Unfortunately the emulator will force a minimum amount.

Install WhatsApp

WhatsApp will only work with your phone number on a device per time: when you log in on your AVD, the other devices will disconnect. If you install WhatsApp on an AVD and copy such AVD, both copies will be able to run WhatsApp (although not at the same time!)

WhatsApp can be installed using Google Play, if available, or with an APK. In the latter case, just drag'n'drop the APK on the emulator's window or run adb install APK_FILE.

In the 'Chats screen' goto 'Menu' > 'WhatsApp Web'. You can follow the instructions and use WhatsApp Web to verify whether all is working.

You can now proceed to link your virtual android to the bridge as described on the authentication Page.

NOTE: The bridge will cycle through multiple QR codes, you have to have everything ready to go. You won't have time to copy/paste images so you will need the VM and the Matrix client running on the same desktop.

Running Headless

Once everything is working, you can run the Android emulator headless, and even copy it to a server or whatever.

Make sure that all the software we need (Android SDK, Emulator, system images etc) is installed on the target host.

Copy your AVD over there (from ~/.android/avd/AVD_NAME.* on your system to the ~/.android/avd/ of the target host).

Run the emulator headless:

./emulator/emulator -avd AVD_NAME -no-audio -no-window [options]

If your AVD goes into sleep-mode or becomes unresponsive, you can try to reboot it or to start WhatsApp main activity running am start -n 'com.whatsapp/.HomeActivity' on your AVD (or e.g. adb [-s DEVICE_SERIAL] shell am start -n 'com.whatsapp/.HomeActivity' directly on your shell).

Required packages

Here a list of the packages you'll need to install on various Linux distributions to make everything work.

Arch Linux

Either install android-studioAUR or:

You might want to choose jdk8-openjdk as java-environment, as newer JDKs seem to have problems with the Android stuff.

Note that android-studio and the other packages aren't fully compatible: the system image path will differ slightly and you'll need to fix it in the AVD config.ini files: image.sysdir.1 should be something like system-images/android-15/default/x86/ for Android Studio images, and system-images/android-15/x86/ for AUR system images. The emulator will otherwise fail printing Cannot find AVD system path. Please define ANDROID_SDK_ROOT.

Install v4l2loopback-dkms-gitAUR to use v4l2loopback.

Authentication

  1. Open a private chat with the bridge bot. Usually @whatsappbot:your.server
  2. Send login to start the login.
  3. Log in by scanning the QR code. If the code expires before you scan it, the bridge will send an error to notify you.
    1. Open WhatsApp on your phone.
    2. Tap Menu or Settings and select WhatsApp Web.
    3. Point your phone at the image sent by the bot to capture the code.
  4. Finally, the bot should inform you of a successful login and the bridge should start creating portal rooms for your recent WhatsApp groups and private chats.

Please note that the bridge uses the web API, so your phone must be connected to the internet for the bridge to work. The WhatsApp app doesn't need to be running all the time, but it needs to be allowed to wake up when receiving messages. The web API is used instead of the main client API to avoid getting banned.

Logging out

Simply run the logout management command.

Relaybot

Configuration

  1. Create a new room for relaybot management and get its internal ID (Room settings → Advanced → Internal room ID in Element Web).
  2. Enable the relaybot and set the management room ID in the relaybot config.
  3. Optionally, add your Matrix account to the invites list in the config to get invited to the automatically created portal rooms for the relaybot.
  4. Make sure the users you want to let into rooms have at least the relaybot permission in the permissions section.
  5. You may also want to set allow_user_invite to true so that you can invite more users to portals created by the bridge. The option is not applied retroactively, but you can use !wa set-pl to make yourself admin in existing rooms.
  6. Restart the bridge and invite the bridge bot to the management room you created.

Logging in

Note that only one user can be logged in with one WhatsApp account at a time, i.e. you can't use the same account for yourself and the relaybot. If you're currently logged in normally, use !wa logout in your normal (not relaybot) management room before logging in with the relaybot.

  1. Commands in the relaybot management room will always affect the relaybot instead of your own account, so simply use the normal !wa login command to make the relaybot log into WhatsApp.
  2. Like with normal login, the relaybot will sync all WhatsApp chats. For newly created portals, everyone in the invites list (mentioned earlier) will be invited.

You can either invite more Matrix users to the automatically created portals or see below for instructions on bridging existing Matrix rooms.

Creating a new WhatsApp group for an existing Matrix room

There are currently a few bugs that affect this:

  • You can only invite the bridge bot to an empty room (#208).
  • You can only create groups in encrypted rooms due to a bug in the bridge (#209).
  1. Invite the bridge bot to the Matrix room.
  2. Invite the ghosts of any WhatsApp users you want in the group right away.
  3. Make sure the room has a name.
  4. Run !wa create (or !wa relaybot create to create it through the relaybot)

Bridging an existing Matrix room to an existing WhatsApp group

Bridging to existing groups is not currently implemented. However, you can fairly easily modify the database to point the bridge at a different room.

TODO: the bridge bot probably needs inviting at some point

  1. Find the JID of the WhatsApp group you want to bridge using !wa relaybot list groups (or just !wa list groups in the relaybot management room). If you can not find it just search for it in the database (e.g. sqlite3 /matrix/mautrix-whatsapp/data/mautrix-whatsapp.db then SELECT * FROM portal WHERE name='WhatsApp_Group_Name'; the first column is the jid).
  2. Find the internal ID of the target matrix room (Room settings → Advanced → Internal room ID in Element Web) for example !bJUfgWQZfgLWtXQqHzZxp:example.com
  3. Stop the bridge. (make sure it is actually stopped, possible commands for this using Docker or Ansible: docker ps -a or with systemctl status matrix-mautrix-whatsapp.service, possible commands to stop docker stop containerID, systemctl stop matrix-mautrix-whatsapp.service)
  4. Run UPDATE portal SET mxid='<target room id>' WHERE jid='groupid@g.us'; in the database. (Possible command to enter the db sqlite3 /matrix/mautrix-whatsapp/data/mautrix-whatsapp.db)
  5. Start the bridge. The bridge should automatically sync the group members from WhatsApp and messages should be bridged in both directions. If not, add the WhatsApp bridge bot to the room. (@whatsappbot:example.com)

mautrix-imessage

Welcome to the mautrix-imessage docs!

Discussion

Matrix room: #imessage:maunium.net

iMessage bridge setup (macOS)

Requirements

Compilation (optional)

  • Go 1.13+ (download & installation instructions at https://golang.org/dl/)
  • libolm3 with dev headers (brew install libolm)

Runtime

  • A computer running a reasonably new version of macOS.
    • The bridge requires full disk access in privacy settings to read your chat database.
  • A Matrix homeserver that supports application services (e.g. Synapse).
  • A websocket proxy to receive appservice transactions.

Installation

You may either compile the bridge manually or download a prebuilt executable from the mau.dev CI.

Compiling manually

  1. Clone the repo with git clone https://github.com/tulir/mautrix-imessage.git.
  2. Enter the directory (cd mautrix-imessage).
  3. Run ./build.sh to fetch Go dependencies and compile (build.sh will simply call go build with some additional flags).

Downloading a prebuilt executable

  1. Go to https://mau.dev/tulir/mautrix-imessage/pipelines?scope=branches&page=1
  2. Find the entry for the master branch and click the download button on the right-hand side in the list.
    • There are three entries: universal, arm64 (Apple Silicon) and amd64 (Intel). You can either pick universal, or the specific architecture depending on what Mac you have.
  3. Extract the downloaded zip file into a new directory.

Configuring and running

  1. Copy example-config.yaml to config.yaml
  2. Update the config to your liking.
    • You need to make sure that the address and domain field point to your homeserver.
    • You will also need to add your user ID to the bridge section.
  3. Generate the appservice registration file by running ./mautrix-imessage -g.
    • You can use the -c and -r flags to change the location of the config and registration files. They default to config.yaml and registration.yaml respectively.
  4. Set up mautrix-wsproxy.
  5. Update your registration file so the url field points to wsproxy (e.g. http://localhost:29331), and make sure the websocket_proxy field in the bridge config also points to wsproxy (e.g. ws://matrix.example.com:29331).
  6. Add the path to the registration file (registration.yaml by default) to your synapse homeserver.yaml under app_service_config_files. You will then need to restart the synapse server. Remember to restart it every time the registration file is regenerated.
  7. Run the bridge with ./mautrix-imessage.
  8. If/when the bridge fails to initialize the iMessage connector with the operation not permitted error, go to System Preferences -> Security & Privacy -> Privacy -> Full Disk Access and grant access to the terminal you're running the bridge in.

iMessage bridge setup (iOS)

Requirements

  • A jailbroken iOS device, minimum and recommended is iPhone 4S with iOS 8.4(.1).
  • A Matrix homeserver that supports application services (e.g. Synapse).
  • A websocket proxy to receive appservice transactions.

Installation

The bridge consists of two components: Brooklyn for connecting to iMessage and mautrix-imessage for connecting to Matrix. The Brooklyn app runs mautrix-imessage as a subprocess and they communicate over stdio.

The recommended way to install the app is getting a precompiled build from the Cydia repo. You can technically also compile everything yourself, but that is less documented.

Compiling manually

There are instructions for compiling Brooklyn in the GitLab repo.

Compiling mautrix-imessage for darwin/armv7 is more complicated and not currently documented. For more recent devices (i.e. armv8/arm64), it should be as simple as compiling mautrix-imessage on a Mac with Apple Silicon.

Precompiled builds

You can get the Brooklyn app with a bundled mautrix-imessage from the Cydia repo. The repo is currently available at http://beeper.gitlab.io/brooklyn/. After adding the repo in Cydia, simply install the "Brooklyn" package from the repo.

Configuring and running

  1. Get the example config and fill it out. You'll at least need to:
    • Fill everything in the homeserver section.
    • Set bridge -> user to your MXID.
    • Change imessage -> platform to ios.
    • Generate random tokens for the as_token and hs_token fields.
  2. Get the example registration and copy the relevant values from the config.
  3. Set up mautrix-wsproxy.
  4. Add the path to the registration file to your Synapse homeserver.yaml under app_service_config_files, then restart Synapse.
  5. Serve the config file with the webserver of your choice. It's recommended to use a random file name or add HTTP basic auth to prevent other people from reading your config.
  6. Generate a QR code with the URL to your config (e.g. echo -n https://user:pass@example.com/your-config.yaml | qrencode -t ansiutf8).
  7. Scan the QR code with Brooklyn.

SMS forwarding on iOS

If you're running the bridge on an old jailbroken iPhone, but want to keep your SIM card in your main iPhone, you can use iMessage's SMS forwarding feature to still send and receive text messages through the bridge.

By default, outgoing SMSes will only be forwarded on non-iPhone devices, and it'll just throw a no sim card installed error if you try to send an SMS. However, Brooklyn includes a bypass that can make the iPhone act like iPads and Macs and forward the SMS through another iPhone.

To enable the bypass:

  1. Deactivate iMessage (Settings -> Messages -> switch off "iMessage").
  2. Enable the bypass in Settings -> Brooklyn.
  3. Reset network settings (Settings -> General -> Reset -> Reset Network Settings).
    • The iPhone will forget your Wi-Fi settings and reboot.
  4. Set up your Wi-Fi connection again.
  5. Reactivate iMessage (same switch as step 1).