Who this is for: platform engineers who want Harbor to notify an OpenClaw gateway on a remote Mac so new or promoted images are prefetched before CI saturates the network, while a compact JSON summary returns to an allowlisted outbound channel. In 2026 community setups you often see curl-based installers for runtimes, openclaw onboard --install-daemon where your distribution documents it, and quick gateway status self-checks (doctor, deep status, or health HTTP probes)—treat those as reference flows from your vendor docs rather than hard dependencies on any single third-party link. For broader registry pull policy on Apple Silicon, see our GHCR vs private registry matrix; for gateway hardening patterns, see OpenClaw gateway security on remote Mac.
  • Cold pulls in CI: jobs still wait on large layers because nothing warmed the runner after Harbor accepted the manifest.
  • Webhook forgery or replay: missing secret handling or hashing the parsed JSON instead of raw bytes breaks trust.
  • Runaway egress: summary callbacks to arbitrary URLs violate corporate allowlists and leak build metadata.

Goals and prerequisites

Goals. When Harbor records a relevant artifact event, your Mac should (1) authenticate the webhook, (2) derive one or more fully qualified image references, (3) prefetch them with bounded parallelism and disk safety, and (4) emit a short JSON summary to a fixed set of outbound hosts so operators see success or structured failure without opening Harbor’s UI.

Prerequisites. A Harbor project with webhook permissions, a TLS-terminated HTTPS entry that forwards to OpenClaw’s listener (often loopback plus reverse proxy), Docker Desktop or Colima with a logged-in daemon for your registry hostname, and a non-interactive service account (robot token or scoped credential) stored at mode 600 on the Mac. Align Node 22 LTS (or the major your OpenClaw release tests against) before installing OpenClaw—many teams still install Node via official curl installers or version managers, then install OpenClaw globally or via the project’s documented script.

Bring the gateway online with openclaw onboard and, when applicable, openclaw onboard --install-daemon so launchd owns restarts. Run openclaw doctor until you understand every warning, then add a cron or LaunchAgent curl probe against the documented health route from the same machine that will receive Harbor traffic. Finally, document an egress allowlist: Harbor ingress CIDRs, registry pull endpoints, and exactly one or two summary destinations (for example internal CI or a signed Slack-compatible webhook behind your API gateway).

Minimal success criterion. Replaying one captured Harbor payload on a staging Mac produces identical digest lines in logs, completes prefetch within your timeout budget, and posts a summary JSON under five kilobytes.

Harbor Webhook event fields and signature verification checklist

Harbor emits JSON envelopes with a type string (for example PUSH_ARTIFACT, PULL_ARTIFACT, DELETE_ARTIFACT), an occur_at timestamp, an operator field, and an event_data object that carries repository and resource metadata. For prefetch you usually care about repository name, tag or digest, and sometimes artifact digest to deduplicate pulls. Keep a printed sample payload in your runbook so field names stay aligned with your Harbor minor version.

Verification checklist (copy into your PR template). (1) Read the raw HTTP body before JSON.parse. (2) Compare Harbor’s configured secret using constant-time equality—either a dedicated header your proxy injects after TLS termination or a shared bearer token Harbor sends per project settings. (3) Reject requests whose Content-Type is not application/json unless you explicitly support alternates. (4) Optionally enforce a freshness window on occur_at if replays worry you. (5) Log only repository plus digest after auth succeeds, never the secret. (6) If you add HMAC later, hash the same raw bytes Harbor signed, not a re-serialized object—proxies that pretty-print JSON are the usual culprit when verification “always fails.”

Field / concern Use in OpenClaw handler
type Gate logic: prefetch on push or retag; ignore deletes unless you prune local images.
event_data.resources Map each resource to registry/project/repo:tag; fall back to digest-pinned pulls when tag is empty.
operator Audit trail and optional rate limits per automation identity.
Raw body integrity Verify secret/HMAC first; return 401 without echoing input on failure.
1
Create the webhook in Harbor pointing to https://your-mac-relay.example/hooks/harbor?token=…; keep query tokens out of shared screenshots.
2
Capture one delivery from Harbor’s webhook history and store the JSON as a fixture for unit tests of your parser.
3
Implement verify-then-parse in OpenClaw’s route handler; reject oversized bodies (for example hard cap one megabyte).
4
Replay from curl with the same headers Harbor uses; confirm logs match line-for-line with a real event.

Remote Mac prefetch script parameters (concurrency, timeout, disk quota)

Once the handler extracts image references, call a small shell script rather than inlining endless docker pull lines—this keeps OpenClaw routes readable and lets operators tune knobs without redeploying TypeScript. Typical 2026 defaults for shared Mini hosts: two to four concurrent pulls, a per-pull wall clock between six and fifteen minutes depending on layer size, and an absolute stop when free disk drops below fifteen to twenty-five gigabytes on the Docker data volume.

