Mautrix-Signal Bridge (Docker-Compose) auf einer nativen Matrix-Synapse Instanz auf Ubuntu 20.04

Dies soll ein Workaround sein. Alle Angaben natürlich ohne Gewähr. Die Quellen für das Workaround sind

https://docs.mau.fi/bridges/index.html

https://signald.org/

https://gitlab.com/signald/captcha-helper

https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-20-04-de

https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-compose-on-ubuntu-20-04-de

https://github.com/mautrix/signal

Ich gehe davon aus das bereits eine native (OHNE Docker oder Docker-Compose) Matrix-Synapse Instanz funktionsfähig z.B. auf Ubuntu 20.04 läuft.

Ebenso gehe ich davon aus das Backups vorhanden sind die im Notfall wiederhergestellt werden können. Kein Backup, kein Mitleid :-)

Voraussetzung für die Mautrix-Signal Bridge ist eine Docker und Docker-Compose installation auf der selben Maschine auf der auch Matrix-Synapse nativ läuft. Im Beispiel gehe ich hier von Ubuntu 20.04 aus.

Falls ihr kein „sudo“ benutzen wollt streicht diesen Schritt, dann müsst Ihr aber in allen folgenden Befehlen das sudo weglassen.

apt install sudo

sudo apt install apt-transport-https ca-certificates curl software-properties-common

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"

sudo apt update

sudo apt install docker-ce

sudo curl -L "https://github.com/docker/compose/releases/download/v2.4.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

sudo chmod +x /usr/local/bin/docker-compose

Jetzt sind normalerweise Docker und Docker-Compose installiert und lauffähig.

Nun erstellen wir einen Ordner für die Mautrix-Signal Bridge im System. Am Beispiel erstelle ich den Ordner in /etc da hier auch die native Matrix-Synapse installation liegt. Natürlich kann dies auch in /opt oder irgendwo liegen.

mkdir /etc/mautrix-signal && cd /etc/mautrix-signal

Nun erstellen wir eine "docker-compose.yml" Datei für Docker-Compose.

nano docker-compose.yml

Hier fügen wir folgenden Inhalt ein. Die stellen die ich mit 111, 222 oder 333 usw. kennzeichne bitte nach den eigenen bedürfnissen abändern. Die Inhalte müssen dann später an anderer stelle nochmal verwendet werden.

version: "3.7"services:  mautrix-signal:    container_name: mautrix-signal    image: dock.mau.dev/mautrix/signal:latest    restart: unless-stopped    volumes:    - ./bridge:/data    - ./signald:/signald    depends_on:    - signald    # If synapse is running outside of docker, you'll need to expose the port.    # Note that in most cases you should either run everything inside docker    # or everything outside docker, rather than mixing docker things with    # non-docker things.    ports:    - "29328:29328"    # You'll also probably want this so the bridge can reach Synapse directly    # using something like `http://host.docker.internal:8008` as the address:    #extra_hosts:    #- "host.docker.internal:host-gateway"    # If synapse is in a different network, then add this container to that network.    # Note the networks object at the bottom too.    #networks:    #- default  # keep the container in the default network too so that the db container is reachable.    #- synapsenet  signald:    container_name: signald    image: docker.io/signald/signald:latest    restart: unless-stopped    volumes:     - ./signald:/signald  db:    image: postgres:13-alpine    restart: unless-stopped    environment:      POSTGRES_USER: mautrixsignal111      POSTGRES_DATABASE: mautrixsignal222      POSTGRES_PASSWORD: password333    volumes:    - ./db:/var/lib/postgresql/data# When synapse is in a different network (note the networks object in the service too):#networks:#  synapsenet:#    external:#      name: synapsenet

danach mit "STRG+X" und "Y" oder "J" speichern und verlassen.

Jetzt kann der "signald" Container schon mal gestartet werden.

docker-compose up -d signald

Nun können wir auch den "Mautrix-Signal" Container das erste mal starten.

docker-compose up mautrix-signal

Es sollte nun unter /etc/mautrix-signal/bridge/ eine config.yaml erstellt worden sein.

Wir stoppen den Mautrix-Signal Container wieder um in ruhe die config.yaml zu bearbeiten.

docker-compose stop mautrix-signal

nano /etc/mautrix-signal/bridge/config.yaml

Die config.yaml sollte so aussehen. Ich habe wichtige stellen mit 111 oder 222 aus der docker-compose.yml oder XXX markiert die unbedingt nach den eigenen Angaben abgeändert werden sollten.

