Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 3 additions & 63 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,69 +100,9 @@ make generate-emoji

## Local Development with Matrix Synapse

For local development and testing, you can run a Matrix Synapse server using Docker Compose.

### Prerequisites

1. Install and configure the Mattermost Matrix Bridge plugin first
- **Matrix Server URL**: `http://localhost:8888`
2. Generate the bridge registration file through the plugin configuration
3. Copy the generated registration file to `docker/mattermost-bridge-registration.yaml`

### Starting the Matrix Synapse Server

1. Start the services:

```bash
docker-compose up -d
```

2. Create an admin user:

```bash
docker exec -it mattermost-plugin-matrix-bridge-synapse-1 register_new_matrix_user -c /data/homeserver.yaml -u admin -p admin123 -a http://localhost:8008
```

3. The Matrix server will be available at `http://localhost:8888`

### Accessing the Web Chat Interface (Element)

Synapse is only a homeserver and has no built-in chat UI. The Docker Compose stack
includes an [Element Web](https://element.io/) client for testing:

1. Start the Element service (included in `docker-compose up -d`, or start it alone):

```bash
docker-compose up -d element
```

2. Open `http://localhost:8880` in your browser.

3. It is pre-configured to use the local homeserver (`http://localhost:8888`), so you
can register or sign in with a test user directly. Registration is enabled for
development, so you can create new users from the login screen.

Element's configuration lives in `docker/element-config.json`.

### Configuration Notes

- The Synapse server is configured to use PostgreSQL as the database
- Registration is enabled for development purposes
- App service configuration is loaded from `docker/mattermost-bridge-registration.yaml`
- Room list publication is restricted to the bridge user only
- An Element Web client is available at `http://localhost:8880` for manual testing

### Stopping the Services

```bash
docker-compose down
```

To completely reset (remove all data):

```bash
docker-compose down -v
```
For local development and testing, you can run one or two Matrix Synapse servers using
Docker Compose. See **[docs/local-development.md](docs/local-development.md)** for the full
guide, including multi-server testing and connecting channels to a second homeserver.

## Troubleshooting

Expand Down
56 changes: 56 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,62 @@ services:
volumes:
- postgres-data:/var/lib/postgresql/data

# --- Second Matrix homeserver, for manual multi-server testing ---
# server_name "synapse2.localhost" resolves to 127.0.0.1 (*.localhost) and is
# a distinct hostname from the first server, so the plugin derives a distinct
# serverID for it. Inject it into the plugin with `/matrix server add`.
synapse2-init:
image: alpine:latest
command: |
sh -c "
chown -R 991:991 /data
chmod -R 755 /data
"
volumes:
- synapse2-data:/data

synapse2:
image: matrixdotorg/synapse:latest
restart: unless-stopped
environment:
- SYNAPSE_SERVER_NAME=synapse2.localhost
- SYNAPSE_REPORT_STATS=no
- UID=991
- GID=991
volumes:
- synapse2-data:/data
- ./docker/synapse2_config.yaml:/data/homeserver.yaml:ro
- ./docker/mattermost-bridge-registration2.yaml:/data/mattermost-bridge-registration.yaml:ro
ports:
- "8889:8008"
- "8449:8448"
depends_on:
- synapse2-init
- postgres2

element2:
image: vectorim/element-web:latest
restart: unless-stopped
ports:
- "8881:80"
volumes:
- ./docker/element2-config.json:/app/config.json:ro
depends_on:
- synapse2

postgres2:
image: postgres:14
restart: unless-stopped
environment:
- POSTGRES_DB=synapse
- POSTGRES_USER=synapse
- POSTGRES_PASSWORD=synapse
- POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C
volumes:
- postgres2-data:/var/lib/postgresql/data

volumes:
synapse-data:
postgres-data:
synapse2-data:
postgres2-data:
13 changes: 13 additions & 0 deletions docker/element2-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"default_server_config": {
"m.homeserver": {
"base_url": "http://synapse2.localhost:8889",
"server_name": "synapse2.localhost"
}
},
"disable_custom_urls": false,
"disable_guests": false,
"brand": "Element (dev, synapse2)",
"default_country_code": "US",
"show_labs_settings": true
}
25 changes: 25 additions & 0 deletions docker/mattermost-bridge-registration2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
id: "mattermost-bridge"
url: "https://pasokon-2.tail893a6.ts.net/plugins/com.mattermost.plugin-matrix-bridge"
# Each homeserver must present a UNIQUE hs_token: the plugin routes inbound
# Application Service traffic to the right server by matching this token.
as_token: "syn2_5Kd9WmXpQ2rLtVnB7cYhFgJ4sZaEuNi"
hs_token: "syn2_Tb3Rk8VpMxWq6NcYdL2fHgJ7sUaZ0eYi"
sender_localpart: "_mattermost_bridge"
namespaces:
users:
- exclusive: true
regex: "@_mattermost_.*:synapse2.localhost"
aliases:
- exclusive: true
regex: "#_mattermost_.*:synapse2.localhost"
- exclusive: false
regex: "#mattermost-bridge-.*:synapse2.localhost"
rooms:
- exclusive: false
regex: "!.*:synapse2.localhost"
rate_limited: false
protocols: ["mattermost"]
de.sorunome.msc2409.push_ephemeral: true
permissions:
- "m.room.directory"
- "m.room.membership"
70 changes: 70 additions & 0 deletions docker/synapse2_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
server_name: "synapse2.localhost"
pid_file: /data/homeserver.pid
public_baseurl: http://synapse2.localhost:8889/

