Unify Signal, WhatsApp and SMS in a personal Matrix server: Part 2 (Signal)

Prerequisites

See Part 1 to get a running Synapse server based off a Docker-Compose file, example file included at the bottom of this post

Matrix-Signal Bridge

Alright, assuming you’re up to date with part 1 then a Synapse server is running and accessible. Huge first step! Now to integrate a Signal bridge. This is going to be very similar to the WhatsApp bridge set up that is upcoming in part 3.

  1. Start a Signal daemon like Signald
    • docker-compose up -d signald
  2. update the docker-compose.yaml to contain an actual password for signal-bridge-db
  3. use an ephemeral Docker container to create the bridge’s configuration file
$ docker run -it --rm -v signal-bridge-data:/data dock.mau.dev/tulir/mautrix-signal:latest
Didn't find a config file.
Copied default config file to /data/config.yaml
Modify that config file to your liking.
Start the container again after that to generate the registration file.
  1. Same as for Synapse, we’ll update this configuration file
    1. sudo nano $(docker inspect --format='{{.Mountpoint}}' signal-bridge-data)/config.yaml
    2. Update a whole bunch of stuff in here:
      • under homeserver
        • update address to be http://synapse:8008
        • update domain to be the domain you are ultimately going to use, for me it’s nuc.localdomain
      • under appservice
        • update address to http://signal-bridge:29328
        • update database to the full Postgres database string, e.g. postgres://mautrix_signal:reallyStrongPassword!2@signal-bridge-db/signal_bridge_db
      • under signal
        • update socket_path to /signald/signald.sock
        • update outgoing_attachment_dir to /signald/attachments
        • update avatar_dir to /signald/avatars
        • update data_dir to /signald/data
      • under bridge
        • under permission add yourself as an administrator (e.g. "toby@nuc.localdomain": "admin")
    3. ensure you save the file!
  2. use another ephemeral Docker container to consume the bridge’s configuration and create a registration file that can be used with Synapse
$ docker run -it --rm -v signal-bridge-data:/data dock.mau.dev/tulir/mautrix-signal:latest
Registration generated and saved to /data/registration.yaml
  1. Now we need to get the registration.yaml for this bridge into Syanpse. Luckily, it’s in a volume that is mounted to both containers, so it’s straightforward. Edit the homeserver.yaml
    • sudo nano $(docker inspect --format='{{.Mountpoint}}' synapse-data)/homeserver.yaml
    • find app_service_config_files (it’s likely commented out). Uncomment it and add the path to the the generated config.yaml
# A list of application service config files to use
#
app_service_config_files:
  - /signal-bridge/registration.yaml
  1. Now you should be able to start both the Signal bridge and Synapse. Note that it may error out a couple times as both are trying to start up talking to one another.
  2. Now is time to actually set up your Signal account with the Signal daemon. These instructions are basically from here.
    1. Invite (or send a direct message, depending on your client) the Signal bot which will be based on your own server name: (@signalbot:nuc.localdomain). You’ll get early feedback that it’ll work when you see the icon change to be Signal’s
  1. send the message link to the bridge bot, then in Signal go to the Settings then Linked devices and Add
  2. Scan the QR code, and hopefully you should be on your way!

At this point, when you receive a Signal message it should show upon the daemon and get pushed to Matrix. If this the first message you’ve received from that contact, you’ll be invited to a new chat (or new group, if it’s a group message) and then be able to chat away! A logical next double-puppeting, which makes the whole experience nicer. I have yet to find a way to proactively crawl existing conversations so they’re present in Matrix right off the bat.

Example docker-compose.yaml

version: "3.7"

volumes:
  # We need to do some initial set up outside of Docker-Compose, so make these volumes external
  synapse-data:
    external: true
  whatsapp-bridge-data:
    external: true
  signal-bridge-data:
    external: true

  # The Signal daemon (Signald) and the Signal bridge (Mautrix-Signal) need to share a volume
  signald-data:

  # Use these named volumes just for convenience
  signal-bridge-db:
  synapse-db:

services:
  synapse-db:
    container_name: synapse-db
    image: postgres:13-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: synapse
      POSTGRES_PASSWORD: <GENERATE A PASSWORD HERE> # Make sure to update this!
      POSTGRES_DB: synapse_db
      # ensure the database gets created correctly
      # https://github.com/matrix-org/synapse/blob/master/docs/postgres.md#set-up-database
      POSTGRES_INITDB_ARGS: --encoding=UTF-8 --lc-collate=C --lc-ctype=C
    volumes:
      - synapse-db:/var/lib/postgresql/data
    ports:
      - 5435:5432/tcp

  synapse:
    container_name: synapse
    image: docker.io/matrixdotorg/synapse:latest
    # Since synapse does not retry to connect to the database, restart upon failure
    restart: unless-stopped
    environment:
      - SYNAPSE_CONFIG_PATH=/data/homeserver.yaml
    volumes:
      - synapse-data:/data
      - signal-bridge-data:/signal-bridge
      - whatsapp-bridge-data:/whatsapp-bridge
    depends_on:
      - synapse-db
    ports:
      - 8008:8008/tcp
      - 8448:8448/tcp

  whatsapp-bridge:
    container_name: whatsapp-bridge
    image: dock.mau.dev/tulir/mautrix-whatsapp:latest
    restart: unless-stopped
    volumes:
    - whatsapp-bridge-data:/data
    ports:
      - 29318:29318/tcp

  # Signal and bridge
  signald:
    container_name: signald
    image: finn/signald:latest
    restart: unless-stopped
    volumes:
    - signald-data:/signald
  signal-bridge-db:
    container_name: signal-bridge-db
    image: postgres:13-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: mautrix_signal
      POSTGRES_DB: signal_bridge_db
      POSTGRES_PASSWORD: <GENERATE A PASSWORD HERE> # Make sure to update this!
    volumes:
    - signal-bridge-db:/var/lib/postgresql/data
    ports:
        - 5434:5432/tcp
  signal-bridge:
    container_name: signal-bridge
    image: dock.mau.dev/tulir/mautrix-signal
    restart: unless-stopped
    volumes:
    - signal-bridge-data:/data
    - signald-data:/signald
    ports:
      - 29328:29328/tcp
    depends_on:
      - signal-bridge-db
      - signald

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s