HowTo 9 min read

2026 OpenClaw MeshMac: Matrix Webhook for Shared Build Status on Multi-Node Remote Mac

M

Published April 1, 2026

Meshmac Team

Teams on a MeshMac pool need one Matrix room for CI state regardless of which Mac runs the build. Here is a minimal path: gateway tokens, webhook or appservice setup, signing, a CI field map, and an FAQ when events vanish—so multi-node observers share one timeline.

Why Matrix Notifications Fail Across Mesh Nodes

  1. Split-brain senders post from different users or aliases, creating duplicate or contradictory lines.
  2. Token sprawl puts full Matrix sessions inside CI images, breaking least privilege when a runner leaks.
  3. Unverified HTTP invites forged payloads; align with our webhook hardening guide.

Use one ingress gateway and the shared queue pattern from multi-node deploy and task queue sync, then emit Matrix events only from that choke point.

Webhook-Only Bot Versus Appservice

Start with a webhook bridge; move to an appservice when you need ghost users or richer transactions.

Pattern Best for Trade-off
Incoming HTTP to bridge Fastest greenfield on a single homeserver Limited schema control; you must validate JSON yourself before the bridge emits m.room.message
Registered appservice Stable multi-room routing and ghost users More moving parts: registration yaml, token pairs, and Synapse reload discipline

Gateway Installation and Tokens

Run the gateway on a stable host reachable from Synapse and CI egress. Set OPENCLAW_CONFIG_ROOT, mount config read-only, and store Matrix secrets outside Git. Create a build bot user, join the team room once, save its access token as 0440 for the gateway user only—workers stay tokenless on the queue. Restart the gateway after token rotation so every MeshMac node picks up the same notify path. See IM alerts and token rotation for cadence.

  • Homeserver URL must match verified TLS; pin fingerprints if self-hosted.
  • Room id should be the full id, not only an alias.
  • Correlation id flows CI → OpenClaw → Matrix body for log joins.

Matrix Webhook and Appservice Configuration Steps

  1. Expose /hooks/matrix/build-status (or similar) behind TLS at the proxy.
  2. Register via the integration manager or app_service_config_files pointing at your yaml.
  3. Set id, url, as_token, hs_token, and namespaces such as buildbot_.
  4. Reload Synapse, curl a signed sample POST, confirm m.room.message.
  5. Document in the topic that every worker adds mesh_node_id for multi-node clarity.

Message Signing or Least-Privilege Verification

Verify every POST: HMAC-SHA256 over raw bytes with constant-time compare, or a bearer secret plus CI egress IP allowlists if the vendor cannot sign. Reject timestamps older than five minutes.

Scope the Matrix token to send in one room only—no invites or admin. Redact Authorization headers in logs and perform verification only on the gateway, not on each Mac.

CI Status Field Mapping Table

Normalize CI JSON before rendering Matrix markdown or plain text.

CI source field Gateway key Matrix message use
workflow name or pipeline name workflow Bold first line so readers recognize which automation fired
status or conclusion state Map to queued, running, succeeded, or failed with emoji guardrails your team agrees on
head branch or ref branch Second line for release versus feature visibility
head sha or commit id commit Short seven character prefix linked to the provider run URL
html_url or web_url run_url Clickable markdown link for deep debugging on the mesh node logs
runner name or custom mesh label mesh_node_id Footer line that disambiguates multi-node pools without opening SSH sessions

Troubleshooting FAQ: When Messages Never Arrive

CI two hundred but no room event
Check membership, bridge logs for empty bodies, and null conclusions in templates; retry with a tiny test workflow.
Appservice signature errors
Diff hs_token in Synapse versus disk yaml, strip secret newlines, curl from the homeserver host to rule out TLS middleboxes.
Only some nodes notify
Runners skipped the shared gateway—unify the webhook URL env and restrict egress to the approved ingress.
Duplicate lines per run
Dedupe with run id plus state keys stored seventy-two hours in Redis or SQLite before emitting Matrix text.

Summary

Send Matrix only from the gateway, verify HTTP callers, map CI fields once, and surface mesh_node_id for pool visibility. Visit the homepage, blog, and help center for next steps.

Notify Every Node From One Matrix Room

Wire Matrix once for every node in the pool. Open the homepage to buy capacity, skim the blog, and read help before checkout.

Rent a Mac