# Homeserver detailshomeserver:    # The address that this appservice can use to connect to the homeserver.    address: https://XXX.XXX    # The domain of the homeserver (for MXIDs, etc).    domain: XXX.XXX    # Whether or not to verify the SSL certificate of the homeserver.    # Only applies if address starts with https://    verify_ssl: true    asmux: false    # Number of retries for all HTTP requests if the homeserver isn't reachable.    http_retry_count: 4    # The URL to push real-time bridge status to.    # If set, the bridge will make POST requests to this URL whenever a user's Signal connection state changes.    # The bridge will use the appservice as_token to authorize requests.    status_endpoint: null    # Endpoint for reporting per-message status.    message_send_checkpoint_endpoint: null    # Maximum number of simultaneous HTTP connections to the homeserver.    connection_limit: 100# Application service host/registration related details# Changing these values requires regeneration of the registration.appservice:    # The address that the homeserver can use to connect to this appservice.    address: http://localhost:29328    # When using https:// the TLS certificate and key files for the address.    tls_cert: false    tls_key: false    # The hostname and port where this appservice should listen.    hostname: 0.0.0.0    port: 29328    # The maximum body size of appservice API requests (from the homeserver) in mebibytes    # Usually 1 is enough, but on high-traffic bridges you might need to increase this to avoid 413s    max_body_size: 1    # The full URI to the database. SQLite and Postgres are supported.    # However, SQLite support is extremely experimental and should not be used.    # Format examples:    #   SQLite:   sqlite:///filename.db    #   Postgres: postgres://username:password@hostname/dbname    database: postgres://mautrixsignal111:password333@db/mautrixsignal222    # Additional arguments for asyncpg.create_pool() or sqlite3.connect()    # https://magicstack.github.io/asyncpg/current/api/index.html#asyncpg.pool.create_pool    # https://docs.python.org/3/library/sqlite3.html#sqlite3.connect    # For sqlite, min_size is used as the connection thread pool size and max_size is ignored.    database_opts:        min_size: 5        max_size: 10    # The unique ID of this appservice.    id: signal    # Username of the appservice bot.    bot_username: signalbot    # Display name and avatar for bot. Set to "remove" to remove display name/avatar, leave empty    # to leave display name/avatar as-is.    bot_displayname: Signal Bridge Bot    bot_avatar: mxc://maunium.net/wPJgTQbZOtpBFmDNkiNEMDUp    # Community ID for bridged users (changes registration file) and rooms.    # Must be created manually.    #    # Example: "+signal:example.com". Set to false to disable.    community_id: false    # Whether or not to receive ephemeral events via appservice transactions.    # Requires MSC2409 support (i.e. Synapse 1.22+).    # You should disable bridge -> sync_with_custom_puppets when this is enabled.    ephemeral_events: false    # Authentication tokens for AS <-> HS communication. Autogenerated; do not modify.    as_token: "This value is generated when generating the registration"    hs_token: "This value is generated when generating the registration"# Prometheus telemetry config. Requires prometheus-client to be installed.metrics:    enabled: false    listen_port: 8000# Manhole config.manhole:    # Whether or not opening the manhole is allowed.    enabled: false    # The path for the unix socket.    path: /var/tmp/mautrix-signal.manhole    # The list of UIDs who can be added to the whitelist.    # If empty, any UIDs can be specified in the open-manhole command.    whitelist:    - 0signal:    # Path to signald unix socket    socket_path: /signald/signald.sock    # Directory for temp files when sending files to Signal. This should be an    # absolute path that signald can read. For attachments in the other direction,    # make sure signald is configured to use an absolute path as the data directory.    outgoing_attachment_dir: /signald/attachment    # Directory where signald stores avatars for groups.    avatar_dir: /signald/avatars    # Directory where signald stores auth data. Used to delete data when logging out.    data_dir: ~/.config/signald/data    # Whether or not unknown signald accounts should be deleted when the bridge is started.    # When this is enabled, any UserInUse errors should be resolved by restarting the bridge.    delete_unknown_accounts_on_start: false    # Whether or not message attachments should be removed from disk after they're bridged.    remove_file_after_handling: true    # Whether or not users can register a primary device    registration_enabled: true    # Whether or not to enable disappearing messages in groups. If enabled, then the expiration    # time of the messages will be determined by the first users to read the message, rather    # than individually. If the bridge has a single user, this can be turned on safely.    enable_disappearing_messages_in_groups: false# Bridge configbridge:    # Localpart template of MXIDs for Signal users.    # {userid} is replaced with an identifier for the Signal user.    username_template: "signal_{userid}"    # Displayname template for Signal users.    # {displayname} is replaced with the displayname of the Signal user, which is the first    # available variable in displayname_preference. The variables in displayname_preference    # can also be used here directly.    displayname_template: "{displayname} (Signal)"    # Whether or not contact list displaynames should be used.    # Possible values: disallow, allow, prefer    #    # Multi-user instances are recommended to disallow contact list names, as otherwise there can    # be conflicts between names from different users' contact lists.    contact_list_names: disallow    # Available variables: full_name, first_name, last_name, phone, uuid    displayname_preference:    - full_name    - phone    # Whether or not to create portals for all groups on login/connect.    autocreate_group_portal: true    # Whether or not to create portals for all contacts on login/connect.    autocreate_contact_portal: false    # Whether or not to use /sync to get read receipts and typing notifications    # when double puppeting is enabled    sync_with_custom_puppets: true    # Whether or not to update the m.direct account data event when double puppeting is enabled.    # Note that updating the m.direct event is not atomic (except with mautrix-asmux)    # and is therefore prone to race conditions.    sync_direct_chat_list: false    # Allow using double puppeting from any server with a valid client .well-known file.    double_puppet_allow_discovery: false    # Servers to allow double puppeting from, even if double_puppet_allow_discovery is false.    double_puppet_server_map:        exampleXXX.comXXX: https://exampleXXX.comXXX    # Shared secret for https://github.com/devture/matrix-synapse-shared-secret-auth    #    # If set, custom puppets will be enabled automatically for local users    # instead of users having to find an access token and run `login-matrix`    # manually.    # If using this for other servers than the bridge's server,    # you must also set the URL in the double_puppet_server_map.    login_shared_secret_map:        example.comXXX: fooXXX PASSWORT AUS DER /etc/matrix-synapse/homeserver.yaml unter shared_secret XXX    # Whether or not created rooms should have federation enabled.    # If false, created portal rooms will never be federated.    federate_rooms: true    # End-to-bridge encryption support options. You must install the e2be optional dependency for    # this to work. See https://github.com/tulir/mautrix-telegram/wiki/End‐to‐bridge-encryption    encryption:        # Allow encryption, work in group chat rooms with e2ee enabled        allow: true        # Default to encryption, force-enable encryption in all portals the bridge creates        # This will cause the bridge bot to be in private chats for the encryption to work properly.        default: false        # Options for automatic key sharing.        key_sharing:            # Enable key sharing? If enabled, key requests for rooms where users are in will be fulfilled.            # You must use a client that supports requesting keys from other users to use this feature.            allow: false            # Require the requesting device to have a valid cross-signing signature?            # This doesn't require that the bridge has verified the device, only that the user has verified it.            # Not yet implemented.            require_cross_signing: false            # Require devices to be verified by the bridge?            # Verification by the bridge is not yet implemented.            require_verification: true    # Whether or not to explicitly set the avatar and room name for private    # chat portal rooms. This will be implicitly enabled if encryption.default is true.    private_chat_portal_meta: false    # Whether or not the bridge should send a read receipt from the bridge bot when a message has    # been sent to Signal. This let's you check manually whether the bridge is receiving your    # messages.    # Note that this is not related to Signal delivery receipts.    delivery_receipts: false    # Whether or not delivery errors should be reported as messages in the Matrix room. (not yet implemented)    delivery_error_reports: false    # Set this to true to tell the bridge to re-send m.bridge events to all rooms on the next run.    # This field will automatically be changed back to false after it,    # except if the config file is not writable.    resend_bridge_info: false    # Interval at which to resync contacts (in seconds).    periodic_sync: 0    # Provisioning API part of the web server for automated portal creation and fetching information.    # Used by things like mautrix-manager (https://github.com/tulir/mautrix-manager).    provisioning:        # Whether or not the provisioning API should be enabled.        enabled: true        # The prefix to use in the provisioning API endpoints.        prefix: /_matrix/provision/v1        # The shared secret to authorize users of the API.        # Set to "generate" to generate and save a new token.        shared_secret: generate    # The prefix for commands. Only required in non-management rooms.    command_prefix: "!signal"    # Messages sent upon joining a management room.    # Markdown is supported. The defaults are listed below.    management_room_text:        # Sent when joining a room.        welcome: "Hello, I'm a Signal bridge bot."        # Sent when joining a management room and the user is already logged in.        welcome_connected: "Use `help` for help."        # Sent when joining a management room and the user is not logged in.        welcome_unconnected: "Use `help` for help or `register` to log in."        # Optional extra text sent when joining a management room.        additional_help: ""    # Send each message separately (for readability in some clients)    management_room_multiple_messages: false    # Permissions for using the bridge.    # Permitted values:    #      relay - Allowed to be relayed through the bridge, no access to commands.    #       user - Use the bridge with puppeting.    #      admin - Use and administrate the bridge.    # Permitted keys:    #        * - All Matrix users    #   domain - All users on that homeserver    #     mxid - Specific user    permissions:        "domain": "relay"        "example.comXXX": "user"        "@adminMATRIXUSERADMINXXX:exampleXXX.comXXX": "admin"    relay:        # Whether relay mode should be allowed. If allowed, `!signal set-relay` can be used to turn any        # authenticated user into a relaybot for that chat.        enabled: false        # The formats to use when sending messages to Signal via a relay user.        #        # Available variables:        #   $sender_displayname - The display name of the sender (e.g. Example User)        #   $sender_username    - The username (Matrix ID localpart) of the sender (e.g. exampleuser)        #   $sender_mxid        - The Matrix ID of the sender (e.g. @exampleuser:example.com)        #   $message            - The message content        message_formats:            m.text: '$sender_displayname: $message'            m.notice: '$sender_displayname: $message'            m.emote: '* $sender_displayname $message'            m.file: '$sender_displayname sent a file'            m.image: '$sender_displayname sent an image'            m.audio: '$sender_displayname sent an audio file'            m.video: '$sender_displayname sent a video'            m.location: '$sender_displayname sent a location'# Python logging configuration.## See section 16.7.2 of the Python documentation for more info:# https://docs.python.org/3.6/library/logging.config.html#configuration-dictionary-schemalogging:    version: 1    formatters:        colored:            (): mautrix_signal.util.ColorFormatter            format: "[%(asctime)s] [%(levelname)s@%(name)s] %(message)s"        normal:            format: "[%(asctime)s] [%(levelname)s@%(name)s] %(message)s"    handlers:        file:            class: logging.handlers.RotatingFileHandler            formatter: normal            filename: ./mautrix-signal.log            maxBytes: 10485760            backupCount: 10        console:            class: logging.StreamHandler            formatter: colored    loggers:        mau:            level: DEBUG        aiohttp:            level: INFO    root:        level: DEBUG        handlers: [file, console]

