Перейти к содержанию
Публикация AiManual

OpenCode на сервере: как развернуть автономного ИИ-агента и не пожалеть

Разбираем headless-режим OpenCode: запуск opencode serve, сетевые флаги, провайдер через OpenAI-совместимый эндпоинт, разрешения allow/ask/deny и деплой через s

Коротко

Что будет в материале

  1. 01

    Зачем выносить OpenCode на сервер

  2. 02

    Как устроен opencode serve: API, порт и сеть

  3. 03

    Провайдер моделей и авторизация сервера

  4. 04

    Разрешения allow/ask/deny и авто-режим

OpenCode — open-source harness-система для ИИ-агентов без привязки к вендору. Агент читает файлы, запускает тесты, привлекает другие модели, передаёт задачи субагентам и подключает MCP, скиллы и плагины. В разборе запуска OpenCode на сервере хорошо видна разница между демонстрацией в терминале и рабочей автономной схемой.

По умолчанию сессия живёт, пока открыт терминал. Отошли от ноутбука, и работа повисла между «подумать» и «сделать». Закрыли крышку, и процесс умер. Для фоновых задач нужен headless-режим: opencode serve поднимает HTTP-сервер с API, потоком событий и эндпоинтом OpenAPI-спецификации. К серверу стучатся из CI, cron, другого скрипта или IDE. Держать его прогретым между запусками полезно, чтобы не платить за холодный старт MCP и LSP каждый раз.

Короткий ответ: серверный OpenCode нужен, когда агенту надо работать без человека в контуре или принимать запросы из внешних систем. Для разовой задачи в терминале хватит TUI: сервер добавит инфраструктуру, которую придётся защищать, обновлять и мониторить.

Claude Code и Codex — закрытые проприетарные инструменты, заточенные под модели своего автора. OpenCode не привязан к одному поставщику: можно подключать официальных провайдеров, сторонние шлюзы и разные модели. Эта независимость делает серверный режим практичным: один harness, несколько моделей, внешние клиенты через API.

Зачем выносить OpenCode на сервер

Чем TUI отличается от headless-режима

Под капотом OpenCode уже клиент-серверная схема. TUI общается с локальным HTTP-сервером, который публикует OpenAPI-спецификацию и отдаёт её любому клиенту. opencode serve выставляет этот же сервер в headless-режиме, без терминального интерфейса. API остаётся тем же, меняется способ управления.

Если TUI уже запущен, opencode serve поднимет второй сервер и не тронет первый. Один процесс остаётся интерактивным, второй принимает запросы от CI или скриптов. На практике удобно держать отдельный сервер для автоматизации, а TUI использовать для ручной работы.

Разница проявляется в состоянии. TUI привязан к терминалу и вашей сессии. Headless-сервер живёт как обычный процесс: его можно запустить через systemd, положить в контейнер, перезапустить, проверить healthcheck. Он не спасает от нестабильных моделей и ошибок агента, но убирает зависимость от открытого ноутбука.

Кому серверный режим реально нужен, а кому нет

Серверный режим полезен в четырёх сценариях: ревью пул-реквестов из GitHub Actions, ночные cron- и systemd-задачи, удалённое управление из IDE, веб-клиенты через API. В каждом случае агент работает без постоянного присутствия человека или принимает запросы от другой системы.

Для разовых задач в терминале сервер не нужен. Если вы просите агента поправить файл и сразу смотрите результат, TUI проще. Сервер добавляет порты, пароли, логи, обновления и риск оставить открытый API. Это лишняя инфраструктура, пока нет повторяемого фонового сценария.

Для многодневных прогонов и автономных задач важнее не сам сервер, а ограничение контекста, память в файлах и проверка результатов. Эти вопросы разобраны в материале о harness для автономных задач.

Как устроен opencode serve: API, порт и сеть

Сервер по умолчанию слушает порт 4096 (либо выбирает случайный порт), а адрес и порт меняются флагами --hostname и --port. Те же параметры можно задать в конфигурационном файле: port, hostname, mdns. Для браузерных клиентов есть --cors (дополнительные разрешённые origin, флаг можно передавать несколько раз), а --mdns включает обнаружение сервиса в локальной сети и автоматически выставляет hostname в 0.0.0.0. Описание флагов и режимов работы сервера приведено в документации по HTTP-серверу OpenCode.

Флаги --hostname, --port, --cors и --mdns

