docs: add worklog and final musiclink config fixes
This commit is contained in:
parent
4adf6723c5
commit
73b932ff47
|
|
@ -1 +1 @@
|
|||
ops-jrz1-k3e0
|
||||
ops-jrz1-zr0q
|
||||
|
|
|
|||
82
docs/worklogs/2026-01-20-musiclink-bot-integration.org
Normal file
82
docs/worklogs/2026-01-20-musiclink-bot-integration.org
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
#+TITLE: MusicLink Bot Integration and Matterbridge Matrix Pivot
|
||||
#+DATE: 2026-01-20
|
||||
#+KEYWORDS: musiclink, matterbridge, matrix, slack-bridge, mautrix-slack, conduwuit, sops-nix
|
||||
#+COMMITS: 2
|
||||
#+COMPRESSION_STATUS: uncompressed
|
||||
|
||||
* Session Summary
|
||||
** Date: 2026-01-20
|
||||
** Focus Area: Integration of MusicLink bot into ops-jrz1 infrastructure
|
||||
|
||||
* Accomplishments
|
||||
- [X] Analyzed and cloned =musiclink= source code from =ops-jrz1= to local dev environment.
|
||||
- [X] Integrated =musiclink= as a Nix Flake input in =flake.nix=.
|
||||
- [X] Created =modules/musiclink.nix= to manage systemd services for the bot and its Matterbridge adapter.
|
||||
- [X] Extended =services.dev-platform= in =modules/dev-services.nix= to include MusicLink configuration.
|
||||
- [X] Migrated Slack tokens to =sops-nix= and added new =musiclink-matrix-token=.
|
||||
- [X] Provisioned =@musiclink:clarun.xyz= user on the homeserver via Matrix API.
|
||||
- [X] Successfully deployed the configuration to =ops-jrz1= VPS.
|
||||
- [X] Verified VM integration tests pass with the new module.
|
||||
- [X] Granted server admin privileges to =@musiclink:clarun.xyz= to facilitate room management.
|
||||
|
||||
* Key Decisions
|
||||
|
||||
** Decision 1: Pivot to Matrix-mediated bridging
|
||||
- Context: =musiclink= requires Matterbridge WebSocket API. Matterbridge (stable) lacks Slack Socket Mode support, which our Slack App requires.
|
||||
- Options considered:
|
||||
1. Patch Matterbridge to support Socket Mode (high effort).
|
||||
2. Use Slack Events API (requires public ingress/TLS management).
|
||||
3. Route via Matrix using =mautrix-slack= as the gateway (Matrix-native approach).
|
||||
- Rationale: Matrix-mediated routing leverages existing infrastructure (=mautrix-slack=) and treats Matrix as the universal communication bus.
|
||||
- Impact: =MusicLink= -> =Matterbridge= -> =Matrix= -> =mautrix-slack= -> =Slack=.
|
||||
|
||||
** Decision 2: Read-only listener for Slack-bridged rooms
|
||||
- Context: Safety constraint to prevent the bot from posting test/automated messages back to Slack during initial setup.
|
||||
- Rationale: Configured Matterbridge gateway as =[[gateway.in]]= for the Matrix side.
|
||||
- Impact: The bot can see and process links from Slack but cannot post back to the channel.
|
||||
|
||||
** Decision 3: Use local file path for Flake input (Workaround)
|
||||
- Context: =nix flake check= failed to authenticate with =git.clarun.xyz= via HTTPS/SSH.
|
||||
- Rationale: Cloned the repo locally and used =git+file:///home/dan/proj/musiclink= to unblock development.
|
||||
- Impact: Filed beads issue =ops-jrz1-zr0q= to resolve permanent git access.
|
||||
|
||||
* Problems & Solutions
|
||||
| Problem | Solution | Learning |
|
||||
|---------+----------+----------|
|
||||
| Matterbridge failed with =not_allowed_token_type= on Slack | Pivoted to Matrix bridge; Matterbridge RTM is incompatible with modern Socket Mode apps | Matterbridge Slack support is lagging behind Slack API changes |
|
||||
| MusicLink crashed with "malformed ws URL" | Changed protocol from =http://= to =ws://= in bot config | WebSocket clients are strict about the =ws://= scheme |
|
||||
| Matterbridge failed Matrix login with =missing field password= | Added =MxID= to config to trigger token-based auth bypass | Matterbridge needs explicit User ID to use an existing access token |
|
||||
| =M_FORBIDDEN= when joining portal room | Granted server admin to bot via =conduwuit --execute= command | Admin status alone doesn't bypass invite-only rules for standard =/join= calls |
|
||||
|
||||
* Technical Details
|
||||
|
||||
** Code Changes
|
||||
- =modules/musiclink.nix=: Defines systemd services with =DynamicUser= and =LoadCredential= for secret safety.
|
||||
- =hosts/ops-jrz1.nix=: Enabled MusicLink, disabled Maubot, added sops secrets.
|
||||
- =flake.nix=: Wired up the new input and passed it to configurations and tests.
|
||||
|
||||
** Commands Used
|
||||
#+BEGIN_SRC bash
|
||||
# Register Matrix user
|
||||
curl -s -X POST -H "Content-Type: application/json" \
|
||||
-d '{"username":"musiclink", "password":"...", "auth":{"type":"m.login.registration_token", "token":"..."}}'
|
||||
http://127.0.0.1:8008/_matrix/client/v3/register
|
||||
|
||||
# Grant admin status via Conduwuit console
|
||||
conduwuit -c continuwuity.toml --execute "admin users make-user-admin @musiclink:clarun.xyz"
|
||||
|
||||
# Find Room ID from mautrix-slack DB
|
||||
sudo -u postgres psql mautrix_slack -c 'SELECT id, mxid, name FROM portal;'
|
||||
#+END_SRC
|
||||
|
||||
* Process and Workflow
|
||||
- Used =nix flake check= and VM integration tests to verify module structure before deployment.
|
||||
- Incremental deployment via =nixos-rebuild switch= allowed catching configuration mismatches (=http= vs =ws=, =MxID= requirement).
|
||||
- Conscious pivot from a blocked path (Matterbridge Slack) to a viable one (Matrix mediation).
|
||||
|
||||
* Next Steps
|
||||
- [ ] User to invite =@musiclink:clarun.xyz= to the =#music= Matrix room.
|
||||
- [ ] Verify message flow: Slack -> Matrix -> MusicLink.
|
||||
- [ ] Enable outbound posting (=gateway.out=) once processing logic is verified.
|
||||
- [ ] Resolve git access issue for the musiclink flake input.
|
||||
- [ ] Close beads task =ops-jrz1-k3e0= (AGENTS.md review).
|
||||
|
|
@ -57,6 +57,9 @@
|
|||
|
||||
# Forgejo API token for dev user provisioning (root only)
|
||||
forgejo-api-token.mode = "0400";
|
||||
|
||||
# Matrix token for MusicLink bot
|
||||
musiclink-matrix-token.mode = "0400";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -56,30 +56,23 @@ in {
|
|||
|
||||
# Secrets
|
||||
LoadCredential = [
|
||||
"slack-bot-token:/run/secrets/slack-bot-token"
|
||||
"slack-app-token:/run/secrets/slack-app-token"
|
||||
"musiclink-matrix-token:/run/secrets/musiclink-matrix-token"
|
||||
];
|
||||
|
||||
ExecStartPre = pkgs.writeShellScript "generate-matterbridge-config" ''
|
||||
set -euo pipefail
|
||||
|
||||
SLACK_TOKEN=$(cat $CREDENTIALS_DIRECTORY/slack-bot-token)
|
||||
SLACK_APP_TOKEN=$(cat $CREDENTIALS_DIRECTORY/slack-app-token)
|
||||
MATRIX_TOKEN=$(cat $CREDENTIALS_DIRECTORY/musiclink-matrix-token)
|
||||
|
||||
cat > /var/lib/musiclink-matterbridge/matterbridge.toml <<EOF
|
||||
[api.local]
|
||||
BindAddress="127.0.0.1:${toString cfg.matterbridge.port}"
|
||||
Token="musiclink-internal-token"
|
||||
|
||||
[[slack]]
|
||||
[slack.my-slack]
|
||||
Token="$SLACK_TOKEN"
|
||||
AppToken="$SLACK_APP_TOKEN"
|
||||
# Socket Mode is cleaner (no public ingress needed)
|
||||
# If using Socket Mode, we usually need app-level token.
|
||||
# Matterbridge supports it? It seems to use standard Slack API.
|
||||
# Let's assume standard RTM or Events API if not specified.
|
||||
# Wait, for standard Slack bot we need 'Token'. 'AppToken' is for Socket Mode.
|
||||
[matrix.clarun]
|
||||
Server="http://127.0.0.1:8008"
|
||||
Token="$MATRIX_TOKEN"
|
||||
MxID="@musiclink:clarun.xyz"
|
||||
|
||||
[[gateway]]
|
||||
name = "musiclink-gateway"
|
||||
|
|
@ -88,9 +81,10 @@ enable = true
|
|||
[[gateway.inout]]
|
||||
account = "api.local"
|
||||
|
||||
[[gateway.inout]]
|
||||
account = "slack.my-slack"
|
||||
channel = "${cfg.matterbridge.slackChannel}"
|
||||
# Read-only from Slack (via Matrix bridge) - DO NOT POST BACK
|
||||
[[gateway.in]]
|
||||
account = "matrix.clarun"
|
||||
channel = "!6wiPLmomcgAoELWta1:clarun.xyz"
|
||||
EOF
|
||||
'';
|
||||
|
||||
|
|
@ -119,7 +113,7 @@ EOF
|
|||
ExecStartPre = pkgs.writeShellScript "generate-musiclink-config" ''
|
||||
cat > /var/lib/musiclink/config.toml <<EOF
|
||||
[matterbridge]
|
||||
url = "http://127.0.0.1:${toString cfg.matterbridge.port}/api/websocket"
|
||||
url = "ws://127.0.0.1:${toString cfg.matterbridge.port}/api/websocket"
|
||||
token = "musiclink-internal-token"
|
||||
gateway = "musiclink-gateway"
|
||||
username = "MusicLink"
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ restic:
|
|||
b2_account_id: ENC[AES256_GCM,data:Arz8ZZ8ahVNjvlPlVEbRbLzWMmLS3AXdgQ==,iv:YcOcAFIs3KjWEpMVOM7mtBGmdrh4IG47/esZIyxeUTg=,tag:eOi7Z4CW9DgzDFjjQwGsdg==,type:str]
|
||||
b2_account_key: ENC[AES256_GCM,data:9jpuaRaGtGxz+Bp9wlOr5apECRorkpsC7+4+wrxUAQ==,iv:WFwKWc1yR8sU7xKVZ40RkCCGVzChGMxLLc5L6D12UBY=,tag:SwLzS6MwA0O1G6XwHo1LtA==,type:str]
|
||||
b2_repo: ENC[AES256_GCM,data:JcvCGIJunXFq99mfo7+GQVjR,iv:ym7mu7yNwNZ2MuViKaEe6WXLuS58k++nFA42ZJHsbis=,tag:0mBsoVKY7aTzv4SxB8Jcyg==,type:str]
|
||||
musiclink-matrix-token: ENC[AES256_GCM,data:q+AG0vFTUm3Bq9EMZog2eFkaJM4NhB0OLJ5vDjKUsaM=,iv:BwvbPdWA4INvatjTVc0CVMcbFrMZMAddtnvt8JsCLzE=,tag:W2ZMAaIomj5eOfa8SskYPg==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- recipient: age1vuxcwvdvzl2u7w6kudqvnnf45czrnhwv9aevjq9hyjjpa409jvkqhkz32q
|
||||
|
|
@ -40,7 +41,7 @@ sops:
|
|||
Y01xOHdGZ2tmL2NyZkJwRU82dGF5SUEK4qfPmXNbIw/vZv1PzMDB7Ya4bB+kl0HJ
|
||||
XBV4M9UWzJ1Zi0qJzsk/HTKAk1147NAKH+koYaK03TPqf3Wkk3AHoQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2026-01-10T21:48:44Z"
|
||||
mac: ENC[AES256_GCM,data:HGGz77ONHpz/OjwJU1+F+D+MJyHJP/UrCytjrYKTRK1pirNsJWyCwWDSKkpXvLt3vgJBlnWLgzbCk9Bp7NpYOO+QooRETdIqaZHSpEGoQjcJjY1o/8j4/THxwTb0Yh5mVZKQg39tEGIFOIcYc8HLPBLGQEbh6JGN2F/4r5PseWI=,iv:70QniATCsMmRfpdPbDspUle35Okxj1y4AhEJvY1CpQI=,tag:HnsKH/qqC9bUsk2aHSkTZQ==,type:str]
|
||||
lastmodified: "2026-01-20T22:29:44Z"
|
||||
mac: ENC[AES256_GCM,data:TXXl0BfgSQtxOuL2e8KxZUOTkQlKLnbDJoqa+Cn57QSHcqs/6QG1Be+INa9HB/El755Vo4evHcVKkt63wKTk/4fEmRIfj13cnq/QTQLqpmSF00/XSWEi7NPKKafsp9lSWu9KAKiG1BxDClDhydUZomxtCOKAlYzsHiWvy70jk0o=,iv:hTN65KdJpkMUnXj8BrUixkmuQSxYUpt/wAWLlW9O7hA=,tag:yTuOAmKSwSSGrxFajVihDg==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.11.0
|
||||
|
|
|
|||
Loading…
Reference in a new issue