listeners:
- port: 8008
tls: false
type: http
x_forwarded: true
resources:
- names: [client, federation]
compress: false

database:
name: psycopg2
args:
user: synapse
password: synapse
database: synapse
host: postgres2
port: 5432
cp_min: 5
cp_max: 10

log:
version: 1
formatters:
precise:
format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s'
handlers:
console:
class: logging.StreamHandler
formatter: precise
loggers:
synapse:
level: INFO
synapse.access:
level: INFO
root:
level: INFO
handlers: [console]

media_store_path: "/data/media_store"
max_upload_size: 50M
max_image_pixels: 32M

registration_shared_secret: "development_secret_key_change_in_production"
macaroon_secret_key: "development_macaroon_secret_change_in_production"
form_secret: "development_form_secret_change_in_production"

signing_key_path: "/data/signing.key"

trusted_key_servers:
- server_name: "matrix.org"

enable_registration: true
enable_registration_without_verification: true

suppress_key_server_warning: true

room_list_publication_rules:
- user_id: "@_mattermost_bridge:synapse2.localhost"
action: allow
- user_id: "*"
action: deny

app_service_config_files:
- /data/mattermost-bridge-registration.yaml

report_stats: false
152 changes: 152 additions & 0 deletions docs/local-development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# Local Development with Matrix Synapse

For local development and testing, you can run a Matrix Synapse server using Docker Compose.

## Table of Contents

