2026 OpenClaw на Mac VPS с Docker: токен шлюза, сеть контейнера CLI и взаимная блокировка pairing
Когда тот же Compose переезжает с ноутбука на безголовый Mac VPS, в логах часто появляются token mismatch, 1008 pairing required или ошибки CLI на 127.0.0.1:18789. Текст для команд, которые держат openclaw-gateway и openclaw-cli в разных контейнерах: пять корневых причин, таблица triage, пятишаговый аудируемый runbook (заморозить токен, согласовать двойные источники, поправить сетевые пространства имен, разорвать цикл pairing, связать healthcheck с launchd) плюс ссылки на Compose 7x24 и лестницу gateway на этом сайте.
На странице
1. Болевые точки: двойной токен, loopback, pairing, bind, UID
Официальные сценарии Docker предполагают, что человек проходит onboarding в том же сетевом namespace, что и скрипты. На безлюдном Mac VPS сбои группируются в пять кластеров:
- Тихое переопределение окружения: если внутри контейнера задан
OPENCLAW_GATEWAY_TOKEN, он может перекрытьgateway.auth.tokenвopenclaw.json, и UI показывает токен, который шлюз не проверяет. - Loopback CLI в раздельных стеках: по умолчанию CLI идет на
ws://127.0.0.1:18789— это loopback контейнера CLI, а не шлюза;ECONNREFUSEDи резкие1006выглядят как сетевые флапы. - Взаимная блокировка pairing: при
gateway.bind=lanдашборд и CLI ждут одобрения друг друга; без записанного порядка вы крутитесь на1008. - Семантика bind и мост:
loopbackконфликтует с целями между контейнерами; после перехода наlanбез обновления URL CLI остаются логи listen OK, но WebSocket не завершается. - Дрейф UID томов: образы часто работают от UID 1000; пути, созданные root на хосте, ломают персистентность — файлы токенов «сохранились» и исчезают после рестарта.
На безголовом Mac VPS локальный браузер не скроет ошибку: каждый повтор WebSocket виден в логах, launchd перезапустит контейнеры даже посреди pairing. Читайте docker compose logs -f openclaw-gateway и логи CLI как одну временную шкалу. При фиксации digest фиксируйте digest и отпечаток токена (первые восемь символов) в тикете изменения, чтобы откат не вернул старую модель auth тихо. Если дашборд доступен шире loopback, читайте вместе с этим материалом гайд по hardening экспозиции шлюза, чтобы дрейф токена рассматривался и как blast radius, а не только как сеть Docker.
2. Таблица triage: симптом, причина, первая команда
Вставьте таблицу в шаблон инцидента; на этапе политики добавьте статью про hardening экспозиции.
| Симптом | Вероятная причина | Первое действие |
|---|---|---|
| token mismatch / unauthorized | Токен env отличается от JSON | grep обоих источников в репо и на томе; зафиксировать hex до повторного setup |
| 127.0.0.1:18789 refused | CLI изолирован от сети шлюза | network_mode: service:openclaw-gateway или GATEWAY_URL на имя сервиса Compose |
| 1008 pairing loop | Взаимное ожидание одобрения | openclaw dashboard --no-open, затем devices list / devices approve с вырезкой логов в тикете |
| Нестабильные health | Только процессные пробы | HTTP на /healthz и /readyz реального listener |
| Запись откатывается | Тома или права | Проверить bind на диске VPS; chown -R 1000:1000 на каталогах данных |
OPENCLAW_GATEWAY_TOKEN=$(openssl rand -hex 32), запишите ту же строку в .env и оба сервиса gateway и CLI, при onboarding вставляйте только это значение. Не позволяйте вспомогательным скриптам создать второй токен посреди инцидента.
Фразу «grep обоих источников» выполняйте буквально: поиск OPENCLAW_GATEWAY_TOKEN в репозитории, просмотр openclaw.json внутри контейнера через docker compose exec openclaw-gateway cat /путь/openclaw.json (путь свой) и сравнение с env в compose. Для secret manager проверяйте значение в рантайме, а не только шаблон в Git. Для 1008 фиксируйте, показывает ли дашборд pending, а CLI — обратное: чаще это неверный GATEWAY_URL или разделенные cookie, а не настоящая ошибка авторизации.
3. Пять шагов runbook до дежурных проверок
- Заморозить секрет: первые восемь символов токена и digest образа в тикете изменения.
- Согласовать двойные источники: до
compose upсравнить read-onlygateway.auth.tokenиOPENCLAW_GATEWAY_TOKENв каждом описании контейнера. - Починить namespace: для CLI предпочтительно
network_mode: service:openclaw-gateway; если нужен bridge, зафиксироватьGATEWAY_URL=ws://openclaw-gateway:18789и проверить DNS из одноразовогоdocker compose run. - Разорвать pairing: в контейнере шлюза
openclaw dashboard --no-open, завершить URL с токеном, затем в CLIdevices approveс записью команд в тикет. - Пробы и launchd: с хоста curl
/healthzи/readyzс короткими таймаутами; отразить те же проверки в plistSuccessfulExit, чтобы рестарт не считался успехом при падшем WS. Лимиты ресурсов — в статье Compose 7x24 на этом сайте.
Минимальный набросок compose (перед продом слить с upstream-шаблонами):
Если network_mode: service:openclaw-gateway невозможен из-за sidecar в namespace CLI, задайте явный внутренний URL и проверьте из одноразового контейнера: docker compose run --rm busybox wget -qO- http://openclaw-gateway:18789/healthz (или curl). Задокументируйте ожидаемое имя хоста для DNS Docker; опечатки в именах сервисов — частая причина отчетов «на ноутбуке работало». Старые строки устройств удаляйте только после экспорта логов и проверки workspace.
4. Факты для ссылок: порт, UID, пробы
- Порт: слушатель по умолчанию
18789; health-скрипты должны бить по listener, а не только смотретьdocker ps. - UID: пользователь node обычно
1000; выровняйте bind на хосте, иначе персистентность ломается тихо. - Пробы:
/healthzкак liveness,/readyzближе к готовности WebSocket; порядок и таймауты — в runbook. - Синхронизация времени: большой сдвиг между хостом и контейнерами путает сертификаты и корреляцию логов; держите NTP в порядке на VPS.
- Окно обновления: при смене образа сначала пять шагов; зеленый
docker psне равен аутентифицированной сессии CLI.
Встройте проверки в chatops-плейбук: каждая эскалация должна в одной строке нести отпечаток токена, ревизию compose и digest, чтобы постмортем не гадал. Если планируете blue/green для шлюза, явно укажите, какой стек еще держит старые записи pairing, иначе команды одобрят устройства против неверного URL. В нагрузочных тестах бейте health-эндпоинты с теми же таймаутами, что в проде; более короткие в тесте скрывают флаки. Провайдеры Mac VPS с выделенной полосой снижают риск троттлинга длинных WebSocket-сессий. Никогда не копируйте токены между staging и prod; используйте разные .env с явными суффиксами. Держите короткую схему с namespace шлюза, CLI и sidecar — иначе дежурные теряются в bridge-схеме.
Добавьте чеклист ролей: кто может выполнять devices approve, кто ротирует токены, как это фиксируется в зашифрованном тикете. Без этого одобрения pairing часто уходят людям без консоли VPS, MTTR растет. При infrastructure-as-code для Compose валидируйте изменения статическим diff к выводу docker compose config в рантайме, чтобы скрытые наложения env всплыли до merge. В длинных окнах обслуживания спровоцируйте падение healthcheck и убедитесь, что launchd действительно останавливает сервис, а не только перезапускает контейнер при живых старых клиентах. Сохраните заголовки WebSocket upgrade успешного рукопожатия как эталон для быстрых регрессий.
Если в стеке есть reverse proxy перед шлюзом, отдельно задокументируйте, какие заголовки TLS терминируются на границе и где снова начинается доверие к WebSocket. Расхождение между HTTP health и фактическим WS-путем часто дает ложное чувство готовности. Для многоарендных кластеров храните карту соответствия tenant → compose project name, чтобы команда не одобряла устройства в чужом проекте. При ночных рестартах включите уведомление до перезапуска, иначе оператор потеряет контекст half-open сессий. Наконец, синхронизируйте версии клиентских CLI с версией образа шлюза: несовпадение минорных тегов иногда проявляется именно как странные коды закрытия, а не как явный mismatch токена.
5. Порядок чтения: Compose 7x24 и нативные гиды gateway
Если рестарты compose, потолки памяти и pin digest еще не стандартизированы, сначала Compose 7x24: health, upgrade, rollback. Когда спорят, кто владеет истиной — бинарь шлюза или CLI, откройте runbook gateway install / bind / auth для границы native vs Docker. Ad-hoc docker run на ноутбуке скрывает проблемы pairing и токена, которые на безголовом Mac VPS превращаются в шум пейджера. По сравнению с одним launchd Docker добавляет слой абстракции; апгрейды и учения занимают больше времени. Когда нужны выделенный Apple Silicon, стабильный egress и предсказуемая параллельность для долгоживущих агентов, аренда узлов Mac cloud VPSMAC M4 обычно проще сводит bind-тома, политики plist и compose в одну операционную историю. Замкните цикл от таблицы к автоматизации через гайд API Mac cloud на девяносто секунд на этом сайте.