ops-jrz1/specs/002-slack-bridge-integration/quickstart.md
Dan ca379311b8 Add Slack bridge integration feature specification
Includes spec, plan, research, data model, contracts, and quickstart guide
for mautrix-slack Socket Mode bridge deployment.
2025-10-26 14:36:44 -07:00

24 KiB

Quickstart: Slack Bridge Deployment

Feature: 002-slack-bridge-integration Target Environment: ops-jrz1 VPS (45.77.205.49) Estimated Time: 30-45 minutes

Overview

This guide provides step-by-step instructions for deploying the mautrix-slack bridge from scratch. Follow these steps in order to achieve a working Slack↔Matrix bridge.

Prerequisites:

  • NixOS 24.05+ running on ops-jrz1 VPS
  • Matrix homeserver (conduwuit) running on port 8008
  • PostgreSQL running with mautrix_slack database
  • Admin access to Slack workspace "chochacho"
  • Matrix client (Element, etc.)

Success Criteria:

  • Service running without errors
  • Socket Mode connection established
  • Test message flows Slack → Matrix within 5 seconds
  • Test message flows Matrix → Slack within 5 seconds

Phase 0: Pre-Deployment Checks

0.1 Verify Infrastructure

# SSH to VPS
ssh root@45.77.205.49

# Check Matrix homeserver running
systemctl status matrix-continuwuity
curl -s http://localhost:8008/_matrix/client/versions | jq .

# Check PostgreSQL running
systemctl status postgresql
sudo -u postgres psql -c '\l' | grep mautrix_slack

# Check database created
sudo -u postgres psql mautrix_slack -c '\dt'
# Expected: Empty (bridge will create tables on first run)

# Check existing bridge status
systemctl status mautrix-slack
# Expected: Inactive or running but not authenticated

If checks fail:

  • Matrix homeserver not running → Start: systemctl start matrix-continuwuity
  • Database doesn't exist → Created by dev-services.nix, redeploy configuration
  • Other issues → Review recent worklogs in docs/worklogs/

0.2 Review Current Configuration

# Check current mautrix-slack configuration
cat /run/current-system/configuration.nix | grep -A 20 "mautrix-slack"

# Check if service is enabled
systemctl list-unit-files | grep mautrix-slack

Current State (as of 2025-10-22):

  • Module exists: modules/mautrix-slack.nix
  • Configured for "delpadtech" workspace (needs update)
  • Service exits with code 11 (missing credentials)

Phase 1: Slack App Configuration

1.1 Create Slack App

  1. Open browser: https://api.slack.com/apps
  2. Click "Create New App"
  3. Choose "From an app manifest"
  4. Select workspace: "chochacho"

1.2 Configure App Manifest

  1. Paste the following manifest (from mautrix-slack):
display_information:
  name: Matrix Bridge
  description: Bridge for Matrix↔Slack messaging
  background_color: "#000000"

features:
  bot_user:
    display_name: Matrix Bridge
    always_online: true

oauth_config:
  scopes:
    bot:
      - channels:history
      - channels:read
      - channels:write.invites
      - channels:write.topic
      - chat:write
      - chat:write.customize
      - chat:write.public
      - emoji:read
      - files:read
      - files:write
      - groups:history
      - groups:read
      - groups:write
      - groups:write.invites
      - groups:write.topic
      - im:history
      - im:read
      - im:write
      - im:write.topic
      - mpim:history
      - mpim:read
      - mpim:write
      - mpim:write.topic
      - pins:read
      - pins:write
      - reactions:read
      - reactions:write
      - team:read
      - users.profile:read
      - users:read
      - users:read.email

settings:
  event_subscriptions:
    bot_events:
      - app_uninstalled
      - channel_archive
      - channel_created
      - channel_deleted
      - channel_id_changed
      - channel_left
      - channel_rename
      - channel_unarchive
      - file_change
      - file_deleted
      - file_shared
      - group_archive
      - group_deleted
      - group_left
      - group_rename
      - group_unarchive
      - member_joined_channel
      - member_left_channel
      - message.channels
      - message.groups
      - message.im
      - message.mpim
      - pin_added
      - pin_removed
      - reaction_added
      - reaction_removed
      - team_domain_change
      - user_change
      - user_profile_changed
      - user_status_changed

  org_deploy_enabled: false
  socket_mode_enabled: true
  token_rotation_enabled: false
  1. Click "Create"
  2. Review and click "Confirm"

