После установки OpenClaw на арендованный Mac mini M4 в Канаде следующий выбор не косметический: тянуть локальный Gateway на TCP 18789 через SSH-туннель или считать хост небольшим пограничным узлом и ходить напрямую на URL шлюза, который публикует провайдер? От этого зависят правила файрвола, то, как хранится gateway.remote.token, нужно ли в launchd экспортировать полный PATH, и что вы увидите в логах в три часа ночи по месту. Ниже — компактное руководство по решению, пошаговый runbook и таблица разбора для внутренней вики; базовый контур онбординга и демона см. в OpenClaw 2026: установка на удалённом Mac, развёртывание и устранение неполадок — openclaw onboard, демон Gateway и практическое планирование M4 среднего и высокого уровня в Канаде.
Когда выигрывает SSH-туннель, а когда — прямой Gateway
Локальный проброс порта по SSH (например ssh -L 18789:127.0.0.1:18789 user@canada-mac) оставляет Gateway привязанным к loopback на сервере, а на ноутбуке вы говорите с localhost:18789. Это удобно для соло-операторов, короткой отладки или политик, запрещающих выставлять порты агента на маршрутизируемый интерфейс. Цена — эксплуатация: туннель умирает вместе с SSH-сессией, переподключения могут гоняться с health check, и всё равно нужен стабильный SSH; командные runbook стоит явно описывать: кто держит сессию, какие keepalive и что делать при обрыве.
Прямой Gateway означает, что control plane или другой сервис вызывает endpoint на Mac без обёртки в SSH — обычно TLS перед 18789 или управляемый провайдером канал. Так проще масштабировать постоянные агенты, несколько клиентов и автоматизацию без интерактивной оболочки. Параллельно приходится думать как об инфраструктуре: ожидания по статическому egress, есть ли у машины физический нативный IP и модель «один IP на машину» для allow-list, и ротация токена, не зависящая от того, включён ли ноутбук разработчика.
launchd и нужны клиенты 7×24.
gateway.remote.token и где он должен лежать
В типичных профилях OpenClaw ключ gateway.remote.token (или эквивалент в онборднутой конфигурации) — общий секрет между удалёнными клиентами и Gateway. Его должен читать тот же пользовательский контекст, что и сам Gateway, — обычно учётная запись, завершившая openclaw onboard, — и токен не должен существовать только в интерактивном профиле shell. Храните его в конфиге, который грузит демон, или экспортируйте через словарь EnvironmentVariables в plist, если модель безопасности это допускает. После изменения проверьте из неинтерактивного зонда (короткий скрипт через launchctl), что переменная реально видна процессу; интерактивный SSH может полностью скрыть отсутствие env в plist.
Порт 18789: адрес привязки, файрвол и двойные слушатели
Большинство сборок по умолчанию держат слушатель Gateway на 127.0.0.1:18789, пока явно не расширите bind для удалённого доступа — это нормально для сценария «сначала туннель». При переходе на прямой доступ задокументируйте: loopback за обратным прокси или адрес в LAN; в любом случае после перезагрузки и обновлений выполняйте lsof -iTCP:18789 -sTCP:LISTEN. Если видите два процесса, остановите дубликаты через openclaw gateway stop, уберите лишние LaunchAgents и снова включите один plist, чтобы проверки здоровья не дёргались.
PATH и launchd: пошагово на headless Mac
Задачи launchd наследуют урезанное окружение; openclaw может не резолвиться так же, как в Terminal.app. На канадском хосте удобная последовательность:
1) В SSH-сессии под тем же пользователем, что и демон, выполните which openclaw и зафиксируйте абсолютный путь к CLI.
2) В plist LaunchAgent в ProgramArguments предпочитайте абсолютный путь к бинарнику, а не обёртку через shell.
3) Если нужен /bin/zsh -lc, зашейте префикс PATH в строку команды, например PATH=/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin;/opt/homebrew/bin/openclaw gateway start, чтобы Node и вспомогательные утилиты находились без ~/.zshrc.
4) Загрузите job: launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/your.openclaw.gateway.plist (домен подстройте под свой шаблон), затем launchctl print gui/$(id -u)/your.label и убедитесь, что задача в состоянии running.
5) Хвост логов по документации вашей сборки, один тестовый запрос клиента; сначала устраните PATH и токен, прежде чем открывать слушатель на публичный интерфейс.
ssh -N -L 18789:127.0.0.1:18789 -i ~/.ssh/id_ed25519 [email protected]
Разбор неисправностей: симптом → вероятная причина → первое исправление
| Симптом | Вероятная причина | Первое действие |
|---|---|---|
| В SSH-оболочке работает, после перезагрузки падает | PATH или токен только в интерактивном профиле | Абсолютные пути + EnvironmentVariables в plist; перезагрузить LaunchAgent |
| Туннель есть, клиент обрывается | Таймаут простоя SSH или нет TCP keepalive | ServerAliveInterval в SSH config или миграция на прямой Gateway |
| Прямой режим: 401 от Gateway | Расхождение gateway.remote.token или неверный заголовок |
Синхронизировать токен в клиенте и на сервере; ротировать при утечке |
EADDRINUSE на 18789 |
Дубликат gateway или лишний процесс Node | openclaw gateway stop; lsof; удалить дублирующий plist |
| Connection refused на публичном IP | Слушатель только на 127.0.0.1 | Обратный прокси или смена bind по документации провайдера; не открывать сырой порт вслепую |
Итог
Для стека OpenClaw 2026 в Канаде выбирайте SSH-туннель, когда нужен временный безопасный канал к 127.0.0.1:18789, и переходите на прямой Gateway с явными токенами и сетевой политикой, когда автоматизация должна переживать сон, перезагрузки и несколько вызывающих сторон. Подключайте gateway.remote.token в тот же контекст, что использует launchd, держите PATH предсказуемым и абсолютным, а таблицу выше оставьте первой страницей runbook дежурства.