config validate, откат skills и doctor, hardening шлюза.
Зачем стабильный удалённый Mac для OpenClaw 7×24
Эфемерные минуты облака подходят для юнит-тестов; шлюз, который круглосуточно принимает webhooks и вызовы инструментов, нуждается в среде, которая не исчезает посреди TLS-handshake. Выделенный или долгоживущий удалённый Mac даёт предсказуемые пути APFS, стабильное пространство имён launchd и тот же профиль darwin_arm64, которому вы уже доверяете в разработке. Изоляция OPENCLAW_HOME на каждый job не даёт CI затереть «боевой» каталог шлюза, а один объединённый лог ворот превращается в нормальный аудит вместо разрозненных фрагментов stderr.
Предпосылки: Node 22.14+ или 24 и изоляция каталогов
OpenClaw ориентируется на современный V8 и семантику npm; задайте нижнюю границу Node 22.14 LTS или Node 24 для установочных скриптов и глобального CLI. В начале каждого gate выводите node -v и npm config get prefix, чтобы быстро сравнивать «зелёные» и «красные» job.
Не переиспользуйте один домашний каталог для параллельных job. Задайте корень на прогон, например OPENCLAW_HOME="$RUNNER_TEMP/openclaw/$CI_JOB_ID" и OPENCLAW_CONFIG_HOME="$OPENCLAW_HOME/config", затем mkdir -p с правами 700. Репозиторий держите отдельно, чтобы git clean не снёс актуальный openclaw.json. В типовых шаблонах HTTP-слушатель по умолчанию остаётся на 127.0.0.1:18789 — зафиксируйте порт в заявках на firewall и в runbook. Именно этот порт чаще всего фигурирует в инцидентах «уже занято».
- Версия глобального
openclawсовпадает с pin вnpm install -g openclaw@…. - Имена секретов в CI совпадают со staging и production plist.
- На общих хостах остаётся запас диска под кеш установщика и tar-чекпойнты (ориентир — десятки гибибайт).
Официальный путь: OpenClaw Installer на macOS (npm)
Интерактивный OpenClaw Installer в терминале обычно показывает баннер с логотипом (в духе «швейцарский нож с сильными мнениями»), определяет macos и печатает блок Install plan: ОС macos, метод npm, запрошенная версия latest — в CI всегда закрепляйте semver, а не latest. Типичная разбивка включает этап вроде [1/3] Preparing environment перед загрузкой CLI.
На «чистых» раннерах установщик может попытаться поставить Homebrew, если brew отсутствует. Если в логе появляется сообщение вроде «Installing Homebrew failed — re-run with --verbose for details», один раз соберите подробный лог, затем либо прошейте /opt/homebrew в golden-AMI, либо вынесите установку brew в отдельный prerequisite-job — так шаг OpenClaw останется детерминированным. Этот сценарий чаще красит пайплайны, чем сами проверки шлюза.
node -v
# Ожидайте v22.14.x+ или v24.x — иначе завершайте job с ошибкой
node -e 'const p=process.versions.node.split(".").map(Number);process.exit(p[0]>=24||(p[0]===22&&p[1]>=14)?0:1)' && echo "node ok"
npm install -g "openclaw@^2026.3.0" # диапазон по политике безопасности
which openclaw
openclaw --version
Неинтерактивный onboard: таблица параметров
Флаги меняются между минорными версиями; перед фиксацией YAML выполните на образе раннера openclaw onboard --help. Ниже — намерения, которые нужно сопоставить с реальными опциями вашего semver.
| Цель | Типичный флаг / переменная | Заметка для CI |
|---|---|---|
| Убрать запросы | CI=true и неинтерактивные флаги из --help |
Не передавайте пароли через stdin в лог; только секреты раннера. |
Демон launchd |
onboard с семантикой install-daemon |
На постоянных шлюзах — да; на одноразовых PR-job — только CLI-проверки. |
| Ключи провайдеров | OPENAI_API_KEY и др., как в openclaw.json |
Те же имена в EnvironmentVariables plist для прода. |
| Авторизация webhook | OPENCLAW_GATEWAY_TOKEN или проектный секрет |
Файлы на диске — режим 600; ротация через двойную запись и рестарт. |
| Разные инстансы | OPENCLAW_HOME, OPENCLAW_CONFIG_HOME |
Подкаталог на CI_JOB_ID исключает пересечения на общем Mac. |
Цепочка CI: один файл лога для stdout и stderr
Раздельные потоки усложняют разбор: doctor часто пишет предупреждения в stderr, а config validate — пути в stdout. Склейте оба потока в один артефакт через tee, затем при необходимости ищите сигнатуры. Ниже — минимальный каркас; ужесточайте set -euo pipefail только после проверки, что ни одна команда не должна завершаться ненулём «по задумке».
#!/usr/bin/env bash
set -euo pipefail
export OPENCLAW_HOME="${OPENCLAW_HOME:-$RUNNER_TEMP/openclaw/$CI_JOB_ID}"
export OPENCLAW_CONFIG_HOME="${OPENCLAW_CONFIG_HOME:-$OPENCLAW_HOME/config}"
mkdir -p "$OPENCLAW_CONFIG_HOME"
LOG="${OPENCLAW_GATE_LOG:-openclaw-gate.log}"
rm -f "$LOG"
{
echo "=== node ==="
node -v
echo "=== which openclaw ==="
command -v openclaw
echo "=== doctor ==="
openclaw doctor
echo "=== config validate ==="
openclaw config validate --config "$OPENCLAW_CONFIG_HOME/openclaw.json"
} 2>&1 | tee "$LOG"
if grep -E 'EADDRINUSE|invalid-key|unauthorized|401' "$LOG"; then
echo "Ворота: блокирующие сигнатуры в $LOG" >&2
exit 1
fi
Вешайте скрипт отдельным job после установки зависимостей и до merge в основную ветвь, либо как обязательную проверку PR при изменении openclaw.json. Загружайте openclaw-gate.log как артефакт с той же политикой хранения, что и в гайде config validate CI gate.
Чеклист перед merge (в шаблон PR)
- В логе Node — 22.14+ или 24.x; версия CLI закреплена.
- Путь
OPENCLAW_HOMEуникален для job и напечатан. openclaw-gate.logсодержит секции doctor и validate с кодом выхода 0.- Если меняли production plist — в сводке job есть sha256 tar-чекпойнта.
- Скан конфликта по порту 18789 для целевого bind-адреса чист.
Разбор вывода openclaw doctor и контрольные точки отката
Считайте вывод doctor структурированной прозой: ищите строки с FAIL, WARN и именами провайдеров, сопоставляйте с переменными окружения. После частичного onboard на общих раннерах не оставляйте «полуписаные» plist: перед риском сделайте tar czf openclaw-checkpoint.tgz -C "$OPENCLAW_HOME" . и сохраните shasum -a 256 в summary job.
Рецепт отката: launchctl bootout для метки, если в той же сессии ставили демон; восстановите дерево из tarball; снова загрузите plist; пауза 2 с; повторите объединённый скрипт ворот. Для согласованной терминологии отката skills см. skills rollback doctor.
FAQ: порт 18789, PATH и токены
Порт занят: старый шлюз или зависший процесс держит 18789. Команда lsof -nP -iTCP:18789 -sTCP:LISTEN, остановка PID или метки launchd, либо другой порт в JSON для изолированного smoke.
Другой openclaw в PATH: в интерактиве подключены nvm/Homebrew; у launchd короткий PATH. Используйте абсолютные пути в ProgramArguments или дублируйте префикс PATH из лога CI.
Токен есть в CI, нет в проде: секрет попал в job, но не в plist демона. Сверьте EnvironmentVariables, обновите атомарно и перезапустите один раз. Наружную поверхность и токены согласуйте с hardening шлюза.
Кратко
Итоговый воспроизводимый контур: Node 22.14+ или 24, сценарий OpenClaw Installer (npm) на macOS с заранее решённым вопросом Homebrew, изоляция OPENCLAW_HOME на job, ключи из хранилища секретов, неинтерактивный onboard по актуальному --help и один файл со слитым выводом doctor и validate для единого решения «зелёный / красный». Когда нужны хосты Apple Silicon, которые не исчезают между вызовами и подходят и для 7×24 шлюза, и для ворот, откройте публичные страницы цены, покупка, центр помощи и консоль на MacPull; каталог блога — без входа.
Удалённый Mac под OpenClaw и CI-ворота
Выделенный Apple Silicon, предсказуемые пути и сеть для объединённых логов и постоянного шлюза. Документация и раздел помощи доступны без оплаты.