1.3 Enable Socket Mode

  1. In app settings, navigate to "Socket Mode"
  2. Toggle "Enable Socket Mode" to ON
  3. Click "Generate an app-level token"
    • Token name: socket-mode-connection
    • Add scope: connections:write
    • Click "Generate"
  4. Copy the token (starts with xapp-)
    • ⚠️ Important: Save this token securely, you'll need it for authentication
    • Format: xapp-1-A0123456789-1234567890123-abc...xyz

1.4 Install App to Workspace

  1. Navigate to "Install App"
  2. Click "Install to Workspace"
  3. Review permissions (29 bot scopes)
  4. Click "Allow"
  5. Copy the "Bot User OAuth Token" (starts with xoxb-)
    • ⚠️ Important: Save this token securely
    • Format: xoxb-1234567890-1234567890123-AbC...WxY

1.5 Verify Tokens

Create a temporary file to store tokens (delete after use):

# On local workstation (NOT on VPS)
cat > /tmp/slack-tokens.txt <<EOF
Bot Token (xoxb-): xoxb-YOUR-TOKEN-HERE
App Token (xapp-): xapp-YOUR-TOKEN-HERE
EOF

chmod 600 /tmp/slack-tokens.txt

Token Security:

  • These tokens grant full access to your Slack workspace
  • Never commit to git
  • Never share publicly
  • Store in password manager for long-term
  • Tokens will be stored in bridge database after authentication

Phase 2: NixOS Configuration

2.1 Update Bridge Configuration

Edit hosts/ops-jrz1.nix:

# Enable mautrix-slack bridge
services.mautrix-slack = {
  enable = true;

  matrix = {
    homeserverUrl = "http://127.0.0.1:8008";
    serverName = "clarun.xyz";
  };

  database = {
    type = "postgres";
    uri = "postgresql:///mautrix_slack?host=/run/postgresql";
  };

  appservice = {
    port = 29319;
  };

  bridge = {
    permissions = {
      "clarun.xyz" = "user";
    };
  };

  # Use debug logging for initial deployment
  logging = {
    level = "debug";  # Change to "info" after successful deployment
  };
};

Changes from current config:

  • Removed workspace-specific settings (no longer needed with interactive login)
  • Added debug logging
  • Simplified configuration

2.2 Verify olm-3.2.16 Allowed

Check if production.nix has:

nixpkgs.config.permittedInsecurePackages = [ "olm-3.2.16" ];

Status: Already present in production.nix (commit 0cbbb19)

2.3 Deploy Configuration

# On local workstation
cd /home/dan/proj/ops-jrz1

# Check git status
git status

# Review changes
git diff hosts/ops-jrz1.nix

# Commit changes
git add hosts/ops-jrz1.nix
git commit -m "Enable mautrix-slack bridge for chochacho workspace"

# Deploy to VPS
nixos-rebuild switch --flake .#ops-jrz1 \
  --target-host root@45.77.205.49 \
  --build-host localhost

# Expected output:
# - Building configuration...
# - Activating configuration...
# - Starting mautrix-slack.service...

Deployment time: ~2-5 minutes


Phase 3: Service Verification

3.1 Check Service Status

# SSH to VPS
ssh root@45.77.205.49

# Check service running
systemctl status mautrix-slack

# Expected output:
# ● mautrix-slack.service - mautrix-slack
#    Loaded: loaded
#    Active: active (running)
#    Main PID: [number]

# View recent logs
journalctl -u mautrix-slack -n 50

# Expected log entries:
# INFO [Main] mautrix-slack starting
# INFO [Database] Connected to PostgreSQL
# INFO [AppService] Listening on http://127.0.0.1:29319
# INFO [Bridge] Waiting for authentication

If service fails to start:

  • Check logs: journalctl -u mautrix-slack -n 100 --no-pager
  • Look for common errors:
    • Database connection failed → Check PostgreSQL running
    • Port already in use → Check nothing else on 29319
    • olm error → Verify permittedInsecurePackages set
    • Exit code 11 → Likely missing credentials (expected at this stage)

