A Matrix <-> Slack bridge written in Rust.
Maintainer: Palpo Team
Contact: chris@acroidea.com
- Rust-only implementation
- Matrix appservice + Slack bot bridge core
- Slack Socket Mode for inbound events
- Slack Web API for outbound messaging, edits, file uploads, and lookups
- HTTP endpoints for health/status/metrics and provisioning
- Database backends: PostgreSQL, SQLite, and MySQL (feature-gated)
src/: bridge implementationconfig/config.sample.yaml: sample configurationDockerfile: multi-stage container build
- Rust toolchain (Docker build uses Rust 1.93)
- A Matrix homeserver configured for appservices
- A Slack app with:
- bot token (
xoxb-...) - app token (
xapp-...) withconnections:write
- bot token (
- Database: PostgreSQL, SQLite, or MySQL
When running with Palpo, you can configure the bridge registration in your palpo.kdl:
// Palpo server config — enable appservice bridge loading
server_name "example.com"
appservice_registration_dir "appservices"And create the bridge config file as config.kdl:
// Matrix-Slack Bridge Configuration (KDL format)
// See config/config.example.kdl for all options
bridge {
domain "example.com"
homeserver_url "http://127.0.0.1:6006"
port 9005
bind_address "0.0.0.0"
bridge_id "slack"
appservice_token "put_your_as_token_here"
homeserver_token "put_your_hs_token_here"
admin_mxid "@admin:example.com"
}
auth {
client_id "YOUR_SLACK_CLIENT_ID"
bot_token "YOUR_SLACK_BOT_TOKEN"
app_token "YOUR_SLACK_APP_TOKEN"
}
database {
url "sqlite://./slack.db"
max_connections 10
min_connections 1
}- Create your config file:
cp config/config.sample.yaml config.yaml-
Set required values in
config.yaml:bridge.domainauth.bot_tokenauth.app_tokendatabase.url(ordatabase.conn_string/database.filename)- registration values via either:
registration.id,registration.as_token,registration.hs_token, orslack-registration.yamlnext to your config file, or- env vars (see Environment Overrides below)
-
Run:
cargo check -p matrix-bridge-slack
cargo test -p matrix-bridge-slack --no-run
cargo run -p matrix-bridge-slack- Verify:
curl http://127.0.0.1:9005/health
curl http://127.0.0.1:9005/status-
Create a Slack app in your workspace:
-
Enable Socket Mode and create an App-Level Token:
- scope:
connections:write - token format:
xapp-...
- scope:
-
Add Bot Token Scopes under OAuth & Permissions (minimum recommended):
chat:writechannels:historychannels:readusers:readfiles:write- optional for private channels:
groups:history,groups:read - optional for username/icon customization:
chat:write.customize
-
Under Event Subscriptions, enable events and subscribe bot events as needed:
message.channels- optional:
message.groups,user_typing,user_change
-
Install/reinstall the app to your workspace and copy tokens:
- Bot User OAuth Token ->
auth.bot_token - App-Level Token ->
auth.app_token
- Bot User OAuth Token ->
-
Fill auth values in
config.yaml:
auth:
bot_token: "xoxb-..."
app_token: "xapp-..."
client_id: null
client_secret: nullThis bridge implementation follows Slack official docs:
- Socket Mode overview: https://api.slack.com/apis/connections/socket
apps.connections.open: https://docs.slack.dev/reference/methods/apps.connections.open/chat.postMessage: https://docs.slack.dev/reference/methods/chat.postMessage/chat.update: https://docs.slack.dev/reference/methods/chat.update/users.info: https://docs.slack.dev/reference/methods/users.info/conversations.info: https://docs.slack.dev/reference/methods/conversations.info/- File upload flow:
- Message event scopes/events:
-
In Palpo config, set your server name and appservice registration directory.
Using KDL (
palpo.kdl):server_name "example.com" appservice_registration_dir "appservices"
Or using TOML (
palpo.toml):server_name = "example.com" appservice_registration_dir = "appservices"
-
Place your bridge registration file there, for example:
appservices/slack-registration.yaml
-
Ensure tokens are consistent between Palpo registration and bridge config:
as_tokenin registration == bridge appservice tokenhs_tokenin registration == bridge homeserver token
-
Ensure bridge homeserver fields point to Palpo:
bridge:
domain: "example.com"
homeserver_url: "http://127.0.0.1:6006"Create slack-registration.yaml (or set REGISTRATION_PATH) and load it from Synapse:
id: "slack"
url: "http://127.0.0.1:9005"
as_token: "CHANGE_ME_AS_TOKEN"
hs_token: "CHANGE_ME_HS_TOKEN"
sender_localpart: "_slack_"
rate_limited: false
protocols: ["slack"]
namespaces:
users:
- exclusive: true
regex: "@_slack_.*:example.com"
aliases:
- exclusive: true
regex: "#_slack_.*:example.com"
rooms: []In homeserver.yaml:
app_service_config_files:
- /path/to/slack-registration.yamlBuild:
docker build -t ghcr.io/palpo-im/matrix-bridge-slack:main -f Dockerfile .Run:
docker run --rm \
-p 9005:9005 \
-v "$(pwd)/config:/data" \
-e CONFIG_PATH=/data/config.yaml \
ghcr.io/palpo-im/matrix-bridge-slack:mainCONFIG_PATHREGISTRATION_PATHAPPSERVICE_SLACK_AUTH_BOT_TOKENAPPSERVICE_SLACK_AUTH_APP_TOKENAPPSERVICE_SLACK_AUTH_CLIENT_IDAPPSERVICE_SLACK_AUTH_CLIENT_SECRETAPPSERVICE_SLACK_REGISTRATION_IDAPPSERVICE_SLACK_REGISTRATION_AS_TOKENAPPSERVICE_SLACK_REGISTRATION_HS_TOKENAPPSERVICE_SLACK_REGISTRATION_SENDER_LOCALPART