П/ВИН

Orca на сервере: один рантайм для ПК и телефона

·8 мин чтения

Представь: у тебя есть мощный инструмент для работы с агентами — Orca. Ты запускаешь его на ноутбуке, добавляешь проекты, настраиваешь агентов. Потом берёшь телефон — и видишь пустой экран. Переходишь на второй ПК — снова с нуля. Знакомо? Именно эту проблему мы решали: сделать так, чтобы один серверный рантайм Orca был постоянно доступен с любого устройства, а все проекты и агенты были синхронизированы автоматически.

Контекст: что такое Orca и зачем её держать на сервере

Orca — это среда для запуска AI-агентов (Claude, Codex и других) с терминалом, файловым менеджером и управлением проектами. По умолчанию она запускается локально с GUI. Но у неё есть режим orca serve — headless-запуск без графического интерфейса, который держит WebSocket-сервер на порту 6768. К этому серверу могут подключаться клиенты: десктопное приложение, мобильное приложение, CLI.

Идея простая: сервер работает 24/7, хранит все состояния, проекты и ключи спаривания. Ты открываешь Orca на телефоне или ПК — и сразу видишь всё то же самое, что и на другом устройстве. Никакой синхронизации вручную, никакого «а где мои проекты».

Но между идеей и рабочей схемой — несколько нетривиальных шагов.

Проблема первая: как безопасно открыть доступ к серверу

Первый вопрос, который встаёт сразу: как подключиться к серверу с телефона и ПК? Варианты:

  1. Открыть порты в интернет — быстро, но небезопасно. WebSocket без TLS на публичном IP — плохая идея.
  2. Tailscale — создаёт приватную mesh-сеть между устройствами, порты не торчат наружу.
  3. Свой VPN — если он уже есть, зачем городить ещё один?

В нашем случае на сервере уже работал WireGuard (wg0), и у нас был собственный VPN-сервис. Tailscale оказался лишним. Мы настроили Orca слушать на VPN-адресе сервера, закрыли публичный доступ к портам 6768 и 6769, и всё — доступ только через VPN.

# Проверка интерфейса WireGuard
ip addr show wg0
# Адрес сервера в VPN-сети: 10.8.0.1
 
# Закрываем публичный доступ к портам Orca
sudo ufw deny 6768
sudo ufw deny 6769
 
# Разрешаем только с VPN-адресов
sudo ufw allow from 10.8.0.0/24 to any port 6768
sudo ufw allow from 10.8.0.0/24 to any port 6769

После этого Orca доступна только тем, кто подключён к VPN. Это и есть правильная модель безопасности для инструментов разработки.

Проблема вторая: два рантайма вместо одного

Вот где началось самое интересное. Изначально на сервере работали два независимых процесса Orca:

  • orca-serve.service на порту 6768 — «десктопный» рантайм
  • orca-mobile-serve.service на порту 6769 — «мобильный» рантайм

Каждый из них имел свой отдельный каталог данных:

/home/deploy/.config/orca          # 50 проектов, агенты, воркспейсы
/home/deploy/.config-orca-mobile/orca  # пусто

Результат: добавляешь 50 проектов с ПК — телефон их не видит, потому что телефон подключён к другому рантайму с пустой базой. Классическая ловушка «два сервиса, одна иллюзия синхронизации».

Решение: оставить один рантайм на порту 6768, к которому подключаются все устройства — и ПК, и телефон. Мобильный сервис на 6769 остановили и отключили.

# Останавливаем и отключаем мобильный рантайм
sudo systemctl stop orca-mobile-serve
sudo systemctl disable orca-mobile-serve
 
# Проверяем, что основной рантайм работает
sudo systemctl status orca-serve
# Active: active (running)

После этого все устройства спариваются с одним рантаймом, видят одни и те же проекты, одних и тех же агентов.

Обновление Orca до актуальной версии

Паралельно обновили Orca на сервере:

Было:  1.4.148
Стало: 1.4.152

