Audience: teams running Bitbucket Pipelines who want a stable remote Mac with OpenClaw terminating repository webhooks, running dependency preflight after pipeline events, and POSTing build summaries to Slack or internal HTTP without storing broad credentials on shared runners. Follow docs.openclaw.ai for install defaults. Size disk and concurrency using the remote Mac build node guide; SSH steps are public on Help (no login to read).

Why a gateway matters: Bitbucket should not hold every mirror secret, long-lived git credential, and regional proxy policy. An OpenClaw listener on Apple Silicon centralizes X-Hub-Signature verification, structured logs, and outbound retries while the Mac keeps a repository read-only app password or HTTPS token scoped to clone URLs referenced in webhook JSON.

  • Reproducibility checklistNode 22 pinned in launchd; openclaw doctor clean; nginx or Caddy terminates TLS; webhook secret file mode 600; synchronous handler returns 2xx in under ~10s; summary worker uses three POST attempts with 2s / 4s / 8s backoff.
  • Repository webhook subscribed to pipeline completion (or the equivalent event list your workspace shows); runbook records repository.full_name, commit hash, pipeline.uuid, and X-Request-UUID.
  • Per-event workdir under /var/tmp/bb-openclaw/<uuid>; SQLite or Redis stores seen UUIDs for twenty four hours to absorb Bitbucket redeliveries.
  • Silent HMAC failures: middleware pretty-prints JSON after TLS so the digest no longer matches X-Hub-Signature.
  • Retry storms: running a full npm ci or bundle install inside the synchronous webhook path exceeds Bitbucket’s delivery window.
  • Permission confusion: repository admin is required to add webhooks—HTTP 403 in the UI is often mistaken for a broken Mac route.

Prerequisites

Install Node 22 LTS for the UNIX account that owns the gateway. Use the official installer or npm install -g openclaw, run openclaw onboard, then openclaw doctor until PATH, listening ports, and Node version warnings are gone. Mirror the same NODE_BINARY and PATH inside a LaunchAgent plist so SSH sessions and background jobs behave identically.

Create ~/.config/openclaw/bitbucket-secret (mode 600) for the webhook secret. Store a read-only Bitbucket app password or scoped HTTP access token with Repositories: Read only—enough for git clone https://x-token-auth:<token>@bitbucket.org/…. Never place a workspace admin token on the gateway unless you are automating webhook CRUD.

Control Purpose Minimal pattern
Listener bind Shrink attack surface OpenClaw on 127.0.0.1; public HTTPS only on reverse proxy
Raw body Valid X-Hub-Signature Disable gzip to upstream for hook location; pass through bytes unchanged
Git identity Clone private repos referenced in JSON Repo-scoped read token; rotate if copied into tickets

Auditable fact: log X-Request-UUID, pipeline UUID, commit, and preflight exit code on one line to ~/Library/Logs/OpenClaw/bitbucket-pipeline.log (or syslog) so retries and OpenClaw skill runs share the same correlation id.

Webhook configuration

In Bitbucket open Repository settings → Webhooks → Add webhook. Paste the public URL that maps to your OpenClaw route, keep SSL / TLS verification enabled, and set a long random secret—Bitbucket signs deliveries with HMAC-SHA256 and sends X-Hub-Signature: sha256=<hex> plus X-Request-UUID. You need repository admin; otherwise the UI returns permission errors that look like network faults.

Under Triggers, pick events that fire when you care about dependency policy—commonly a pipeline or build completion hook depending on your Bitbucket Cloud generation. Skip noisy triggers such as every push if you only want post-pipeline summaries. Send a test request, capture headers in nginx access_log or OpenClaw debug, and confirm your handler returns HTTP 200 within roughly ten seconds so Bitbucket stops retrying that attempt.

Verification: strip the sha256= prefix, compute HMAC_SHA256(secret, rawBody), compare with crypto.timingSafeEqual in Node or hmac.compare_digest in Python. Hash the buffer before JSON.parse. Cross-check with Atlassian’s webhook documentation if your workspace shows alternate header names behind feature flags.