3.2 Verify Registration File

# Check registration file exists
ls -l /var/lib/matrix-appservices/mautrix_slack_registration.yaml

# View contents
cat /var/lib/matrix-appservices/mautrix_slack_registration.yaml

# Expected structure:
# id: slack
# url: http://127.0.0.1:29319
# as_token: [auto-generated]
# hs_token: [auto-generated]
# sender_localpart: slackbot
# namespaces:
#   users:
#     - regex: "^@slackbot:clarun.xyz$"
#       exclusive: true
#     - regex: "^@slack_.*:clarun.xyz$"
#       exclusive: true

3.3 Register Appservice with Homeserver

For conduwuit (current homeserver):

# Stop homeserver
systemctl stop matrix-continuwuity

# Add registration to configuration
# Edit: /var/lib/matrix-continuwuity/continuwuity.toml
cat >> /var/lib/matrix-continuwuity/continuwuity.toml <<EOF

[[appservices]]
registration = "/var/lib/matrix-appservices/mautrix_slack_registration.yaml"
EOF

# Restart homeserver
systemctl start matrix-continuwuity

# Verify homeserver loaded appservice
journalctl -u matrix-continuwuity -n 20 | grep -i slack
# Expected: "Loaded appservice: slack"

Alternative: Update via NixOS configuration if conduwuit module supports appservice registration.


Phase 4: Bridge Authentication

4.1 Create Matrix DM with Bridge Bot

  1. Open Matrix client (Element Web, Element Desktop, etc.)
  2. Log in as admin user
  3. Start new Direct Message
  4. Enter: @slackbot:clarun.xyz
  5. Send message: Hello

Expected Response:

Welcome to the Slack bridge.
Use `help` to see available commands.
You are not logged in. Use `login app` to authenticate.

If no response:

  • Check bot user exists: Try to view profile of @slackbot:clarun.xyz
  • Check appservice registration loaded by homeserver
  • Check bridge logs: journalctl -u mautrix-slack -f
  • Verify homeserver can reach appservice: curl http://127.0.0.1:29319/_matrix/app/v1/transactions

4.2 Authenticate with Slack

In the DM with @slackbot:clarun.xyz:

  1. Send command: login app

  2. Bot prompts: Please provide bot token (xoxb-...)

    • Paste your bot token from Phase 1.5
    • Format: xoxb-1234567890-1234567890123-AbCdEfGhIjKlMnOpQrStUvWxYz
  3. Bot prompts: Please provide app token (xapp-...)

    • Paste your app token from Phase 1.5
    • Format: xapp-1-A0123456789-1234567890123-abc123def456...xyz
  4. Expected Success Message:

Successfully logged in to Slack workspace: chochacho
Syncing recent conversations (conversation_count: 10)
Creating portals for active channels...
Done. You should receive invitations to bridged rooms shortly.

Authentication logs (on VPS):

# Watch logs during authentication
journalctl -u mautrix-slack -f

# Expected log entries:
# INFO [Auth] Received login command
# INFO [Auth] Validating bot token
# INFO [Slack] Connecting to workspace: chochacho
# INFO [Socket] Calling apps.connections.open
# INFO [Socket] WebSocket URL received: wss://wss.slack.com/link/...
# INFO [Socket] Connecting to WebSocket
# INFO [Socket] Connected successfully
# INFO [Socket] Received hello message
# INFO [Portal] Syncing 10 recent conversations
# INFO [Portal] Creating portal for channel: #general (C0123ABC)
# INFO [Portal] Creating portal for channel: #dev-platform (C0456DEF)

4.3 Verify Socket Mode Connection

# Check logs for Socket Mode status
journalctl -u mautrix-slack -n 20 | grep -i "socket\|websocket\|connected"

# Expected:
# INFO [Socket] WebSocket connected
# INFO [Socket] Connection state: connected

Health Indicators:

  • connection_status: connected
  • last_successful_message: Updated within last minute
  • error_count: 0

Phase 5: Testing