Expose parameters as environment variables your LaunchAgent plist sets: PREFETCH_CONCURRENCY, PULL_TIMEOUT_SEC, MIN_FREE_GB, and optionally MAX_IMAGES_PER_EVENT to prevent a misconfigured webhook from queuing hundreds of repos. Use xargs -P or GNU parallel if installed, but stay consistent with macOS BSD xargs limits. After each batch, append a single JSON line to a log file OpenClaw tails for summaries.

#!/usr/bin/env bash
set -euo pipefail
: "${PREFETCH_CONCURRENCY:=3}"
: "${PULL_TIMEOUT_SEC:=600}"
: "${MIN_FREE_GB:=18}"
# macOS: df -g uses 1 GiB blocks (see man df on the runner)
avail_gib="$(df -g / | awk 'NR==2 {print $4}')"
if [ "${avail_gib:-0}" -lt "${MIN_FREE_GB}" ]; then
  printf '{"prefetch":"skipped","reason":"disk_low","avail_gib":%s}\n' "${avail_gib}"
  exit 0
fi
printf '%s\n' "$@" | xargs -n1 -P"${PREFETCH_CONCURRENCY}" -IREF docker pull REF
# Optional: wrap each pull with gtimeout "${PULL_TIMEOUT_SEC}" if GNU coreutils is installed

Replace the placeholder timeout comment with your preferred implementation (gtimeout from coreutils, a Python wrapper, or Docker’s own pull settings). Pair this script with the resilience ideas in OpenClaw Docker integration on remote Mac when CI and the gateway share one host.

OpenClaw gateway routing and failure summary template

Mount one HTTPS route per integration (for example /hooks/harbor/v1) so firewall rules stay narrow. Inside the handler, branch on verified type, enqueue prefetch work if the event matches your policy, and always build a failure summary template that downstream systems can parse without regex on prose.

{
  "source": "harbor-webhook",
  "event_type": "PUSH_ARTIFACT",
  "repository": "acme/base-images/nodejs",
  "digest": "sha256:…",
  "prefetch": { "ok": false, "failed_image": "reg.example/acme/base-images/nodejs:20", "exit_code": 1, "log_tail": "…last 400 chars…" },
  "host": "mac-ci-07",
  "duration_ms": 8420
}

POST this object only to hosts present in your allowlist configuration; reject unknown hostnames before DNS resolution when possible. Retry failures with two, four, and eight second sleeps and curl --max-time 25 (or equivalent) so a wedged summary endpoint does not block Harbor’s delivery thread—if Harbor’s timeout is aggressive, respond 202 Accepted quickly after validation and finish prefetch asynchronously when your design permits.

Common error FAQ (authentication, timeout, disk full)

Authentication: Harbor or registry returns 401 during prefetch

Robot password rotated but plist still exports the old value; hostname in docker pull does not match the token’s scope; or Keychain interaction blocked non-GUI sessions. Re-login headlessly, pin absolute paths in EnvironmentVariables, and test with a single docker pull under sudo -u automation.

Timeout: Harbor marks webhook failed even though pulls continue

Harbor waits for your HTTP response while layers download. Acknowledge fast, move pulls to a worker queue, or reduce work per event (single tag per delivery). Increase only what your security team allows—never disable TLS to “speed things up.”

Disk full: prefetch stops mid-batch

Shared runners accumulate dangling images. Enforce MIN_FREE_GB, run docker image prune -f on a schedule after green builds, and keep large test fixtures off the Docker root volume.

OpenClaw gateway “healthy” in curl but Harbor sees 502

Mismatch between internal listener address and proxy upstream, or SNI hostname differs from cert. Hit the public URL from an external jump host and compare TLS chains.

Summary and purchase-oriented next steps

You now have a minimal, reproducible spine: verify Harbor’s raw JSON, prefetch with explicit concurrency and disk gates, route through OpenClaw with a typed summary JSON, and keep outbound callbacks on a short allowlist with bounded retries. That combination cuts CI noise and makes Apple Silicon runners predictable without turning the Mac into a generic open relay.

If you need a host that stays awake, keeps stable TLS, and survives reboots with the same launchd labels, rent a remote Mac from MacPull—public entry points only: home, purchase, help, and the technical blog index (no login required to browse).

MacPull provides dedicated Mac Mini nodes so OpenClaw + Harbor prefetch gateways remain online, monitored, and easy to justify to security reviewers.

Run Harbor-driven prefetch on an always-on remote Mac

Use MacPull for stable TLS, persistent OpenClaw daemons, and predictable disk for docker layers. Browse home, purchase, help, and blog without signing in.