Обновление важно не только ради новых фич. В свежих версиях Orca активно идут перформанс-правки — например, в 1.4.160-rc.2 появились:

  • perf(editor): сокращение работы на каждое нажатие клавиши в rich-markdown редакторе
  • perf(terminal): сканирование выходных фреймов по code unit вместо code point
  • perf(git): параллельное чтение при getBranchCompare
  • fix(mobile): доставка уведомлений, пропущенных при переподключении

Это напрямую влияет на отзывчивость интерфейса — особенно при работе через сеть.

Systemd: правильный автозапуск

Чтобы Orca поднималась автоматически после перезагрузки сервера, настроили systemd-юниты. Ключевые параметры:

[Unit]
Description=Orca Runtime Server
After=network.target
Wants=network-online.target
 
[Service]
Type=simple
User=deploy
ExecStart=/usr/local/bin/orca serve
Restart=on-failure
RestartSec=5
Environment=HOME=/home/deploy
 
[Install]
WantedBy=multi-user.target

Важный момент: когда нужно было применить изменения конфига без потери текущей сессии, использовали transient-юнит вне cgroup Orca. Это позволяет остановить основной сервис и перезапустить его, не убивая скрипт, который этим управляет:

# Запуск отложенного перезапуска через transient-юнит
systemd-run --unit=orca-reconfig \
  --description="Orca reconfiguration" \
  /bin/bash -c 'sleep 2 && systemctl restart orca-serve'

Нюанс с конфигом: почему нельзя менять на лету

Одна из неочевидных особенностей Orca: файл orca-data.json перезаписывается процессом каждые ~300мс. Если попытаться отредактировать его напрямую во время работы — изменения затрутся почти мгновенно.

Правильная последовательность:

  1. Остановить сервис
  2. Отредактировать orca-data.json
  3. Запустить сервис
  4. Подождать ~25 секунд и проверить, что значения не откатились миграциями

Это важно понимать, если хочешь включить экспериментальные фичи или изменить настройки агентов на сервере.

Автоматизация: очистка устаревших устройств

Когда устройств становится много (14 записей в реестре), появляется другая проблема: старые QR-коды и давно не заходившие устройства засоряют реестр. Настроили автоматическую очистку через ExecStartPre в systemd-юните.

Логика простая:

  • Устройство не заходило больше N дней → отзываем грант
  • Топ-3 самых свежих устройства всегда защищены (на случай если все давно не заходили)
  • QR-коды, которые ни разу не сканировали → удаляем

Начально поставили порог в 7 дней, но это оказалось мало — после 5-дневного перерыва MacBook вылетел бы из реестра и пришлось бы заново спариваться. Подняли до 20 дней.

STALE_DAYS = 20
MIN_KEEP = 3  # всегда оставляем топ-N свежих
 
from datetime import datetime, timedelta
import json
 
def cleanup_stale_devices(registry_path):
    with open(registry_path) as f:
        registry = json.load(f)
    
    cutoff = datetime.now() - timedelta(days=STALE_DAYS)
    devices = registry.get('devices', [])
    
    # Сортируем по lastSeenAt, защищаем топ-N
    active = sorted(
        [d for d in devices if d.get('lastSeenAt')],
        key=lambda d: d['lastSeenAt'],
        reverse=True
    )
    
    to_keep = set(d['id'] for d in active[:MIN_KEEP])
    
    result = []
    for device in devices:
        last_seen = device.get('lastSeenAt')
        if device['id'] in to_keep:
            result.append(device)
        elif last_seen and datetime.fromisoformat(last_seen) > cutoff:
            result.append(device)
        # else: устройство устарело, не включаем
    
    registry['devices'] = result
    with open(registry_path, 'w') as f:
        json.dump(registry, f, indent=2)

Dry-run на боевом реестре показал: под отзыв попала ровно одна запись — QR-код, который выпустили и ни разу не отсканировали. Остальные 13 устройств остались нетронутыми.

Проблема с UI-лагами: осторожно с экспериментальными фичами

