Bridge Matrix to IRC

Updated 20 May 2020

Preparing a LXC container

We recommend setting up the bridge in a separate container according to the manual.

Installing software

Install the NodeJS version control tool:

emerge -a dev-python/nodeenv

Create system user irc:

useradd -m -d /var/calculate/matrix-irc-bridge -s /bin/bash -p irc irc

Install Node.js in the user's directory:

su - irc

nodeenv --node=10.20.1 .node-10

source .node-10/bin/activate

echo 'source ~/.node-10/bin/activate' >> ~/.bash_profile

Download the latest version of matrix-appservice-irc from github and save it to the live directory:

git clone https://github.com/matrix-org/matrix-appservice-irc live

Move to the application directory, then build and install the app:

cd live

npm install

npm run-script build

Configuring the bridge

Copy the contents of config.sample.yaml to config.yaml and apply the configuration:

~/live/config.yaml
homeserver:
  # The URL of the homeserver hosting media files. This is only used to transform
  # mxc URIs to http URIs when bridging m.room.[file|image] events. Optional. By
  # default, this is the homeserver URL, specified above.
  #
  media_url: "https://matrix.example.org"
  # The 'domain' part for user IDs on this home server. Usually (but not always)
  # is the "domain name" part of the HS URL.
  domain: "matrix.example.org"
# Configuration specific to the IRC service
ircService:
  # The address of the server to connect to.
  irc.freenode.org:
    name: "FreeNode"
    # additionalAddresses: [ "irc2.example.com" ]
    botConfig:
      # Enable the presence of the bot in IRC channels.
      enabled: false
    # Configuration for mappings not explicitly listed in the 'mappings'
    # section.
    dynamicChannels:
      groupId: +ircfreenode:matrix.example.org
    # The room alias template to apply when creating new aliases. This only
    # applies if createAlias is 'true'. The following variables are exposed:
    # $SERVER => The IRC server address (e.g. "irc.example.com")
    # $CHANNEL => The IRC channel (e.g. "#python")
    # This MUST have $CHANNEL somewhere in it.
    # Default: '#irc_$SERVER_$CHANNEL'
    aliasTemplate: "#freenode_$CHANNEL"
    # Configuration for controlling how Matrix and IRC membership lists are
    # synced.
    membershipLists:
      # Enable the syncing of membership lists between IRC and Matrix. This
      # can have a significant effect on performance on startup as the lists are
      # synced. This must be enabled for anything else in this section to take
      # effect. Default: false.
      enabled: true

      global:
        ircToMatrix:
          # Get a snapshot of all real IRC users on a channel (via NAMES) and
          # join their virtual matrix clients to the room.
          initial: true
          # Make virtual matrix clients join and leave rooms as their real IRC
          # counterparts join/part channels. Default: false.
          incremental: true
        matrixToIrc:
          # Get a snapshot of all real Matrix users in the room and join all of
          # them to the mapped IRC channel on startup. Default: false.
          initial: true
          # Make virtual IRC clients join and leave channels as their real Matrix
          # counterparts join/leave rooms. Make sure your 'maxClients' value is
          # high enough! Default: false.
          incremental: true
    mapping:
      # 1:many mappings from IRC channels to room IDs on this IRC server.
      # The matrix room must already exist. Your matrix client should expose
      # the room ID in a "settings" page for the room.
      "#chatexample": ["!kieouiJuedJoxtVdaG:matrix.example.org"]
    # Configuration for virtual matrix users. The following variables are
    # exposed:
    # $NICK => The IRC nick
    # $SERVER => The IRC server address (e.g. "irc.example.com")
    matrixClient:
      # The user ID template to use when creating virtual matrix users. This
      # MUST have $NICK somewhere in it.
      # Optional. Default: "@$SERVER_$NICK".
      # Example: "@irc.example.com_Alice:example.com"
      userTemplate: "@freenode_$NICK"
      # The display name to use for created matrix clients. This should have
      # $NICK somewhere in it if it is specified. Can also use $SERVER to
      # insert the IRC domain.
      # Optional. Default: "$NICK (IRC)". Example: "Alice (IRC)"
      displayName: "$NICK"
    # Configuration for virtual IRC users. The following variables are exposed:
    # $LOCALPART => The user ID localpart ("alice" in @alice:localhost)
    # $USERID => The user ID
    # $DISPLAY => The display name of this user, with excluded characters
    #             (e.g. space) removed. If the user has no display name, this
    #             falls back to $LOCALPART.
    ircClient:
      # The template to apply to every IRC client nick. This MUST have either
      # $DISPLAY or $USERID or $LOCALPART somewhere in it.
      # Optional. Default: "M-$DISPLAY". Example: "M-Alice".
      nickTemplate: "$DISPLAY[m]"
      # The max number of IRC clients that will connect. If the limit is
      # reached, the client that spoke the longest time ago will be
      # disconnected and replaced.
      # Optional. Default: 30.
      maxClients: 150
      # A list of user modes to set on every IRC client. For example, "RiG" would set
      # +R, +i and +G on every IRC connection when they have successfully connected.
      # User modes vary wildly depending on the IRC network you're connecting to,
      # so check before setting this value. Some modes may not work as intended
      # through the bridge e.g. caller ID as there is no way to /ACCEPT.
      # Default: "" (no user modes)
      userModes: "R"