1
Expose HTTPS to the documented OpenClaw path; curl -v https://hooks.example.com/openclaw/bitbucket from the public internet must hit the same cert Bitbucket will validate.
2
Create the webhook with a unique secret; paste the secret only into Bitbucket and the Mac file, nowhere else.
3
Select triggers aligned to pipeline completion; document the exact event labels in your runbook for on-call.
4
Run test delivery; verify signature offline with a saved raw body file and the shared secret.
5
Filter in code: ignore non-default branches or non-success pipeline states before expensive clones.
// Node: rawBody must be Buffer; secret from file mode 600
// const sig = req.headers['x-hub-signature']; // 'sha256=' + hex
// const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
// crypto.timingSafeEqual(Buffer.from(sig.slice(7), 'hex'), Buffer.from(expected, 'hex'))

Preflight script chaining

After authentication, parse JSON for repository.full_name, commit id, and pipeline identifiers. Export GIT_CLONE_URL with the read-only token embedded. Create a disposable directory per X-Request-UUID, git clone --depth 1 at the reported commit, then chain stack-specific dry runs: Node npm ci --dry-run or pnpm install --frozen-lockfile --prefer-offline with --dry-run where supported; Ruby bundle check plus bundle outdated --strict as a soft signal; PHP composer validate and composer install --dry-run. Exit non-zero only for policy breaches you want highlighted; capture the last eighty lines of stdout/stderr into the summary payload.

Keep the synchronous slice under the webhook budget: verify signature, optionally enqueue a LaunchAgent job or OpenClaw skill with the UUID, return { "accepted": true, "requestUuid": "…" } immediately. Run the heavy chain in the worker. The same orchestration pattern appears in the Jenkins generic webhook preflight playbook—swap payload fields only.

#!/usr/bin/env bash
set -euo pipefail
# bb-preflight.sh <clone-url> <commit>
WORKDIR="$(mktemp -d /tmp/bb-pf-XXXXXX)"
git clone --depth 48 "$1" "$WORKDIR/repo"
cd "$WORKDIR/repo" && git checkout --detach "$2"
npm ci --dry-run 2>&1 | tail -n 80

Tail log show --predicate 'process == "node"' --last 30m when launchd stderr is empty; often the plist WorkingDirectory or token env var is missing compared to your interactive SSH test.

Summary feedback

When preflight finishes, POST a compact JSON document to your chat webhook or internal API: include repository, commit, pipelineUuid, preflightExitCode, truncated log excerpt, and a deep link to the Bitbucket pipeline run. Use three attempts with sleeps of 2, 4, and 8 seconds and an HTTP client timeout near 25 seconds per attempt so transient egress blips do not lose the summary.

If the outbound endpoint requires its own bearer token, store it beside the Bitbucket read token with the same mode 600 and separate rotation policy. Structured fields make it easy to alert only when preflightExitCode != 0 while still archiving every run for audits.

Reference numbers you can quote: ten-second synchronous budget for the inbound hook; three summary retries; twenty four-hour dedupe window for UUIDs; twenty five-second per-attempt outbound timeout.

FAQ and common errors

Every X-Hub-Signature check fails

Confirm nginx is not decompressing or modifying the body, that you slice off the sha256= prefix correctly, and that the secret in Bitbucket matches the file on disk byte for byte.

Bitbucket retries; nginx logs show slow upstream

Move cloning and package managers out of the request thread; respond 200 immediately after verify (and optional enqueue). Watch for DNS or TLS handshake latency to localhost misconfigured upstreams.

403 when creating the webhook or 401 from git clone

Webhook creation needs repository admin. Clone failures mean the app password lacks repository read or the clone URL still uses an old username instead of x-token-auth.

Duplicate summaries after pipeline reruns

Dedupe on X-Request-UUID plus pipeline UUID; return 200 even when skipping duplicate work so Bitbucket does not back off incorrectly.

Closing checklist

  1. Doctor-clean gateway user with pinned Node and plist env.
  2. TLS → loopback; raw POST bytes preserved for HMAC.
  3. Bitbucket secret on disk; repository read token scoped.
  4. Preflight in worker; fast 200 JSON acknowledgment.
  5. Summary POST 2/4/8s retries; UUID dedupe store warm.

Rent a remote Mac for always-on webhooks: laptops sleep; data-center Mac Minis do not. Start from Home, compare plans on Pricing, provision via Purchase, then use Help for SSH. More automation articles live on the Technical Blog.

MacPull hosts Apple Silicon machines so OpenClaw stays online for Bitbucket Pipelines webhooks, dependency preflight, and summary delivery without tying up developer laptops.

Run OpenClaw + Bitbucket Pipelines on a dedicated Mac

Stable TLS, signed webhooks, and launchd-backed automation—jump to Home, Purchase, or Help below. Pages are readable without signing in.