- [Prerequisites](#prerequisites)
- [Starting the Matrix Synapse Server](#starting-the-matrix-synapse-server)
- [Accessing the Web Chat Interface (Element)](#accessing-the-web-chat-interface-element)
- [Configuration Notes](#configuration-notes)
- [Multi-Server Testing (two homeservers)](#multi-server-testing-two-homeservers)
- [Connecting a channel to a room on the second server](#connecting-a-channel-to-a-room-on-the-second-server)
- [Stopping the Services](#stopping-the-services)

## Prerequisites

1. Install and configure the Mattermost Matrix Bridge plugin first
- **Matrix Server URL**: `http://localhost:8888`
2. Generate the bridge registration file through the plugin configuration
3. Copy the generated registration file to `docker/mattermost-bridge-registration.yaml`

## Starting the Matrix Synapse Server

1. Start the services:

```bash
docker-compose up -d
```

2. Create an admin user:

```bash
docker exec -it mattermost-plugin-matrix-bridge-synapse-1 register_new_matrix_user -c /data/homeserver.yaml -u admin -p admin123 -a http://localhost:8008
```

3. The Matrix server will be available at `http://localhost:8888`

## Accessing the Web Chat Interface (Element)

Synapse is only a homeserver and has no built-in chat UI. The Docker Compose stack
includes an [Element Web](https://element.io/) client for testing:

1. Start the Element service (included in `docker-compose up -d`, or start it alone):

```bash
docker-compose up -d element
```

2. Open `http://localhost:8880` in your browser.

3. It is pre-configured to use the local homeserver (`http://localhost:8888`), so you
can register or sign in with a test user directly. Registration is enabled for
development, so you can create new users from the login screen.

Element's configuration lives in `docker/element-config.json`.

## Configuration Notes

- The Synapse server is configured to use PostgreSQL as the database
- Registration is enabled for development purposes
- App service configuration is loaded from `docker/mattermost-bridge-registration.yaml`
- Room list publication is restricted to the bridge user only
- An Element Web client is available at `http://localhost:8880` for manual testing

## Multi-Server Testing (two homeservers)

The Docker Compose stack includes a **second, independent homeserver** so you can
exercise multi-server bridging locally. It runs alongside the first:

| | Server 1 | Server 2 |
| ----------------- | -------------------------------------------- | --------------------------------------------- |
| Server name | `localhost` | `synapse2.localhost` |
| Matrix API (host) | `http://localhost:8888` | `http://synapse2.localhost:8889` |
| Element client | `http://localhost:8880` | `http://localhost:8881` |
| Registration file | `docker/mattermost-bridge-registration.yaml` | `docker/mattermost-bridge-registration2.yaml` |

`synapse2.localhost` resolves to `127.0.0.1` automatically (the `.localhost` TLD),
so no `/etc/hosts` changes are needed. The two servers must use **distinct
hostnames** — the plugin derives each server's ID from its URL hostname, and both
homeservers carry **distinct `hs_token`s** so inbound traffic routes to the right one.

Bring everything up and create an admin user on the second server:

```bash
docker-compose up -d
docker exec -it mattermost-plugin-matrix-bridge-synapse2-1 register_new_matrix_user -c /data/homeserver.yaml -u admin -p admin123 -a http://localhost:8008
```

Configure **Server 1** as usual through the System Console (Matrix Server URL
`http://localhost:8888`). The System Console UI can only manage a single server, so
register **Server 2** with the admin-only slash command (the tokens come from
`docker/mattermost-bridge-registration2.yaml`):

```
/matrix server add http://synapse2.localhost:8889 synapse2.localhost syn2_5Kd9WmXpQ2rLtVnB7cYhFgJ4sZaEuNi syn2_Tb3Rk8VpMxWq6NcYdL2fHgJ7sUaZ0eYi matrix2
```

Other server-management commands:

- `/matrix server list` — show all registered servers and their IDs
- `/matrix server remove <server_id>` — remove an injected server

### Connecting a channel to a room on the second server

The regular `/matrix map` and `/matrix create` commands always target the primary
server (the one configured in the System Console). To bridge a channel to a room on
the **second** server, use the server-scoped map command:

1. Create (or find) a room on server 2 — for example, sign in at
`http://localhost:8881` (Element for server 2) and create a room.
2. Find the second server's ID with `/matrix server list`.
3. In the Mattermost channel you want to bridge, run:

```
/matrix server map <server_id> <room_alias_or_id>
```

for example:

```
/matrix server map yjfnsajexkwmmmphkd4ceyte9a #room:synapse2.localhost
```

This resolves the room, joins the bridge bot on server 2, and stores the mapping
under that server's namespace (preserving any mapping the channel already has to the
primary server). Send a message in the Matrix room and it appears in the Mattermost
channel.

> **Inbound only for now:** messages **from** server 2 sync **into** Mattermost. The
> reverse direction (Mattermost → a non-primary server) is not yet wired — outbound
> multi-server routing lands in a later phase — so posting in the Mattermost channel
> will not (yet) reach server 2's room.

Notes:

- These commands require System Administrator privileges.
- Injected servers persist in the plugin's KV store and survive restarts and plugin
reconfiguration. The single server configured in the System Console is always the
"primary"; removing it via the command is not permanent (it is re-derived from the
configuration), whereas injected servers can be removed permanently.

## Stopping the Services

```bash
docker-compose down
```

To completely reset (remove all data):

```bash
docker-compose down -v
```
Loading
Loading