Monitoring Your Matterbridge Chat Bridge with Vigilmon
Matterbridge is a single Go binary that bridges chat messages across Slack, Discord, Matrix, IRC, Telegram, Mattermost, Rocket.Chat, and a dozen more protocols — all at once, with routing rules you define in a TOML config file.
When Matterbridge goes down, message bridging stops silently. People on Slack think people on Matrix aren't responding. Discord users don't see IRC messages. Nobody gets an error — they just stop hearing from each other. By the time someone files a complaint, the bridge may have been down for hours.
This tutorial adds external monitoring to your Matterbridge deployment:
- Process health check via HTTP API
- HTTP uptime monitoring with Vigilmon
- Per-gateway connection status monitoring (Slack, Discord, Matrix, IRC, Telegram)
- Heartbeat monitoring for message relay throughput
- Slack/Discord alerts and a public status page
Architecture overview
Matterbridge is intentionally minimal — it runs as a single process with no built-in HTTP server. Monitoring it requires a lightweight sidecar or log-based approach:
| What to monitor | How | |-----------------|-----| | Bridge process health | PID file + HTTP sidecar | | Slack gateway connection | WebSocket reconnect events in logs | | Discord gateway connection | WebSocket reconnect events in logs | | Matrix homeserver connectivity | Direct HTTP check on homeserver | | IRC server connection | Log-based + TCP port check | | Telegram Bot API | Direct HTTP check | | Message relay throughput | Heartbeat based on log line count | | Reconnection frequency | Log error rate check | | Config file integrity | Heartbeat after config validation | | Webhook receiver | HTTP monitor if enabled |
Step 1: Add a health check sidecar
Matterbridge doesn't expose an HTTP server, so you need a lightweight health sidecar that reports bridge process status. The simplest approach is a small systemd service that wraps a health check script:
#!/bin/bash
# /usr/local/bin/matterbridge-health
# Simple HTTP health server for Matterbridge process monitoring
MATTERBRIDGE_PID_FILE="${MATTERBRIDGE_PID_FILE:-/var/run/matterbridge.pid}"
PORT="${HEALTH_PORT:-8765}"
check_health() {
# Check if PID file exists and process is running
if [ ! -f "$MATTERBRIDGE_PID_FILE" ]; then
echo '{"status":"error","reason":"pid_file_missing"}'
return 1
fi
pid=$(cat "$MATTERBRIDGE_PID_FILE")
if ! kill -0 "$pid" 2>/dev/null; then
echo '{"status":"error","reason":"process_not_running","pid":'"$pid"'}'
return 1
fi
# Check log file for recent errors (last 60 seconds)
log_file="${MATTERBRIDGE_LOG:-/var/log/matterbridge/matterbridge.log}"
if [ -f "$log_file" ]; then
recent_errors=$(awk -v d="$(date -d '60 seconds ago' '+%Y/%m/%d %H:%M')" '$0 >= d' "$log_file" | grep -c '"level":"error"' || true)
echo "{\"status\":\"ok\",\"pid\":${pid},\"recent_errors\":${recent_errors}}"
else
echo "{\"status\":\"ok\",\"pid\":${pid}}"
fi
return 0
}
# Serve HTTP responses
while true; do
response=$(check_health)
exit_code=$?
if [ $exit_code -eq 0 ]; then
http_status="200 OK"
else
http_status="503 Service Unavailable"
fi
printf "HTTP/1.1 %s\r\nContent-Type: application/json\r\nContent-Length: %d\r\n\r\n%s" \
"$http_status" "${#response}" "$response" | nc -l -p "$PORT" -q 1 2>/dev/null
done
Run Matterbridge with a PID file:
# /etc/systemd/system/matterbridge.service
[Unit]
Description=Matterbridge chat bridge
After=network.target
[Service]
Type=simple
User=matterbridge
ExecStart=/usr/local/bin/matterbridge -conf /etc/matterbridge/matterbridge.toml
PIDFile=/var/run/matterbridge.pid
Restart=on-failure
RestartSec=10
StandardOutput=append:/var/log/matterbridge/matterbridge.log
StandardError=append:/var/log/matterbridge/matterbridge.log
[Install]
WantedBy=multi-user.target
# /etc/systemd/system/matterbridge-health.service
[Unit]
Description=Matterbridge health check sidecar
After=matterbridge.service
[Service]
Type=simple
User=matterbridge
ExecStart=/usr/local/bin/matterbridge-health
Environment=MATTERBRIDGE_PID_FILE=/var/run/matterbridge.pid
Environment=HEALTH_PORT=8765
Restart=always
[Install]
WantedBy=multi-user.target
Test it:
curl http://localhost:8765
# {"status":"ok","pid":12345,"recent_errors":0}
Put this behind your reverse proxy at /health and Vigilmon can monitor it:
location /health {
proxy_pass http://localhost:8765;
proxy_connect_timeout 5s;
proxy_read_timeout 10s;
}
Step 2: Set up HTTP monitoring in Vigilmon
Point Vigilmon at your health endpoint:
- Sign up at vigilmon.online
- Click New Monitor → HTTP
- Enter
https://matterbridge.yourdomain.com/health - Set check interval: 1 minute (paid) or 5 minutes (free)
- Add keyword check for
"status":"ok"in response body - Save
This detects the most common failure mode: the systemd service crashed, the process exited, or the binary panicked. A 503 means the bridge is down; anything else means the sidecar itself is broken.
Step 3: Monitor per-gateway connections
Each protocol gateway has its own connectivity requirements. Add direct health monitors where possible:
Matrix homeserver:
https://matrix.yourdomain.com/_matrix/client/versions
In Vigilmon:
- Add keyword check for
"versions"in response body - This verifies the Matrix homeserver is accepting connections
Telegram Bot API:
https://api.telegram.org/botYOUR_BOT_TOKEN/getMe
In Vigilmon:
- Add keyword check for
"ok":truein response body - A 401 indicates the bot token is invalid or revoked
Discord gateway:
https://discord.com/api/v10/gateway
- Keyword check for
"url"— the returned gateway URL indicates Discord's API is operational
Slack API:
https://slack.com/api/api.test
- Keyword check for
"ok":true
IRC server TCP check:
For IRC, use Vigilmon's TCP monitor:
- Click New Monitor → TCP
- Enter your IRC server hostname and port (usually 6667 or 6697 for SSL)
- This verifies the IRC server accepts TCP connections
These per-protocol monitors tell you when a gateway failure is the external service's fault, not Matterbridge's. When Discord has an incident, your Discord monitor goes red — and you immediately know why Matterbridge isn't bridging Discord messages.
Step 4: Alerts via Slack or Discord
Slack alerts:
In Vigilmon, go to Notifications → New Channel → Slack and paste your incoming webhook URL.
- api.slack.com/apps → Create New App
- Enable Incoming Webhooks → copy URL
Discord alerts (recommended since you're bridging Discord):
In Vigilmon, go to Notifications → New Channel → Webhook:
- Pick a monitoring-specific Discord channel (not one that Matterbridge bridges)
- Channel settings → Integrations → Webhooks → New Webhook → copy URL
- Append
/slackto use the Slack-compatible format:https://discord.com/api/webhooks/...TOKEN.../slack
Use a dedicated monitoring channel that is NOT part of any bridge — if Matterbridge goes down, you don't want your alerts to also go through Matterbridge.
Step 5: Heartbeat monitoring for message relay throughput
A running Matterbridge process doesn't guarantee messages are flowing. The bridge can be up while all gateways have silently disconnected. Add a throughput heartbeat:
#!/bin/bash
# /usr/local/bin/matterbridge-throughput-check
# Run every 5 minutes via cron
VIGILMON_HEARTBEAT_URL="${VIGILMON_HEARTBEAT_URL}"
LOG_FILE="${MATTERBRIDGE_LOG:-/var/log/matterbridge/matterbridge.log}"
CHECK_WINDOW_SECONDS=300 # 5 minutes
# Count relayed messages in the last 5 minutes
recent_relayed=$(awk \
-v d="$(date -d "${CHECK_WINDOW_SECONDS} seconds ago" '+%Y/%m/%d %H:%M')" \
'$0 >= d && /msg relay/ {count++} END {print count+0}' \
"$LOG_FILE" 2>/dev/null)
# Count reconnection events in the same window
reconnects=$(awk \
-v d="$(date -d "${CHECK_WINDOW_SECONDS} seconds ago" '+%Y/%m/%d %H:%M')" \
'$0 >= d && /reconnect/ {count++} END {print count+0}' \
"$LOG_FILE" 2>/dev/null)
echo "Recent relayed: ${recent_relayed}, Reconnects: ${reconnects}"
# Alert on excessive reconnections even if messages are flowing
if [ "$reconnects" -gt 10 ]; then
echo "Too many reconnections (${reconnects}) — skipping heartbeat ping"
exit 1
fi
# Ping heartbeat if bridge appears healthy
# Note: we ping even with 0 messages — low traffic is normal
# The PID check in the health endpoint handles actual process failures
curl -sf "${VIGILMON_HEARTBEAT_URL}" > /dev/null
Add to crontab:
*/5 * * * * /usr/local/bin/matterbridge-throughput-check
In Vigilmon, create a Heartbeat Monitor:
- Click New Monitor → Heartbeat
- Set expected interval: 10 minutes (2× cron interval)
- Copy the ping URL → set as
VIGILMON_HEARTBEAT_URL - Enable Discord/Slack alerts
Step 6: Monitor reconnection frequency
Frequent reconnections indicate gateway instability — a flaky IRC server, a rate-limited Telegram connection, or a Discord WebSocket that keeps dropping. Add a log-based monitor:
#!/bin/bash
# /usr/local/bin/matterbridge-reconnect-monitor
# Run every hour via cron
VIGILMON_HEARTBEAT_STABILITY="${VIGILMON_HEARTBEAT_STABILITY}"
LOG_FILE="${MATTERBRIDGE_LOG:-/var/log/matterbridge/matterbridge.log}"
# Count reconnections in the last hour
reconnects=$(awk \
-v d="$(date -d '1 hour ago' '+%Y/%m/%d %H:%M')" \
'$0 >= d && /reconnect/ {count++} END {print count+0}' \
"$LOG_FILE" 2>/dev/null)
echo "Reconnections in last hour: ${reconnects}"
# Only ping if reconnection count is within acceptable range
# Occasional reconnects are normal; >20/hour suggests a problem
if [ "$reconnects" -lt 20 ]; then
curl -sf "${VIGILMON_HEARTBEAT_STABILITY}" > /dev/null
echo "Stability heartbeat sent"
else
echo "Reconnection rate too high (${reconnects}/hr) — skipping heartbeat"
fi
5 * * * * /usr/local/bin/matterbridge-reconnect-monitor
In Vigilmon, create a Heartbeat Monitor with expected interval 2 hours and enable alerts. A missed heartbeat means reconnections exceeded 20/hour in the last interval — worth investigating before the gateway starts dropping messages entirely.
Step 7: Configuration file integrity check
Matterbridge reads its config at startup. A broken TOML file causes a silent failure on restart. Add a validation heartbeat to your deployment pipeline:
#!/bin/bash
# /usr/local/bin/matterbridge-config-validate
# Run after any config change
CONFIG_FILE="${MATTERBRIDGE_CONFIG:-/etc/matterbridge/matterbridge.toml}"
VIGILMON_HEARTBEAT_CONFIG="${VIGILMON_HEARTBEAT_CONFIG}"
# Validate config by doing a dry run (check if matterbridge can parse it)
if /usr/local/bin/matterbridge -conf "$CONFIG_FILE" -debug 2>&1 | grep -q "Starting bridge"; then
# Config is valid — but this would actually start the bridge
# Instead, use a config linter or basic TOML validation
echo "Config appears valid"
else
echo "Config validation check skipped (use toml-test or similar)"
fi
# Simple TOML syntax check using Python (usually available)
if python3 -c "
import sys
try:
import tomllib
with open('${CONFIG_FILE}', 'rb') as f:
tomllib.load(f)
print('valid')
except Exception as e:
print(f'error: {e}', file=sys.stderr)
sys.exit(1)
" 2>/dev/null; then
curl -sf "${VIGILMON_HEARTBEAT_CONFIG}" > /dev/null
echo "Config heartbeat sent"
fi
Run this as a git pre-commit hook or a post-deploy step. Set the Vigilmon heartbeat window to 24 hours — a missed daily heartbeat means the last config change or deployment didn't validate cleanly.
Step 8: Status page and badge
Status page:
- Go to Status Pages → New Status Page in Vigilmon
- Add all monitors in groups:
- Bridge Core: process health, throughput heartbeat
- Protocol Gateways: Matrix, Telegram, Discord, Slack, IRC
- Stability: reconnection rate heartbeat, config heartbeat
- Copy the public URL
Share the status page URL with your bridged communities. When users in one platform stop seeing messages from another, they can check the status page first before pinging an admin.
README badge:
[](https://status.yourdomain.com)
What you've built
| What | How |
|------|-----|
| Bridge process health | PID-based sidecar HTTP endpoint |
| Matrix homeserver | HTTP monitor on /_matrix/client/versions |
| Telegram Bot API | HTTP monitor on /getMe |
| Discord API | HTTP monitor on /gateway |
| Slack API | HTTP monitor on /api.test |
| IRC server | TCP port monitor |
| Message throughput | Log-based cron heartbeat every 5 min |
| Reconnection stability | Hourly log-based heartbeat |
| Config integrity | Deployment-triggered TOML validation heartbeat |
| Discord/Slack alerts | Vigilmon notification channel |
| Status page | Vigilmon public status page |
Matterbridge bridges your communities. Vigilmon makes sure the bridge itself doesn't silently collapse.
Next steps
- Add log rotation monitoring — a growing unbounded log file can eventually exhaust disk and crash the bridge
- Use Vigilmon response time history to detect when Matrix federation latency spikes before messages start dropping
- If you run multiple Matterbridge instances for redundancy, add separate heartbeat monitors per instance
- Consider adding a test message bot that sends a known message and verifies it appears on the other side — the ultimate end-to-end bridge health check
Get started free at vigilmon.online.