Когда вы сознательно оставляете единственный OpenClaw Gateway на арендованном Mac mini M4 в Канаде, а команда сидит в Европе, Азии и по обе стороны Тихого океана, вопрос перестаёт быть «какой красивый URL у Dashboard». Он становится схемой доверия: кто имеет право дергать 127.0.0.1:18789, как macOS-клиенты доходят до веб-интерфейса без лишнего публичного bind, и где лежит gateway.remote.token, чтобы полуночный перезапуск не ломал автоматизацию. Ниже — связный туториал по трём типовым каналам (SSH, Tailnet, осознанный публичный фронт), две таблицы для вики и FAQ; базовый онбординг Gateway и сценарии 7×24 см. в OpenClaw 2026 на удалённом Mac: скрипты установки и onboard, Gateway 18789, Token, LaunchDaemon, таблица логов и сценарии 7×24 на M4 в Канаде, а прод-нагрузку на диске и «дрожание» каналов — в OpenClaw 2026: готовность к продакшену на удалённом Mac M4 в Канаде — планирование Node и workspace на диске, продление авторизации Channels, удалённое «дрожание» Gateway и таблица разбора ошибок (HowTo + FAQ).
Зачем вообще «только Канада» и что это ломает в головах у распределённой команды
Единый регион шлюза упрощает ответы на аудит: один набор часовых поясов для смен дежурных, один контур egress для allow-list партнёров, одна юрисдикция для логов по умолчанию. Цена — латентность и зависимость от ночных окон, когда Азия уже вечером, а Торонто ещё пьёт кофе. Поэтому архитектуру клиентов стоит проектировать так, чтобы не требовать постоянного интерактивного SSH от каждого разработчика: либо стабильный overlay (Tailnet), либо reverse-proxy с TLS, либо явный jump-host с короткоживущими сессиями.
На практике «только Канада» часто означает: ни одного второго Gateway в другом регионе под тем же workspace, иначе вы получите гонку webhook, двойные подписки и непредсказуемый порядок side-effect. Зафиксируйте в runbook, какой хост считается истиной для 18789, и как вы откатываетесь, если машина ушла в обслуживание.
Канал A: macOS Remote over SSH — как «приземлить» Dashboard и 18789 на ноутбук
Классический путь для соло-инженера: на канадском Mac Gateway слушает 127.0.0.1:18789, а вы поднимаете локальный порт на своём MacBook через SSH. Тогда браузер на клиенте открывает http://127.0.0.1:18789 (или соседний порт, если 18789 занят) и попадает на удалённый loopback через туннель. Плюсы: не нужно открывать TCP 18789 в интернет, проще объяснить ИБ. Минусы: туннель живёт, пока живёт ssh; при обрыве трансокеанского канала агенты «отваливаются» до ручного переподключения, если нет автоматизации.
ssh -N -L 18789:127.0.0.1:18789 -o ServerAliveInterval=30 -i ~/.ssh/id_ed25519 ops@canada-mac.example
Если Dashboard отдаётся отдельным HTTP-портом (условно 3000), добавьте второй -L или используйте ProxyJump в корпоративной схеме. Главное — задокументировать, какой именно localhost ожидает ваш фронтенд: несовпадение схемы http/https и заголовка Host часто ломает cookie и WebSocket после перехода с прямого IP на туннель.
Для команд из Азии и Европы полезно заранее описать роль jump-хоста: кто имеет право открывать интерактивный SSH, нужен ли Match User в sshd_config и как вы отключаете port-forwarding для гостевых аккаунтов. Если в цепочке участвует корпоративный VPN, убедитесь, что split-tunnel не перехватывает маршрут к канадскому IP случайно — иначе туннель будет подниматься, но latency станет непредсказуемой. Наконец, храните в репозитории runbook не «скриншот команды», а параметризованный пример с плейсхолдерами для имени пользователя, ключа и FQDN, чтобы новый инженер не угадывал порт по памяти.
Канал B: Tailnet (Tailscale) — когда команде нужен «постоянный виртуальный LAN» до Канады
Tailnet даёт маршрутизируемые имена вида canada-mac.tailnet-name.ts.net без публичного открытия портов на домашнем роутере. Для OpenClaw это обычно означает: Gateway по-прежнему loopback-first на самой машине, а доступ снаружи идёт через tailscale-демон и ACL. Настройте ACL так, чтобы только роли dev-gateway-clients могли достучаться до нужных портов; не смешивайте в одну группу людей с правом SSH и людей, которым достаточно read-only Dashboard.
С точки зрения macOS-клиента вы выигрываете тем, что не зависите от ручного ssh в терминале для повседневной работы: tailscaled держит ключи, переподключение происходит на уровне демона. Но вы всё равно должны явно решить, публикуете ли вы 18789 только внутри tailnet или ещё и на физическом LAN — смешение без документации приводит к «у меня работает, у коллеги нет».
На стороне Канады заведите отдельный тег машины для production-gateway и запретите в ACL случайные подсети домашних роутеров. Для аудита сохраняйте выгрузку tailnet policy рядом с changelog OpenClaw: когда инженер добавляет правило «разрешить всем dev», это почти всегда ударит по принципу единственного шлюза. Если в tailnet есть subnet-router, проверьте, не дублирует ли он маршрут, который уже отдаёт ваш облачный провайдер, иначе получите асимметричную маршрутизацию и «плавающие» таймауты именно у удалённых клиентов.
Dashboard и 18789: как «сшить» UI, API и health-check
Типичная ошибка при трансокеанской схеме — смешать URL, по которому браузер грузит JS, с URL, по которому тот же JS дергает Gateway. Если Dashboard собран с жёстко прошитым https://public.example:18789, а вы пришли через SSH на http://127.0.0.1:18789, часть запросов уйдёт мимо туннеля и вы получите CORS или пустой экран. Исправление: единый базовый URL через переменные окружения фронта, либо reverse-proxy, который проксирует и статику, и API под одним хостом.
Порт 18789 в большинстве инсталляций остаётся «внутренним сервисным»; проверяйте после обновлений командой вроде lsof -iTCP:18789 -sTCP:LISTEN, что слушатель один и привязан к ожидаемому адресу. Два процесса на одном порту — почти всегда следствие того, что кто-то вручную запустил openclaw gateway start поверх уже работающего LaunchAgent.
Для смешанных команд (дизайн смотрит Dashboard, бэкенд бьёт API) выпишите матрицу «кто какой базовый URL видит». Частый паттерн — reverse-proxy на 443, который проксирует /api на loopback 18789, а статику отдаёт CDN; тогда macOS-клиентам не нужно помнить порт вообще. Если вы оставляете прямой 18789 только внутри tailnet, зафиксируйте это в onboarding-письме, иначе новичок из другого часового пояса потратит час на поиск «почему браузер пишет connection refused», хотя проблема всего лишь в ACL.
Токены gateway.remote.token для команды через океан
Токен — не «пароль от Wi‑Fi», а долгоживущий секрет автоматизации. Для распределённой команды заведите: (1) где хранится эталон (секрет-хранилище, а не Slack), (2) кто имеет право ротации, (3) как клиенты узнают о смене без утечки в git. На канадском хосте токен должен читаться тем же пользователем, что и процесс Gateway под launchd, иначе ночной рестарт превратится в цепочку 401.
Для людей в Азии удобно иметь короткоживущий персональный токен или SSO-слой поверх Gateway, если ваша сборка это поддерживает; не шарьте один и тот же секрет между CI и ноутбуками без журнала выдачи. После инцидента меняйте токен до разбора логов, если есть риск утечки из артефакта пайплайна.
Добавьте в регламент пункт о локализации времени ротации: менять секрет в «окно Канады», когда дежурный в Торонто может сразу проверить LaunchAgent и логи, а не в пик азиатской ночи, когда откат затягивается. Для артефактов GitHub Actions или GitLab CI используйте environment secrets с required reviewers, чтобы случайный форк не прочитал значение. Если токен когда-то попал в общий чат, считайте его скомпрометированным навсегда, даже после удаления сообщения: боты архивируют быстрее, чем вы успеваете нажать Delete.
Политика loopback-first и когда её нарушают осознанно
Loopback-first означает: Gateway по умолчанию слушает только 127.0.0.1, а весь внешний доступ — через SSH, Tailnet или reverse-proxy с TLS-терминацией. Это снижает поверхность атаки и упрощает объяснение ИБ, почему в интернет «не торчит сырой Node-порт». Нарушать политику стоит только когда у вас есть явный L7-балансировщик, WAF и мониторинг SYN-штормов — и то лучше публиковать не «голый 18789», а HTTPS на 443 с маршрутизацией на loopback за nginx/caddy.
Если вы используете split DNS (внутри tailnet одно имя, снаружи другое), зафиксируйте, какой резолвинг видит LaunchAgent: он не читает ваши эксперименты с /etc/hosts на ноутбуке разработчика.
LaunchAgent на headless Mac: plist, PATH и контрольный список
launchd не загружает интерактивный ~/.zshrc; пишите абсолютные пути к openclaw и Node, либо задавайте EnvironmentVariables в plist. Для пользовательского LaunchAgent путь обычно ~/Library/LaunchAgents/com.example.openclaw.gateway.plist; после правок — launchctl bootout/bootstrap в GUI-домене того же uid.
UID=$(id -u)
launchctl print "gui/${UID}/com.example.openclaw.gateway" | sed -n '1,40p'
Логи пишите в известный файл в ~/Library/Logs и ротируйте их; при трансокеанических расследованиях важно иметь одну временную шкалу (UTC) и отметку, какой канал (SSH/Tailnet/публичный) использовал клиент. План перезагрузки: сначала убедиться, что plist Loaded, затем удалённый smoke-test с европейского jump-хоста, затем открыть доступ широкой команде.
Отдельно зафиксируйте, кто владеет файлом plist в git: если каждый дежурный правит локально, вы потеряете воспроизводимость. Храните шаблон в репозитории инфраструктуры и деплойте его скриптом с подстановкой HOME и uid, затем делайте plutil -lint в CI. Для headless Mac без GUI-сессии убедитесь, что выбранный LaunchAgent действительно загружается в gui/uid, а не остаётся «висячим» в launchctl list со статусом, который никто не мониторит.
Сравнительная таблица: SSH, Tailnet и публичный L7-фронт
| Критерий | SSH port-forward | Tailnet | Публичный HTTPS-фронт |
|---|---|---|---|
| Стабильность для 7×24 | Низкая без автопереподключения | Высокая при корректных ACL | Высокая при нормальном LB |
| Онбординг нового macOS-клиента | Быстро, но ручной ssh |
Один раз tailscale login | Только браузер/HTTPS-клиент |
| Поверхность атаки | Зависит от SSH-hardening | Зависит от ACL и ключей | Нужны TLS, WAF, rate-limit |
| Совместимость с loopback-first | Отличная | Отличная при split routing | Требует reverse-proxy |
Таблица разбора: симптом → причина → действие
| Симптом | Вероятная причина | Первое действие |
|---|---|---|
Dashboard грузится, API на 18789 падает |
Разные базовые URL / mixed content | Выровнять схему и Host; один reverse-proxy |
| Утром 401 только у азиатской команды | Токен ротировали, кэш клиента старый | Синхронизировать секреты; очистить Keychain/конфиги |
| После рестарта Mac Gateway не поднимается | PATH в plist урезан | Абсолютные пути; launchctl print |
| Tailnet «есть пинг», UI недоступен | ACL режет TCP к порту | Проверить tailnet policy и теги машин |
EADDRINUSE на 18789 |
Двойной запуск | lsof; оставить один LaunchAgent |
| SSH-туннель рвётся каждые 20 минут | Idle timeout посредника | ServerAliveInterval или миграция на Tailnet |
FAQ
Нужен ли публичный IP для Dashboard, если Gateway на loopback?
Не обязательно, если весь доступ идёт через SSH, Tailnet или HTTPS-прокси. Публичный IP нужен только для выбранной модели egress или если партнёр требует прямого allow-list на маршрутизируемый адрес.
Можно ли одновременно держать SSH-туннель и Tailnet к одному хосту?
Технически да, но операционно это создаёт двойные пути в инцидентах. Выберите основной канал в runbook и второй оставьте как аварийный.
Как объяснить ИБ, что порт 18789 не «торчит в интернет»?
Покажите lsof с bind на 127.0.0.1, схему reverse-proxy и список ACL Tailnet. Добавьте схему потоков из таблицы выше.
Где хранить gateway.remote.token для CI в другом регионе?
В секрет-хранилище провайдера CI с инъекцией в рантайм, не в репозиторий. Ротация — через ту же систему, что и для людей, с отдельным сервисным аккаунтом.
LaunchAgent vs LaunchDaemon для Gateway?
Для интерактивного пользователя, под которым идёт openclaw onboard, чаще выбирают LaunchAgent в GUI-домене. LaunchDaemon уместен для системных ролей, но усложняет доступ к keychain и графическим сессиям — уточните по вашей сборке.
Что делать, если WebSocket из Азии обрывается чаще, чем HTTP?
Проверьте таймауты на промежуточных прокси, поддержку upgrade и MTU. Часто помогает единый L7-хост с корректными заголовками Upgrade и отключённым буферизующим middleware.
Нужно ли синхронизировать системное время на канадском Mac?
Да: смещённые часы ломают OAuth/TLS-журналы и усложняют корреляцию логов с клиентами через океан. Включите NTP и мониторинг дрейфа.
Итог
Схема «OpenClaw только в Канаде на M4» работает, если вы явно выбрали один основной канал до 18789 и Dashboard, закрепили loopback-first или осознанный публичный фронт, а токены и plist для LaunchAgent отражают реальность launchd, а не вашу интерактивную оболочку. Две таблицы выше можно вставить в внутреннюю вики как чек-лист смены дежурного; FAQ закрывает типичные вопросы ИБ и сетевиков при трансокеанском созвоне.