ФлагЧто делаетКогда трогать
--hostnameЗадаёт адрес, на котором слушает серверКогда нужен доступ с другой машины, и только с паролем, firewall или VPN
--portМеняет порт; по умолчанию 4096 или случайныйКогда порт занят или нужна отдельная схема проброса
--corsДобавляет разрешённые браузерные origin; можно указать несколько разКогда веб-интерфейс открыт с другого origin; не открывайте всем подряд
--mdnsВключает mDNS-обнаружение и автоматически ставит hostname в 0.0.0.0Когда машин несколько и прописывать адреса вручную неудобно

Пример запуска: opencode serve --port 4096 --hostname 0.0.0.0. Смена --hostname на 0.0.0.0 без пароля и firewall — плохая идея. Сервер получит доступ к файлам и инструментам, а вы получите открытый API в сети. Для внешнего доступа ставьте reverse proxy с TLS и ограничением по IP.

При запуске TUI OpenCode случайным образом назначает порт и hostname; вместо этого можно передать свои значения и подключиться к серверу по ним.

OpenAPI-спецификация и генерация SDK

Сервер публикует OpenAPI 3.1 spec endpoint. По спецификации генерируют клиентов и инспектируют типы запросов и ответов. Сценарий простой: скрипт в пайплайне создаёт сессию, отправляет промпт с ссылкой на дифф, забирает события и комментарии. SDK убирает ручную сборку HTTP-запросов.

Спецификацию надо сверять с версией сервера. После обновления OpenAPI может измениться, и старый SDK начнёт ломаться. Pinned-версия и контрактный тест на пару ключевых вызовов экономят время при обновлениях.

Провайдер моделей и авторизация сервера

Провайдер подключается через OpenAI-совместимый эндпоинт. Подойдут официальные API, сторонние шлюзы и локальные серверы с совместимым интерфейсом. Тот же материал приводит BotHub как пример шлюза с оплатой в рублях без VPN. Это один из вариантов, не единственный.

Список моделей зависит от провайдера. В исходном описании упомянуты GLM 5.3 и Claude Opus 5.5. На сервере важна модель, а ещё лимиты, задержки и стабильность эндпоинта. Для ночных задач берите модель с предсказуемой стоимостью и таймаутом, иначе счёт вырастет быстрее, чем польза.

OPENCODE_SERVER_PASSWORD: что он закрывает и чего не делает

Базовая авторизация включается переменной OPENCODE_SERVER_PASSWORD: она защищает сервер через HTTP basic auth. Если переменная не задана, сервер остаётся незащищённым — это допустимо для локального использования, но для сетевого доступа пароль нужно задавать. Имя пользователя по умолчанию в доступных выдержках документации обрывочно, поэтому сверьте его с документацией вашей версии.

Пароля мало для публичного интернета: он не разграничивает права между клиентами, не шифрует трафик и не заменяет firewall или VPN. Если сервер смотрит в интернет, нужен reverse proxy с TLS и ограничением по IP. Пароль — минимум, а не полноценная система аутентификации. Для CI выдавайте отдельный пароль и меняйте его при утечке.

Ограничение исходного материала: статья на Habr обрывается на флаге --, поэтому детали systemd-юнитов, Docker-образов и плагинов сверяйте с документацией вашей версии. Ниже даны схематические примеры и места, где обычно ломается.

Разрешения allow/ask/deny и авто-режим

Система разрешений сводит каждое правило к одному из трёх исходов. allow выполняется без подтверждения, ask требует подтверждения, deny блокирует действие. Для сервера это ключевая настройка: в CI и cron человека нет, ответить на ask некому. Правила и их приоритеты описаны в документации по разрешениям OpenCode.

Правила применяются по шаблонам, и при совпадении нескольких правил побеждает последнее совпавшее. Разрешения задаются глобально и переопределяются для конкретных инструментов или агентов; правила агента имеют приоритет над глобальными.

В OpenCode есть auto mode: он автоматически одобряет запросы на разрешения, которые не запрещены явно, при этом deny-правила продолжают действовать. Auto mode меняет только те запросы, которые иначе требовали бы подтверждения. Отдельный CLI-флаг --auto в доступных материалах не подтверждён — сверьтесь с документацией версии, прежде чем прописывать его в юните или workflow.

  • allow: чтение файлов, запуск тестов и линтеров в рабочей копии.
  • ask: установка зависимостей, сетевые вызовы, изменение конфигов.
  • deny: push в main, доступ к секретам, удаление данных, произвольные команды за пределами workspace.