В процессе настройки включили несколько экспериментальных параметров Orca, в том числе experimentalNativeChat и openAgentTabsInChatByDefault. После этого появились жалобы: текст промпта не виден при вводе, белый экран до обновления страницы.

Связь прямая: клиент читает настройки с сервера через settings.get, и экспериментальный UI рендерится на стороне клиента. Если клиент (десктопное приложение) не готов к этим настройкам — получаем визуальные артефакты.

Решение: откатить экспериментальные флаги, оставить только стабильные настройки. Урок — экспериментальные фичи тестировать сначала на мобильном рантайме (который можно перезапустить без потери основной сессии), и только потом применять к десктопному.

Bypass permissions для агентов

Отдельный вопрос — как быстро включить режим без подтверждений для агентов. Это нужно, когда хочешь запустить агента в автономном режиме без постоянных «разрешить/отклонить».

Для разных агентов флаги разные:

# Claude Code
claude --dangerously-skip-permissions
 
# Codex / OMP
codex --dangerously-bypass-approvals-and-sandbox
 
# Или через настройки Orca:
# Settings → Agents → нужный агент → Default arguments
# Значение: --approval-mode=yolo

Важный нюанс: bypass должен включаться на уровне агента (OMP, Claude и т.д.), а не на уровне Orca. Orca только передаёт аргументы агенту при запуске. Это разделение ответственности важно понимать, чтобы не искать настройку не там.

Итоговая схема

Вот что получилось в итоге:

┌─────────────────────────────────────────┐
│           Linux Server (24/7)           │
│                                         │
│  orca-serve.service                     │
│  └── WebSocket :6768 (VPN only)         │
│  └── ~/.config/orca (все проекты)       │
│  └── systemd автозапуск                 │
│  └── автоочистка устройств (20 дней)    │
└──────────────┬──────────────────────────┘
               │ WireGuard VPN
       ┌───────┴────────┐
       │                │
  MacBook Pro      iPhone
  (Orca desktop)   (Orca mobile)

  Second PC
  (Orca desktop)

Все три устройства подключены к одному рантайму. Проекты, агенты, история — всё общее. Сервер работает 24/7, перезапускается автоматически после ребута.

Выводы

Главный урок этой истории — не плодить рантаймы без необходимости. Два независимых процесса Orca с разными каталогами данных выглядят как «мобильный» и «десктопный» режим, но на деле это просто два изолированных сервера. Никакой магической синхронизации между ними нет. Один рантайм, к которому подключаются все клиенты — правильная архитектура.

Второй урок: используй то, что уже есть. Tailscale — отличный инструмент, но если у тебя уже работает WireGuard и собственный VPN-сервис, добавлять ещё один слой сети — лишняя сложность. Всегда сначала смотри, что уже есть в инфраструктуре.

Третий урок касается экспериментальных фич: тестируй на изолированном окружении. У нас был мобильный рантайм, который мы в итоге отключили — но он сыграл роль тестовой площадки. Применили настройки там, убедились что они не ломают UI, и только потом трогали основной рантайм. Когда этот порядок нарушился — получили лаги в интерфейсе.

Четвёртый урок: порог автоочистки должен учитывать реальные паттерны использования. 7 дней звучит разумно, но если ты берёшь отпуск или просто не заходишь с какого-то устройства неделю — оно вылетает из реестра и нужно заново спариваться. 20 дней — более реалистичный порог для рабочего инструмента. Всегда думай о крайних случаях: командировка, болезнь, просто другой ритм работы.

В целом, настройка Orca как постоянного серверного рантайма — это не rocket science, но требует понимания нескольких неочевидных деталей: как работает реестр устройств, почему конфиг нельзя менять на лету, как правильно изолировать доступ через VPN. Зато результат того стоит: открываешь Orca на любом устройстве — и сразу в работе, без лишних телодвижений.

Полезные ссылки

Паша Вин
Паша Вин

AI-инженер, предприниматель, маркетолог. Основатель feberra.com и x10seo.ru. 13 лет в перфоманс-маркетинге, 3 года в системной интеграции AI в бизнес.