mit "STRG+X" und "Y" oder "J" speichern und verlassen.

Nun starten wir den Container noch einmal. Es sollte nun eine "registration.yaml" in /etc/mautrix-signal/bridge/ erzeugt werden.

docker-compose up mautrix-signal

Jetzt muss der Appservice von Mautrix-Signal auch Matrix-Synapse bekannt gemacht werden. Dies machen wir indem wir die homeserver.yaml editieren.

nano /etc/matrix-synapse/homeserver.yaml

unter der Rubrik "app_service_config_files" ändern wir folgendes ab. Dies sollte dann so aussehen:

# A list of application service config files to use#app_service_config_files:  - /etc/mautrix-signal/bridge/registration.yaml

mit "STRG+X" und "Y" oder "J" speichern und verlassen.

Jetzt muss Matrix-Synapse neu gestartet werden.

systemctl restart matrix-synapse.service

Jetzt kann die Bridge final hochgefahren werden und sollte nun lauffähig sein.

docker-compose up -d

Den Mautrix-Signal Bot kann man nun in einen neuen Raum/Direktnachricht einladen. In Element eine neue Direktnachricht starten und nach @signalbot:DEINEDOMAIN.de suchen und in den Raum einladen.

Für die Registrierung bei Signal benötigt man noch ein Captcha. Es gibt folgende möglichkeiten die HIER zu finden sind. Ich habe mit dem Signal-Captch-Helper auf einem Ubuntu Desktop gute Erfahrungen gemacht. Alternativ kann man aber auch diese Lösung nehmen.