Правила стоит писать от запрета, а не от разрешения. Сначала deny на всё опасное, потом точечный allow на нужные инструменты. Широкий allow в сочетании с auto mode означает, что агент действует без человека в контуре. Это нормально для песочницы, но плохо для VPS с доступом к продакшену.

Деплой: systemd на VPS или Docker-контейнер

Два рабочих способа: systemd-сервис на VPS и Docker-контейнер. Первый даёт прямой доступ к файлам и окружению, второй — воспроизводимость и изоляцию. Выбор зависит от того, что важнее: минимум слоёв или предсказуемая среда.

Systemd-сервис: PATH, HOME и другие грабли

Главная ловушка systemd — минимальное окружение. Сервис запускается не из вашей shell-сессии, поэтому PATH не содержит путей из .bashrc или .zshrc, а HOME может отличаться от ожидаемого. Агент не находит бинарник, пишет конфиг не туда или видит пустой кэш.

Лечится явным указанием Environment, EnvironmentFile, WorkingDirectory и абсолютных путей в ExecStart. Пример скелета юнита:

[Service]
WorkingDirectory=/srv/projects/my-repo
Environment=HOME=/srv/opencode
Environment=PATH=/usr/local/bin:/usr/bin:/bin
ExecStart=/usr/local/bin/opencode serve --hostname 127.0.0.1 --port 4096
Restart=on-failure

Это скелет, а не готовый юнит. Подставьте свои пути и проверьте, под каким пользователем работает сервис. Логи systemd пишет в journald, отдельный файл не нужен. Если агент запускает тесты, убедитесь, что в окружении есть нужные переменные и доступ к workspace.

Docker: pinned-версия, изоляция и volume

Docker даёт pinned-версию образа: тег фиксируется, обновление становится осознанным действием. Workspace и сессии монтируются отдельными volume, чтобы состояние переживало пересоздание контейнера. Файловая система контейнера изолирована, но это не песочница безопасности: доступ к смонтированному workspace и сети остаётся.

docker run -d --name opencode -p 127.0.0.1:4096:4096 -v opencode-workspace:/workspace -v opencode-sessions:/path/to/sessions -e OPENCODE_SERVER_PASSWORD=... <image>:<pinned-tag>

Минусы Docker: сложнее с доступом к хостовым инструментам и прокси, нужно пробрасывать переменные и проверять сетевой доступ. Если агенту нужен Docker внутри, SSH-ключи хоста или GPU, контейнерная схема усложняется. Состояние проекта между сессиями можно хранить отдельно, например через Later Bender.

КритерийsystemdDocker
ВоспроизводимостьЗависит от VPS и ручных настроекВыше с pinned-тегом
Доступ к хостуПрямойЧерез volume и проброс
ИзоляцияНа уровне пользователя и прав ОСФайловая система контейнера
Отладкаjournalddocker logs

Критерий выбора простой. Если нужен минимум слоёв и прямой доступ к файлам, берите systemd. Если важнее повторяемый образ и чистая файловая система, берите Docker. В обоих случаях сервер не должен работать от root.

Практические сценарии: CI, cron, IDE и веб-клиенты

Серверный режим раскрывается в четырёх сценариях. В каждом есть внешний клиент, который не хочет держать терминал.

Ревью пул-реквестов через GitHub Actions

Workflow поднимает сервер или переиспользует уже запущенный, отправляет через API дифф и инструкцию, агент читает файлы, запускает тесты и оставляет комментарий. Нужны auto mode, узкие allow и deny, токен только на комментарии. Push в основную ветку лучше запретить на уровне прав, а не на уровне промпта.

Секреты не должны попадать в контекст агента. Передавайте минимальные переменные, не монтируйте весь .ssh и не давайте токен с правом записи в репозиторий, если агент только комментирует.

Ночные задачи с opencode-scheduler

Плагин opencode-scheduler от different-ai планирует повторяющиеся задачи через нативные планировщики ОС: launchd на macOS, systemd на Linux, Task Scheduler на Windows, с fallback на cron там, где нативные бэкенды недоступны. Плагин записывает файл задачи и ставит таймер в планировщике ОС; в назначенное время планировщик вызывает supervisor-скрипт, который запускает задачу, дописывает логи и обновляет метаданные задачи. Проект упоминается в официальном списке экосистемы OpenCode, а его репозиторий и описание работы доступны на GitHub.

