Matrix gateway setup with ejabberd

As of version 24.02, ejabberd is shipped with a Matrix gateway and can participate in the Matrix federation. This means that an XMPP client can exchange messages with Matrix users or rooms. Let’s see how to configure your ejabberd to enable this gateway.

Jérôme Sautret
· 3 min read
Send by email

Configuration in ejabberd

HTTPS listener

First, add an HTTP handler, as Matrix uses HTTPS for Server-Server API.

In the listen section of your ejabberd.yml configuration file, add a handler on Matrix port 8448 for path /_matrix that calls the mod_matrix_gw module. You must enable TLS on this port to accept HTTPS connections (unless a proxy already handles HTTPS in front of ejabberd) and provide a valid certificate for your Matrix domain (see matrix_domain below). You can set this certificate using the certfile option of the listener, like in the example below, or listing it in the certfiles top level option.

Example:

listen:
  -
    port: 5222
    module: ejabberd_c2s
  -
    port: 8448 # Matrix federation
    module: ejabberd_http
    tls: true
    certfile: "/opt/ejabberd/conf/matrix.pem"
    request_handlers:
      "/_matrix": mod_matrix_gw

If you want to use a non-standard port instead of 8448, you must serve a /.well-known/matrix/server on your Matrix domain (see below).

Server-to-Server

You must enable s2s (Server-to-Server federation) by setting an access rule all or allow on s2s_access top level option:

Example:

s2s_access: s2s

access_rules:
  local:
    - allow: local
  c2s:
    - deny: blocked
    - allow
  s2s:
    - allow # to allow Matrix federation

Matrix gateway module

Finally, add mod_matrix_gw module in the modules list.

Example:

modules:
  mod_matrix_gw:
    matrix_domain: "matrixdomain.com"
    key_name: "key1"
    key: "SU4mu/j8b8A1i1EdyxIcKlFlrp+eSRBIlZwGyHP7Mfo="

matrix_domain

Replace matrixdomain.com with your Matrix domain. That domain must resolve to your ejabberd server or serve a file https://matrixdomain.com/.well-known/matrix/server that contains a JSON file with the address and Matrix port (as defined by the Matrix HTTPS handler, see above) of your ejabberd server:

Example:

{
   "m.server": "ejabberddomain.com:8448"
}

key_name & key

The key_name is arbitrary. The key value is your base64-encoded ed25519 Matrix signing key. It can be generated by Matrix tools or in an Erlang shell using the command base64:encode(element(2, crypto:generate_key(eddsa, ed25519))).:

Example:

$ erl
Erlang/OTP 24 [erts-12.3.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [dtrace]

Eshell V12.3.1 (abort with ^G)
1> base64:encode(element(2, crypto:generate_key(eddsa, ed25519))).
<<"SU4mu/j8b8A1i1EdyxIcKlFlrp+eSRBIlZwGyHP7Mfo=">>
2> q().
ok

Once your configuration is ready, you can restart ejabberd.

Testing

To check if your setup is correct, go to the following page and enter your Matrix domain (as set by the matrix_domain option):
https://federationtester.matrix.org/

This page should list any problem related to Matrix on your ejabberd installation.

Routing

What messages are routed to an external Matrix server?

Implicit routing

Let’s say an XMPP client connected to your ejabberd server sends a message to a JID user1@domain1.com. If domain1.com is defined by the hosts parameter of your ejabberd server (i.e. it’s one of your XMPP domains), the message will be routed locally. If it’s not, ejabberd will try to establish an XMPP Server-to-Server connection to a remote domain1.com XMPP server. If this fails (i.e. there is no such external domain1.com XMPP domain), then ejabberd will try on the Matrix federation, transforming the user1@domain1.com JID into the Matrix ID @user1:domain1.com and will try to open a connection to a remote domain1.com Matrix domain.

Explicit routing

It is also possible to route messages explicitly to the Matrix federation by setting the option matrix_id_as_jid in the mod_matrix_gw module to true:

Example:

modules:
  mod_matrix_gw:
    host: "matrix.@HOST@"
    matrix_domain: "matrixdomain.com"
    key_name: "key1"
    key: "SU4mu/j8b8A1i1EdyxIcKlFlrp+eSRBIlZwGyHP7Mfo="
    matrix_id_as_jid: true

In this case, the automatic fallback to Matrix when XMPP s2s fails is disabled and messages must be explicitly sent to the matrix gateway service Jabber ID to be routed to a remote Matrix server.

To send a message to the Matrix user @user:remotedomain.com, the XMPP client must send a message to the JID user%remotedomain.com@matrix.xmppdomain.com, where matrix.xmppdomain.com is the JID of the gateway service as set by the host option of the mod_matrix_gw module (the keyword @HOST@ is replaced with the XMPP domain of the server). If host is not set, the Matrix gateway JID is your XMPP domain with the matrix. prefix added.

The default value for matrix_id_as_jid is false, so the implicit routing will be used if this option is not set.