openclaw onboard --install-daemon там, где это описано в вашей сборке OpenClaw, и быстрые самопроверки шлюза (openclaw doctor, отдельные подкоманды статуса или curl к маршруту здоровья) — трактуйте их как справочные шаги из документации вашего дистрибутива, а не как жёсткую зависимость от одного внешнего URL. Дополнительно по теме: OpenClaw и Docker CI на удалённом Mac, безопасность шлюза OpenClaw и параллельные pull и диск в пуле сборок.
- Холодные слои в CI: агент начинает тянуть большой образ только после старта job, хотя Harbor уже принял манифест.
- Подделка или поломка проверки: секрет сравнивают после
JSON.parseили хэшируют пересобранный JSON — проверка «никогда не сходится». - Неконтролируемый исходящий трафик: сводки улетают на произвольные URL и не проходят корпоративный белый список.
Цели и предварительные условия
Цели. При релевантном событии Harbor узел на macOS должен: (1) аутентифицировать webhook; (2) построить одну или несколько полных ссылок на образ registry/project/repo:tag или по digest; (3) выполнить предзагрузку с ограниченным параллелизмом и защитой диска; (4) отправить короткий JSON о успехе или структурированном сбое только на фиксированный набор исходящих адресов, чтобы оператору не открывать UI Harbor.
Предварительные условия. Проект Harbor с правом настройки webhook; HTTPS-вход (TLS на границе) с проксированием на слушатель OpenClaw (часто 127.0.0.1 плюс Caddy, nginx или SSH-туннель); работающий Docker Desktop или Colima с неинтерактивным docker login для вашего hostname реестра; робот-аккаунт или scoped-токен в файле с правами 600. Зафиксируйте ветку Node 22 LTS или ту, что указана в примечаниях к вашей версии OpenClaw; установка Node у многих команд по-прежнему следует через официальный или поставщика curl-инсталлятор либо менеджер версий — главное, чтобы openclaw doctor не ругался на рассинхрон путей.
Поднимите шлюз через openclaw onboard и, если поддерживается вашим пакетом, openclaw onboard --install-daemon, чтобы обработчик переживал перезагрузку под launchd. Добавьте отдельный LaunchAgent с curl к документированному маршруту здоровья — так вы ловите расхождение TLS, DNS и upstream до того, как Harbor начнёт слать реальные события. Оформите белый список исходящих: адреса реестра для pull, один-два URL для сводки (внутренний CI, шлюз API) и, при необходимости, список доверенных CIDR для входящих вызовов Harbor.
Критерий готовности. Повтор одного сохранённого JSON из журнала доставок Harbor на стендовом Mac даёт те же digest в логах, предзагрузка укладывается в лимит времени, размер POST-сводки остаётся небольшим (порядка нескольких килобайт).
Поля событий Harbor Webhook и чеклист проверки подписи
Harbor шлёт JSON-конверт с полем type (например PUSH_ARTIFACT, PULL_ARTIFACT, DELETE_ARTIFACT), временем occur_at, operator и объектом event_data с метаданными репозитория и артефакта. Для предзагрузки обычно нужны имя репозитория, тег или digest и при необходимости digest артефакта, чтобы не дублировать pull. Сохраните эталонный payload из вашей минорной версии Harbor в репозитории фикстур — имена полей иногда меняются между релизами.
Чеклист проверки (вставьте в шаблон PR). (1) Прочитайте сырое тело HTTP до JSON.parse. (2) Сравните секрет Harbor константным временем — отдельный заголовок, bearer или значение из query, как настроено в проекте. (3) Отклоните неверный Content-Type, если вы не поддерживаете альтернативы. (4) По желанию ограничьте окно свежести по occur_at против replay. (5) После успеха логируйте только репозиторий и digest, не секрет. (6) Если позже добавите HMAC, хэшируйте те же сырые байты, которые подписал Harbor; пересборка JSON прокси «для красоты» ломает подпись чаще всего.
| Поле / аспект | Использование в обработчике OpenClaw |
|---|---|
type |
Ветвление: предзагрузка на push/retag; delete — только если вы явно чистите локальные образы. |
event_data.resources |
Сбор ссылок registry/project/repo:tag; при пустом теге — pull по digest. |
operator |
Аудит и опциональные лимиты по учётной записи автоматизации. |
| Целостность сырого тела | Сначала секрет/HMAC; при ошибке 401 без эха входных данных. |
https://ваш-реле.example/hooks/harbor?token=…; токен в URL не светите в скриншотах.Параметры скрипта предзагрузки на удалённом Mac (параллелизм, таймаут, квота диска)
После извлечения ссылок вызывайте небольшой shell-скрипт вместо десятков встроенных docker pull — проще менять лимиты без пересборки TypeScript. На общих Mac Mini в 2026 году разумны 2–4 параллельных pull, настенные часы на один pull от 6 до 15 минут в зависимости от слоёв и жёсткая остановка, если свободно меньше 15–25 ГБ на томе данных Docker.
Задайте переменные окружения в plist LaunchAgent: PREFETCH_CONCURRENCY, PULL_TIMEOUT_SEC, MIN_FREE_GB, опционально MAX_IMAGES_PER_EVENT, чтобы сбойный webhook не поставил в очередь сотни репозиториев. На macOS удобен xargs -P; учитывайте ограничения BSD xargs. После батча допишите одну строку JSON в файл, который шлюз читает для сводки.
#!/usr/bin/env bash
set -euo pipefail
: "${PREFETCH_CONCURRENCY:=3}"
: "${PULL_TIMEOUT_SEC:=600}"
: "${MIN_FREE_GB:=18}"
# macOS: df -g — блоки по 1 ГиБ (см. man df на раннере)
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
# При необходимости оберните каждый pull в gtimeout из GNU coreutils
Комментарий с gtimeout замените на ваш вариант: обёртка на Python, отдельный процесс с alarm или настройки клиента. Держите таймаут исходящей сводки отдельно от таймаута Harbor на webhook: для последнего важнее быстрый ответ.
Маршрутизация шлюза OpenClaw и шаблон сводки об ошибках
Заведите отдельный HTTPS-путь на интеграцию, например /hooks/harbor/v1, чтобы правила файрвола оставались узкими. Внутри обработчика после проверки type ставьте задачу предзагрузки в очередь и формируйте единый шаблон сводки при сбое, который downstream парсит без эвристик по тексту.
{
"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": "…последние 400 символов…" },
"host": "mac-ci-07",
"duration_ms": 8420
}
Отправляйте объект только на хосты из конфигурации белого списка; неизвестные имена отсекайте до резолва DNS, если архитектура позволяет. Повторы при сетевых ошибках и 5xx — с паузами 2 / 4 / 8 с и curl --max-time 25 (или эквивалент), чтобы зависший приёмник не держал поток Harbor. Если политика безопасности разрешает, отвечайте Harbor 202 Accepted сразу после валидации и выполняйте тяжёлый pull в фоне.
Типичные ошибки: FAQ (аутентификация, таймаут, заполнение диска)
Аутентификация: 401 при docker login или pull
Ротировали пароль робота, но plist всё ещё экспортирует старое значение; hostname в docker pull не совпадает с областью токена; сессия без GUI не может разблокировать Keychain. Проверьте логин вручную под тем же пользователем, задайте абсолютные пути в EnvironmentVariables, избегайте интерактивных запросов.
Таймаут: Harbor помечает webhook failed, хотя pull продолжается
Harbor ждёт HTTP-ответ, пока синхронно качаются слои. Укоротите синхронную часть до проверки и постановки в очередь; уменьшите объём работы на одно событие; не отключайте TLS «ради скорости».
Диск: предзагрузка обрывается на середине батча
На общих раннерах копятся «висячие» слои. Соблюдайте MIN_FREE_GB, планово запускайте docker image prune -f после зелёных сборок, не кладите крупные не-docker данные на корень данных Docker.
Локально curl показывает «здоров», Harbor видит 502
Расхождение SNI и сертификата, другой upstream у публичного URL и у loopback. Проверьте цепочку с внешнего jump-хоста тем же Host-заголовком.
Резюме и ориентация на покупку
Минимально воспроизводимая цепочка: проверка сырого JSON Harbor, предзагрузка с явными лимитами параллелизма и диска, маршрут OpenClaw с типизированной сводкой и исходящий трафик только по белому списку с ограниченными повторами. Так вы снижаете шум в CI и делаете Apple Silicon-раннер предсказуемым без превращения Mac в открытый ретранслятор.
Если нужен узел, который не засыпает, держит стабильный TLS и после перезагрузки поднимает те же метки launchd, рассмотрите аренду удалённого Mac у MacPull — публичные точки входа без обязательного входа: главная, покупка и конфигурации, центр помощи и каталог блога.
Итог: связка Harbor → OpenClaw на loopback с проверенным webhook, скриптом предзагрузки и белым списком исходящих хорошо проходит разбор у службы безопасности и снимает пики сети перед основными job.
Harbor и OpenClaw на постоянном удалённом Mac
Помощь и SSH, покупка узла, главная и подборка в блоге — без обязательной авторизации.