5.1 Join Bridged Room

  1. In Matrix client, check for room invitations
  2. You should see invites for Slack channels:
    • #slack_general:clarun.xyz
    • #slack_dev-platform:clarun.xyz
    • Others based on recent Slack activity
  3. Join #slack_dev-platform:clarun.xyz (or your test channel)

Expected room state:

  • Room name: "dev-platform (Slack)" or similar
  • Room topic: Synced from Slack channel topic
  • Members: Bridge bot + ghost users for Slack members

5.2 Test Slack → Matrix

  1. In Slack app/web, go to #dev-platform channel
  2. Post test message: Hello from Slack! Testing bridge.
  3. Wait (should appear in Matrix within 5 seconds)

Expected in Matrix:

  • Message appears in #slack_dev-platform:clarun.xyz
  • Sender: @slack_U123ABC:clarun.xyz (ghost user)
  • Display name: Your Slack display name
  • Timestamp: Match Slack timestamp
  • Latency: <5 seconds (FR-001 requirement)

If message doesn't appear:

  • Check Slack WebSocket connection: journalctl -u mautrix-slack -f
  • Look for event reception log: INFO [Message] Relaying message from Slack
  • Verify Matrix homeserver reachable
  • Check for errors in bridge logs

5.3 Test Matrix → Slack

  1. In Matrix client, in #slack_dev-platform:clarun.xyz
  2. Send test message: Hello from Matrix! Bridge working.
  3. Wait (should appear in Slack within 5 seconds)

Expected in Slack:

  • Message appears in #dev-platform
  • Sender: Matrix Bridge bot (or your display name via customization)
  • Content: "Your Matrix Name: Hello from Matrix! Bridge working."
  • Latency: <5 seconds (FR-002 requirement)

If message doesn't appear:

  • Check bot token valid: Look for Slack API errors
  • Verify bot is member of channel
  • Check for rate limiting errors
  • Look for relay errors in logs

5.4 Test Additional Features

Reactions (FR-003):

  1. In Slack, react to a message with 👍
  2. Verify reaction appears in Matrix within 5 seconds
  3. In Matrix, react to a message
  4. Verify reaction appears in Slack

File Attachments:

  1. In Slack, upload an image to #dev-platform
  2. Verify image appears in Matrix (as Matrix content URI)
  3. In Matrix, upload a file
  4. Verify file appears in Slack

Edits:

  1. In Slack, edit a message
  2. Verify edit appears in Matrix
  3. In Matrix, edit a message
  4. Verify edit appears in Slack

Threading (if supported):

  1. In Slack, reply in a thread
  2. Verify thread structure in Matrix

5.5 Verify Health Indicators

# Check bridge health
journalctl -u mautrix-slack -n 50 | grep -E "connection|message|error"

# Health indicators (from SC-003a):
# - connection_status: connected
# - last_successful_message: [recent timestamp]
# - error_count: 0 (or very low)

# Check portal count
sudo -u mautrix_slack psql mautrix_slack -c "SELECT COUNT(*) FROM portal;"
# Expected: Number of synced channels (at least 1)

# Check ghost users
sudo -u mautrix_slack psql mautrix_slack -c "SELECT COUNT(*) FROM puppet;"
# Expected: Number of Slack users in bridged channels

Phase 6: Production Readiness

6.1 Reduce Logging Level

After successful testing, reduce log verbosity:

Edit hosts/ops-jrz1.nix:

services.mautrix-slack = {
  # ... existing config ...
  logging = {
    level = "info";  # Changed from "debug"
  };
};

Redeploy:

nixos-rebuild switch --flake .#ops-jrz1 \
  --target-host root@45.77.205.49 \
  --build-host localhost

6.2 Document Deployment

Create worklog entry:

# On local workstation
cat > docs/worklogs/2025-10-22-slack-bridge-deployment.org <<EOF
* Slack Bridge Deployment - Generation [NUMBER]
** Date: 2025-10-22
** Objective: Deploy mautrix-slack bridge for chochacho workspace

** Steps Taken
1. Created Slack app with app manifest
2. Enabled Socket Mode, generated tokens
3. Updated NixOS configuration
4. Deployed to VPS
5. Authenticated bridge via Matrix chat
6. Tested bidirectional messaging