Auf einem Rechner mit einem Ubuntu/Debian Desktop die Datei herunterladen. Danach ein Terminal öffnen und

cd /Downloads

chmod +x signal-captcha-helper

./signal-captcha-helper

Nun das Captcha lösen. Das Fenster schließt sich wieder und im Terminal wird der Code erzeugt.

Jetzt den Code (ohne Leerzeichen oder sonstiges) sauber kopieren.

In Element im Raum mit dem Signalbot können wir uns nun Registrieren.

register --captcha HIER-DAS-CAPTCHA-EINSETZEN +495558475222

Der Bot registriert nun die Nummer bei Signal und fordert einen Code an der an die eingegebene Nummer per SMS kommt. Diesen Code dem Bot mitteilen. Nun ist die Rufnummer registriert und der Matrix-Account ist mit der Rufnummer gebridget.

mit help im Chat mit dem Bot kann man sich auch noch weitere Infos holen was die Kommunikation mit dem Bot betrifft.

Die Bridge startet übrigens bei Neustart des Servers automatisch da in der docker-compose.yml die Option „restart: unless-stopped“ gewählt wurde.

Leider ist Stand 01/2022 die Übermittlung der Namen und der Profilbilder noch buggy. Dies liegt wahrscheinlich an signald. Hier kann man auf Patches hoffen und warten.

Upgrades kann man übrigens im Verzeichnis /etc/mautrix-signal/ mit

docker-compose pull

und

docker-compose up -d

machen.

Ich hoffe ich konnte dies hier etwas verständlich ausführen und euch weiter helfen.

Noch ein dickes BIGUP und Danke an Tulir Asokan für seine großartige Arbeit!