Ночью никто не ответит на ask, поэтому правила должны быть в allow и deny, а результат — в логах и артефактах. Ночной прогон стоит ограничивать по времени и бюджету токенов. Если задача может идти часами, ставьте таймаут и внешний kill-switch. Пример дисциплины для локального марафона описан в разборе Qwen 27B на двух GPU: мелкие фазы, машинная проверка и человек на приёмке.

IDE и веб-клиенты работают через тот же HTTP API. Для браузерного клиента с другого origin нужен --cors, но не открывайте CORS всем подряд. IDE подключается к серверу по адресу и порту, а не запускает второй экземпляр агента.

Ограничения безопасности: OpenCode — не песочница

OpenCode запускает инструменты и читает файлы с правами того пользователя, под которым работает. Запустили сервис как root, агент получил root. Смонтировали docker.sock, агент получил контроль над хостом. Это обычные последствия широких прав, а не экзотическая атака.

Что сделать дополнительно: отдельный пользователь без sudo, контейнер с минимальным набором смонтированных путей, исходящие соединения по allowlist, аудит MCP-серверов и плагинов, read-only токены для CI.

MCP-серверы вне модели угроз

MCP-сервер — отдельный процесс со своими правами. Harness вызывает его инструменты, но не контролирует, что внутри. MCP-сервер может читать файлы, ходить в сеть или выполнять команды, которые вы ему разрешили. Подключайте проверенные серверы и ограничивайте их права на уровне ОС.

Если агенту нужен доступ к состоянию Linux-сервера, посмотрите разбор MCP daemon. Там показано, как выдать точечные права вместо SSH с sudo и где конфигурация превращает агента в полный root.

Bun и прокси: что учесть

OpenCode работает на Bun. У Bun есть особенности работы с прокси, которые влияют на сетевые запросы агента. Проверяйте переменные HTTP_PROXY, HTTPS_PROXY и NO_PROXY, тестируйте доступ к провайдеру и MCP-серверам до запуска в прод.

Прокси может ломать поток событий, если соединение долго живёт. Проверьте таймауты, keep-alive и логи reverse proxy. Ошибка в прокси выглядит как зависший агент, хотя модель и сервер живы.

Мониторинг: health-эндпоинт, journald и Docker logs

Сервер OpenCode предоставляет API для проверки здоровья и версии, возвращающий { healthy: true, version: string }. Исторический маршрут /global/health относился к v1 HTTP API; в v2-серверах этого маршрута нет, и запросы к неизвестным не-/api путям возвращают HTML веб-интерфейса вместо JSON. Поэтому перед настройкой healthcheck уточните версию сервера и точный путь из его OpenAPI-спецификации.

Для systemd логи смотрите в journalctl -u opencode, для Docker — в docker logs. Плагин opencode-otel для телеметрии в OpenTelemetry в доступных материалах не подтверждён: если он нужен, проверьте его существование и настройку по актуальной документации, прежде чем закладывать в схему.

healthcheck:
  test: ['CMD', 'curl', '-f', 'http://127.0.0.1:4096/<health-path>']
  interval: 30s
  timeout: 5s
  retries: 3

Это пример для Docker Compose, curl должен быть в образе, а путь подставьте из спецификации вашей версии. Алерт ставьте на недоступность healthcheck и на рост ошибок 5xx. Отдельно полезен алерт на завершение процесса и на исчерпание диска: агент активно пишет логи и артефакты.

Чек-лист перед запуском в прод

  • Пароль OPENCODE_SERVER_PASSWORD задан, сервер не слушает 0.0.0.0 без необходимости.
  • Firewall и reverse proxy с TLS, доступ по IP или VPN.
  • Правила allow, ask и deny продуманы, auto mode только с внешними ограничениями.
  • MCP-серверы проверены, их права урезаны.
  • Версия OpenCode и образ pinned.
  • Workspace и сессии лежат на отдельных volume или в отдельных каталогах.
  • healthcheck на health-эндпоинт из спецификации вашей версии, логи в journald или Docker logs.
  • CI-токены только на чтение и комментарии, без push в main.
  • Прокси-переменные проверены, доступ к провайдеру и MCP протестирован.

Серверный OpenCode — инфраструктурный компонент. Его обновляют, мониторят и ограничивают так же, как любой другой сервис с доступом к коду и сети.

Подписаться на канал