** Results
- ✅ Service running without errors
- ✅ Socket Mode connection established
- ✅ Messages relay Slack → Matrix within [X] seconds
- ✅ Messages relay Matrix → Slack within [X] seconds
- ✅ Reactions, files, edits working

** Configuration
- Workspace: chochacho
- Bridge port: 29319
- Database: PostgreSQL (mautrix_slack)
- Logging: info level
- Portals created: [NUMBER]

** Known Issues
- None

** Next Steps
- Monitor stability over 7 days
- Add additional channels based on team usage
- Consider enabling encryption for sensitive channels
EOF

git add docs/worklogs/2025-10-22-slack-bridge-deployment.org
git commit -m "Document Slack bridge deployment"

6.3 Backup Configuration

# Backup bridge database (optional but recommended)
ssh root@45.77.205.49 'sudo -u postgres pg_dump mautrix_slack' > /tmp/mautrix_slack_backup.sql

# Backup contains:
# - Portal mappings
# - Ghost user profiles
# - Message event mappings
# - Authentication credentials (encrypted in DB)

6.4 Set Up Monitoring

Add to monitoring system (if available):

# Service uptime check
systemctl is-active mautrix-slack

# Connection health (look for "connected" in recent logs)
journalctl -u mautrix-slack --since "5 minutes ago" | grep -i "connected"

# Error rate (should be 0 or very low)
journalctl -u mautrix-slack --since "1 hour ago" | grep -c ERROR

Alerting thresholds:

  • Service down for >5 minutes → Page admin
  • No messages relayed in >1 hour → Warning
  • Error count >10 in 10 minutes → Warning

Phase 7: Gradual Rollout

7.1 Week 1-2: Single Channel Validation

Current state: Bridge working with 1 test channel

Actions:

  • Monitor logs daily: journalctl -u mautrix-slack --since today
  • Test all features: messages, reactions, files, edits
  • Document any issues or unexpected behavior
  • Gather feedback from test users (2-3 people)

Success criteria:

  • Zero service crashes
  • All messages delivered within 5 seconds
  • No user-reported issues

7.2 Week 3-4: Multi-Channel Expansion

After Week 1-2 validation succeeds:

  1. Invite Slack bot to additional channels:

    # In Slack workspace
    /invite @Matrix Bridge to #general
    /invite @Matrix Bridge to #random
    
  2. Portals auto-create when bot joins or messages arrive

  3. Invite Matrix users to new bridged rooms

  4. Monitor performance:

    • Database size: sudo -u postgres psql mautrix_slack -c '\dt+'
    • Memory usage: systemctl status mautrix-slack | grep Memory
    • Message count: SELECT COUNT(*) FROM message;

Success criteria:

  • Handle 1000 messages/day per channel (SC-002 requirement)
  • 99% uptime over 7 days (SC-004 requirement)

7.3 Week 5+: Full Team Adoption

After multi-channel testing succeeds:

  1. Announce to team: Bridge is production-ready
  2. Provide user guide: How to authenticate, join rooms
  3. Let adoption grow organically: Portals created on-demand
  4. Monitor health metrics: Weekly review of logs and performance

Ongoing maintenance:

  • Weekly log review for errors
  • Monthly token rotation (optional, recommended every 90 days)
  • Periodic bridge version updates (via nixpkgs-unstable)

Troubleshooting

Service Won't Start

Symptom: systemctl status mautrix-slack shows failed

Checks:

  1. Review logs: journalctl -u mautrix-slack -n 100
  2. Check database connection: sudo -u mautrix_slack psql mautrix_slack -c '\conninfo'
  3. Check port availability: ss -tuln | grep 29319
  4. Verify olm package allowed: grep permittedInsecurePackages production.nix

Common fixes:

  • Database not created → Check dev-services.nix, redeploy
  • Port in use → Change appservice.port in config
  • Permission error → Check file ownership in /var/lib/mautrix_slack

Socket Mode Disconnects Frequently

Symptom: Logs show repeated disconnects/reconnects

Checks:

  1. Check rate limiting: Look for "rate limited" in logs
  2. Verify token validity: Test tokens in Slack API tester
  3. Check network stability: ping -c 100 wss.slack.com