# Configuration for logging. Optional. Default: console debug level logging
# only.
logging:
  # Level to log on console/logfile. One of error|warn|info|debug
  level: "debug"
  # The file location to log to. This is relative to the project directory.
  logfile: "debug.log"
  # The file location to log errors to. This is relative to the project
  # directory.
  errfile: "errors.log"
  # Whether to log to the console or not.
  toConsole: false
  # The max number of files to keep. Files will be overwritten eventually due
  # to rotations.
  maxFiles: 5
# Use an external database to store bridge state.
database:
  # database engine (must be 'postgres' or 'nedb'). Default: nedb
  engine: "nedb"
  # Either a PostgreSQL connection string, or a path to the NeDB storage directory.
  # For postgres, it must start with postgres://
  # For NeDB, it must start with nedb://. The path is relative to the project directory.
  connectionString: "nedb://freenode"

Generate a key to encrypt IRC user passwords:

openssl genpkey -out passkey.pem -outform PEM -algorithm RSA -pkeyopt rsa_keygen_bits:2048

Generate a log file that allows the application to communicate with the Matrix server. Specify matrix-irc.example.org as the IRC bridge hostname:

node app.js -r -f registration_freenode.yaml -u "http://matrix-irc.example.org:9999" -c config.yaml -l freenodebot

Copy this file to the Synapse server:

scp registration_freenode.yaml root@synapse:/var/calculate/synapse/

Add it to the Synapse configuration:

homeserver.yaml
...
# A list of application service config file to use
app_service_config_files:
  - registration_freenode.yaml
...

Restart Synapse:

/etc/init.d/synapse restart

Using an Ident server

To be able to bridge with an identification protocol, include Ident in the IRC configuration file:

~/live/config.yaml
...
ircService:
  ident:
    enabled: true
    port: 1113
...

Starting the bridge

Create an OpenRC script to manage the Matrix IRC bridge daemon:

/etc/init.d/matrix-irc-bridge
#!/sbin/openrc-run
# Copyright 1999-2011 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $

description="Matrix-IRC bridge"
pidfile=/run/matrix-irc-bridge.pid
command_user=irc
output_log=/var/log/matrix-irc-bridge.log
error_log=/var/log/matrix-irc-bridge.log
directory=/var/calculate/matrix-irc-bridge/live
command="/var/calculate/matrix-irc-bridge/.node-10/bin/node"
command_args="app.js -c config.yaml -f registration_freenode.yaml -p 9999"
stopsig="2"
command_background=true

depend() {
        need net
}

start_pre() {
    checkpath -f -o irc -m 0600 /var/log/matrix-irc-bridge.log
}

Set the

chmod 0755 /etc/init.d/matrix-irc-bridge

Launch the daemon:

/etc/init.d/matrix-irc-bridge start

Add it to autostart:

rc-update add matrix-irc-bridge