Common causes:

  • Rate limit hit (1 connection/minute) → Automatic recovery, just wait
  • Token revoked → Re-authenticate with new tokens
  • Network issues → Check VPS network status

Messages Not Relaying

Symptom: Messages sent but don't appear in destination

Slack → Matrix troubleshooting:

  1. Check Socket Mode connected: journalctl -u mautrix-slack | grep -i websocket
  2. Look for event reception: grep "message.channels" logs
  3. Verify portal exists: psql -c "SELECT * FROM portal WHERE name='dev-platform';"
  4. Check homeserver reachable: curl http://localhost:8008/_matrix/client/versions

Matrix → Slack troubleshooting:

  1. Check bot token valid: Look for auth errors
  2. Verify bot in channel: Check Slack channel members
  3. Look for rate limit errors: grep "rate_limit" logs
  4. Test Slack API manually: curl -H "Authorization: Bearer xoxb-..." https://slack.com/api/chat.postMessage ...

Exit Code 11 (SIGSEGV)

Symptom: Service crashes with exit code 11

Likely causes (from research.md):

  1. Missing credentials (most common at initial deployment)
  2. Incomplete configuration
  3. Security hardening conflicts

Fixes:

  1. Enable debug logging
  2. Temporarily disable systemd hardening:
    # In mautrix-slack.nix service config
    # Comment out: NoNewPrivileges, ProtectSystem, etc.
    
  3. Check for nil pointer dereference in logs
  4. Verify all required config fields present

Reference Information

Useful Commands

# Service management
systemctl status mautrix-slack
systemctl restart mautrix-slack
systemctl stop mautrix-slack

# View logs
journalctl -u mautrix-slack -f                    # Follow logs
journalctl -u mautrix-slack -n 100                # Last 100 lines
journalctl -u mautrix-slack --since "1 hour ago"  # Last hour
journalctl -u mautrix-slack --since today         # Today's logs

# Database queries
sudo -u mautrix_slack psql mautrix_slack -c "SELECT * FROM portal;"
sudo -u mautrix_slack psql mautrix_slack -c "SELECT * FROM puppet LIMIT 10;"
sudo -u mautrix_slack psql mautrix_slack -c "SELECT COUNT(*) FROM message;"

# Configuration files
/var/lib/mautrix_slack/config/config.yaml                     # Generated config
/var/lib/matrix-appservices/mautrix_slack_registration.yaml   # Appservice registration
/nix/store/.../modules/mautrix-slack.nix                      # NixOS module

# Check service resources
systemctl status mautrix-slack | grep -E "Memory|CPU"
ps aux | grep mautrix-slack

Key Endpoints

Service Endpoint Purpose
Bridge http://127.0.0.1:29319 Appservice HTTP server
Homeserver http://127.0.0.1:8008 Matrix client-server API
Database /run/postgresql PostgreSQL Unix socket
Slack WebSocket wss://wss.slack.com/link/ Socket Mode connection

Important File Locations

Path Contents Owner
/var/lib/mautrix_slack/config/ Generated config.yaml mautrix_slack
/var/lib/mautrix_slack/mautrix_slack.db SQLite DB (if not using PostgreSQL) mautrix_slack
/var/lib/matrix-appservices/ Appservice registration files matrix-appservices
/run/secrets/ Decrypted sops-nix secrets root/service user

Success Criteria Checklist

From spec.md:

  • SC-001: Bridge relays messages bidirectionally
  • SC-002: Handle 1000 messages/day per channel
  • SC-003: Reactions sync correctly in both directions
  • SC-003a: Health indicators logged (connection status, last message timestamp, error count)
  • SC-004: 99% uptime over 7-day observation period
  • SC-005: File attachments <10MB sync successfully
  • SC-006: Documentation exists (this quickstart!)

Next Steps

After successful deployment:

  1. Run /speckit.tasks to generate detailed implementation task breakdown
  2. Begin monitoring for 7-day stability period
  3. Gather user feedback from test users
  4. Plan expansion to additional channels based on team usage
  5. Document lessons learned in worklog

Support Resources


Document Version: 1.0 Last Updated: 2025-10-22 Tested On: NixOS 24.05, mautrix-slack (nixpkgs-unstable) Status: Ready for deployment