OpenCode и Goose: ИИ-агент для кода на своём сервере
Агент для работы с кодом — это программа, которая по задаче, поставленной словами, сама читает файлы, правит их и выполняет команды. На ноутбуке такая работа обрывается вместе с закрытой крышкой. На сервере — нет. Разбираем, какой из открытых агентов выбрать, как его поставить и как ограничить ему права.
Зачем агенту отдельный сервер
Агент работает не секундами. Он читает десятки файлов, запускает сборку, ждёт тесты, исправляет и запускает снова — задача занимает минуты, иногда полчаса. Всё это время процесс должен быть жив. На рабочей машине его убивает любая мелочь: закрытая крышка ноутбука, обрыв связи, перезагрузка. На сервере процесс продолжает работать, а вы подключаетесь и отключаетесь когда угодно.
Вторая причина важнее первой. Агент выполняет команды по-настоящему: он может удалить файл, установить пакет, отправить запрос в сеть. На рабочей машине рядом с проектом лежат другие проекты, ключи от серверов и настроенное годами окружение. На отдельном сервере лежит только то, что вы туда положили, и цена ошибки становится измеримой.
Этот довод подробно разобран в статье про Claude Code на VPS. Разница в том, что Claude Code привязан к одному поставщику моделей, а OpenCode и Goose — открытые программы, которые работают с ключом любого поставщика и с моделью, запущенной на вашем же сервере. Именно поэтому их ставят на арендованную машину чаще: менять модель можно, не меняя привычек.
OpenCode, Goose или OpenHands
Открытых агентов много, но всерьёз выбирают из трёх. Разница между ними не в качестве ответов — оно зависит от модели, — а в том, как они устроены и что требуют от сервера.
| Агент | Как устроен | Когда брать |
|---|---|---|
| OpenCodeMIT, 1.18.26 | Один исполняемый файл. Работает в терминале, при желании открывает тот же интерфейс в браузере. Зависимостей нет. | Основной случай: живая работа над проектом с подключением по SSH. |
| GooseApache 2.0, 1.48.0 | Тоже один файл, но легче по памяти. Умеет сохранять задачу в файл-рецепт и выполнять её без человека за терминалом. | Повторяющиеся задачи без участия человека: отчёт, разбор журналов, проверка изменений. |
| OpenHandsMIT | Веб-приложение в Docker. Каждую задачу выполняет в отдельном контейнере, для этого ему отдают сокет Docker. | Нужна изоляция каждой задачи и интерфейс для нескольких человек. |
Дальше в статье основной — OpenCode: он ставится за минуту и не требует ни Docker, ни Node.js. Goose разобран отдельным разделом ниже, потому что закрывает другую задачу — работу по расписанию. OpenHands мы не рассматриваем: доступ к сокету Docker равносилен правам администратора на всём сервере, и ради изоляции задач вы отдаёте агенту машину целиком.
Что за проекты и кому принадлежат
OpenCode развивает компания Anomaly — та же команда, что делает средство разработки SST; репозиторий раньше лежал по адресу sst/opencode. На сентябрь 2026 у него около 203 000 звёзд на GitHub. Goose начинал в компании Block, а в апреле 2026 передан в Agentic AI Foundation — организацию Linux Foundation, куда вошли также протокол MCP и соглашение AGENTS.md; звёзд около 53 800. Обе программы бесплатны целиком, платных изданий у них нет.
Что понадобится
- Сервер с Ubuntu 22.04 или 24.04, доступ по SSH. Сам агент нетребователен: в наших замерах он занимал около 300 МБ памяти в покое и 500–550 МБ во время задачи. Память нужна не ему, а проекту — сборке, тестам, базе данных рядом.
- Место на диске. Каждая из двух программ занимает около 300 МБ вместе со вспомогательными файлами. Остальное уходит на сам проект и его зависимости.
- Доступ к модели. Либо ключ поставщика, которым вы уже пользуетесь, либо бесплатные модели, доступные в OpenCode сразу после установки — их хватит, чтобы проверить работу. Локальная модель на сервере без видеокарты для агента не подходит, и ниже объясняется почему.
Если сервера ещё нет
4 ГБ RAM · 40 ГБ диска
Четыре гигабайта памяти взяты не под агента, а под то, что он будет запускать: установку зависимостей, сборку и тесты проекта. Если сервер отведён только под правку конфигураций и небольших сценариев, хватит и двух гигабайт. Диск от 40 ГБ даёт запас на сам проект: агент часто ставит пакеты и оставляет промежуточные файлы.
В каталоге под эти требования подходят 83 тарифа, самый дешёвый — 720 ₽/мес (HostKey, 4 ГБ, 60 ГБ NVMe).
Открыть каталог с этими фильтрами →Шаг 1. Отдельный пользователь
Агента запускают не от имени администратора. Сначала ставим то, что понадобится в работе, потом создаём отдельного пользователя и переносим ему ваш открытый ключ, чтобы заходить по SSH сразу под ним:
sudo apt update && sudo apt install -y curl git tmux
sudo useradd -m -s /bin/bash agent
sudo mkdir -p /home/agent/.ssh
sudo cp ~/.ssh/authorized_keys /home/agent/.ssh/
sudo chown -R agent:agent /home/agent/.ssh
sudo chmod 700 /home/agent/.ssh
sudo chmod 600 /home/agent/.ssh/authorized_keysЕсли на сервер вы заходите по паролю, файла ~/.ssh/authorized_keys у вас нет и команда копирования выдаст ошибку. Тогда откройте /home/agent/.ssh/authorized_keys в редакторе и вставьте туда свой открытый ключ (~/.ssh/id_ed25519.pub на вашем компьютере) — права на файл те же.
Пароля у этого пользователя нет, вход только по ключу — тому же, которым вы заходите сами. В группу sudo его не добавляем: это главное ограничение всей схемы. Что бы агент ни выполнил, за пределы домашнего каталога и общедоступных файлов он не выйдет.
Дальше все команды выполняются на сервере под этим пользователем:
ssh agent@ВАШ_IPШаг 2. Установка OpenCode
Установка выполняется от пользователя agent, права администратора не нужны:
curl -fsSL https://opencode.ai/install | bashСкрипт кладёт один файл в ~/.opencode/bin/opencode и дописывает строку с путём в ~/.bashrc. Ни Node.js, ни Docker, ни компилятор не требуются — всё нужное уже внутри файла.
Сразу после установки команда не найдётся
Новый путь подхватывается только в следующем сеансе. Выйдите и зайдите заново или выполните exec bash -l — после этого opencode --version покажет версию, у нас это 1.18.26.
Проверить работу можно немедленно и бесплатно: у OpenCode есть несколько моделей, которые отвечают без ключа. Посмотреть список и задать вопрос:
opencode models
opencode run --model opencode/big-pickle "Ответь одним словом: сколько будет 2+2?"Пришёл ответ — установка закончена. Дальше стоит помнить о двух особенностях бесплатных моделей. Они общие для всех: скорость непредсказуема (один и тот же вопрос у нас обработался за 9, 17 и 166 секунд на трёх разных моделях), а при большом количестве обращений вместо ответа возвращается сообщение о превышении лимита — тогда берут другую модель из списка или подключают свой ключ. И, по документации сервиса, содержимое запросов к бесплатным моделям может использоваться для их улучшения — на закрытом коде их лучше не пробовать.
Шаг 3. Подключение модели
Для работы над своим проектом подключается ключ поставщика. Команда открывает список, в котором выбирают поставщика и вставляют ключ; то же самое делает команда /connect, набранная внутри интерфейса агента:
opencode auth loginМодель по умолчанию задаётся в файле настроек, который создаётся при установке. Точное имя модели берётся из вывода opencode models — оно всегда в формате «поставщик/модель»:
{
"$schema": "https://opencode.ai/config.json",
"model": "opencode/big-pickle"
}Агенту нужна модель, умеющая вызывать инструменты, — без этого он не сможет ни читать файлы, ни выполнять команды. У крупных поставщиков это умеют все актуальные модели, а вот у маленьких локальных с этим сложнее.
Локальная модель: честная оценка
OpenCode умеет обращаться к Ollama на этом же сервере — настройка занимает несколько строк, и никаких дополнительных пакетов ставить не нужно, недостающее OpenCode догрузит сам:
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"ollama": {
"npm": "@ai-sdk/openai-compatible",
"name": "Ollama",
"options": { "baseURL": "http://127.0.0.1:11434/v1" },
"models": {
"qwen3:1.7b": { "name": "Qwen3 1.7B" }
}
}
}
}После этого модель появляется в списке как ollama/qwen3:1.7b. Настройка работает, а вот результат разочаровывает. Мы проверили это на сервере без видеокарты с четырьмя ядрами: скорость составила около шести токенов в секунду, и за десять минут агент не справился с задачей «прочитай файл из одной строки и скажи, что он делает» — трижды перечитал файл и в итоге ошибся в формате вызова инструмента.
Дело не только в скорости. Агент передаёт модели описание своих инструментов — это около двух тысяч токенов ещё до вашей задачи, а Ollama на процессоре по умолчанию отводит под весь разговор 4096 токенов (меняется переменной OLLAMA_CONTEXT_LENGTH, но каждый шаг увеличения требует памяти). Вывод простой: на сервере без видеокарты локальную модель для агента брать не стоит.
Шаг 4. Первый запуск и права агента
Агент работает с тем каталогом, из которого запущен. Забираем проект на сервер и запускаем:
mkdir -p ~/projects && cd ~/projects
git clone https://github.com/ваш-логин/myapp.git
cd myapp
opencodeОткрывается интерфейс в терминале. Внизу экрана указан текущий режим и модель — например, Build · Big Pickle. Клавиша Tab переключает режим,Ctrl+P открывает список команд. Режимов два, и разница между ними принципиальна: Plan только читает код и отвечает, ничего не меняя,Build — правит файлы и выполняет команды. Первую задачу в незнакомом проекте разумно ставить в режиме Plan.
По умолчанию агенту разрешено почти всё, кроме чтения файлов с переменными окружения (.env). Правила задаются разделом permission в том же файле настроек: разделы model, provider и permission живут в нём рядом, отдельных файлов заводить не нужно. Разумный набор для начала:
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"bash": {
"*": "ask",
"git *": "allow",
"npm run *": "allow",
"rm *": "deny",
"sudo *": "deny"
},
"external_directory": "deny"
}
}Читается это так: любую команду агент спрашивает, работу с системой контроля версий и запуск сценариев проекта выполняет молча, удаление файлов и попытки повысить права запрещены совсем, выход за пределы каталога проекта — тоже. Мы проверили запрет на живой установке: команда не выполняется, а агенту возвращается отказ с текстом сработавшего правила. Значение ask имеет смысл только в живом сеансе: в неинтерактивном режиме opencode run подтверждать запрос некому, и он автоматически отклоняется.
Шаг 5. Долгие задачи и доступ из браузера
Если запустить агента прямо в сеансе SSH, обрыв связи прервёт задачу. Запускайте его внутри tmux — программы, которая держит сеанс терминала на сервере независимо от вашего подключения:
tmux new -s agent # создать сеанс и работать в нём
# отсоединиться: Ctrl+B, затем D
tmux attach -t agent # вернуться в него с любого устройстваВторой способ работы — тот же интерфейс в браузере. На сервере его поднимает команда opencode serve: она слушает только адрес 127.0.0.1 и наружу ничего не отдаёт. Пароль задаётся переменной окружения, имя пользователя по умолчанию — opencode. Сгенерируем пароль, сохраним его в файл и запустим:
openssl rand -base64 24 > ~/.opencode-password
chmod 600 ~/.opencode-password
cd ~/projects/myapp
OPENCODE_SERVER_PASSWORD=$(cat ~/.opencode-password) opencode serve --port 4096Чтобы интерфейс поднимался сам после перезагрузки, оформим его службой. Проверочный запуск при этом надо остановить клавишами Ctrl+C, иначе порт окажется занят. Пароль — тот же, что в файле выше; кладём его туда, где его прочитает только администратор:
OPENCODE_SERVER_PASSWORD=строка_из_файла_.opencode-password[Unit]
Description=OpenCode server
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=agent
WorkingDirectory=/home/agent/projects/myapp
EnvironmentFile=/etc/opencode.env
ExecStart=/home/agent/.opencode/bin/opencode serve --port 4096
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable --now opencodeСо своего компьютера порт пробрасывается туннелем SSH, после чего интерфейс открывается по адресу http://127.0.0.1:4096 в обычном браузере:
ssh -N -L 4096:127.0.0.1:4096 agent@ВАШ_IPНе открывайте этот порт наружу
У serve есть параметр --hostname 0.0.0.0, который выставляет интерфейс в интернет. Делать этого не нужно: через него выполняются команды на сервере, и единственная защита — пароль в переменной окружения. Туннель SSH даёт тот же результат без открытого порта.
Goose: когда он подходит лучше
Goose решает ту же задачу, но у него есть две особенности, ради которых его ставят рядом. Первая — вес: в наших замерах он занимал около 110 МБ памяти против примерно 500 МБ у OpenCode. Вторая важнее — задачу можно сохранить в файл-рецепт и выполнять её без человека за терминалом, по расписанию.
Установка требует одного пакета, иначе архив не распакуется:
sudo apt install -y bzip2
curl -fsSL https://github.com/aaif-goose/goose/releases/download/stable/download_cli.sh | CONFIGURE=false bashПрограмма кладётся в ~/.local/bin/goose; как и в случае с OpenCode, путь подхватывается при следующем входе. Переменная CONFIGURE=false отключает интерактивную настройку — на сервере её удобнее заменить двумя файлами. Первый задаёт поставщика и модель, второй хранит ключ:
GOOSE_PROVIDER: anthropic
GOOSE_MODEL: claude-sonnet-5ANTHROPIC_API_KEY: ваш_ключМы проверили: ключ из этого файла подхватывается, отдельная команда настройки не нужна. Локальная модель подключается так же просто — GOOSE_PROVIDER: ollama и OLLAMA_HOST: http://127.0.0.1:11434, с теми же оговорками про скорость, что и выше.
Разовая задача без сохранения истории выполняется одной командой:
cd ~/projects/myapp
goose run --no-session -t "Проверь, что все зависимости в package.json используются"Ради чего всё затевалось — повторяющаяся задача. Она описывается файлом-рецептом, в котором обязательно поле prompt: без него запуск без человека завершается ошибкой no text provided for prompt in headless mode.
version: 1.0.0
title: Проверка зависимостей
description: Ищет неиспользуемые пакеты в проекте
instructions: Ты работаешь в каталоге проекта и отвечаешь коротко, списком.
prompt: Найди в package.json пакеты, которые нигде не импортируются, и выведи их списком.goose run --no-session --recipe ~/recipes/deps.yamlКогда рецепт отработал вручную, его ставят на расписание. Расписание задаёт системный cron: crontab -e под пользователем agent и одна строка. Пути указываются полностью — у cron своё короткое значение PATH, и короткое имя команды он не найдёт:
0 9 * * 1 cd /home/agent/projects/myapp && /home/agent/.local/bin/goose run --no-session --recipe /home/agent/recipes/deps.yaml >> /home/agent/deps.log 2>&1Почему не встроенное расписание goose
У Goose есть своя команда goose schedule add, и она действительно записывает задание — goose schedule list показывает его в списке. Но выполнять задания некому: встроенный планировщик живёт внутри запущенного приложения, а на сервере оно не запущено. Мы проверили: задание с расписанием «каждую минуту» даже через полторы минуты оставалось со строкой Last Run: Never, в том числе при работающем goose serve. Поэтому на сервере расписание отдают cron.
Что агент может на самом деле
Правила permission ограничивают агента, но не превращают его в песочницу. Модель решает, какую команду вызвать, а выполняется команда от имени пользователя agent со всеми его правами. Простое правило: считайте, что всё доступное этому пользователю доступно и агенту.
- Никакого sudo. Права администратора агенту не нужны ни для одной задачи по коду. Если пакет действительно нужен системе — поставьте его сами.
- Ключи от других серверов — не здесь. В домашнем каталоге этого пользователя не должно быть ни ключей от рабочих серверов, ни доступов к базам с настоящими данными.
- Проект — копия репозитория. Работайте в клоне репозитория и регулярно смотрите
git diff. Это единственный способ отличить нужную правку от лишней. - Порт агента не выставляется в интернет. Только адрес
127.0.0.1и туннель SSH. - Чужой код — отдельный сервер. Если проект принадлежит клиенту, дешевле поднять отдельную машину, чем разбираться потом, что именно агент прочитал.
Более строгая изоляция — запуск агента внутри контейнера, из которого виден только каталог проекта. Это уменьшает ущерб от ошибки, но добавляет работы: контейнеру придётся отдать всё, что нужно проекту, — язык, пакеты, сеть. Описанный выше вариант — отдельный пользователь без прав администратора — закрывает большую часть рисков и не мешает работать. Общие настройки сервера разобраны в статье о базовой безопасности VPS.
Частые проблемы
opencode: command not found сразу после установки
Установка прошла, но путь к программе добавлен в ~/.bashrc, а текущий сеанс этот файл уже прочитал. Выйдите и зайдите заново либо выполните exec bash -l. То же самое относится к Goose: он ставится в ~/.local/bin, который добавляется в путь при входе в систему. Важное следствие: ~/.bashrc читается только для сеанса с клавиатурой, поэтому в сценариях, службах и заданиях cron команду всегда пишут полным путём — /home/agent/.opencode/bin/opencode.
opencode web на сервере выдаёт ошибку xdg-open
Команда web рассчитана на настольную систему: она поднимает интерфейс и сразу пытается открыть браузер. На сервере браузера нет, и вместо запуска выводится сообщение Executable not found in $PATH: xdg-open. Сам интерфейс при этом работает, но пугающее сообщение остаётся в журнале. На сервере используйте opencode serve --port 4096 — интерфейс тот же, попытки открыть браузер нет.
Локальная модель бесконечно перечитывает один и тот же файл
Это не ошибка настройки, а нехватка возможностей модели. Небольшие модели путаются в вызове инструментов и зацикливаются, а короткий предел разговора (у Ollama на процессоре по умолчанию 4096 токенов) вытесняет начало задачи из памяти модели. Увеличьте предел переменной OLLAMA_CONTEXT_LENGTH и возьмите модель покрупнее — но на сервере без видеокарты это упирается в скорость. Рабочее решение — внешняя модель по ключу.
Установка Goose обрывается: bzip2 is required but not installed
В минимальном образе Ubuntu этого архиватора нет, а установочный скрипт им распаковывает архив. Поставьте sudo apt install -y bzip2 и повторите установку. После неудачной попытки в домашнем каталоге остаётся скачанный архив goose-x86_64-unknown-linux-gnu.tar.bz2 — его можно удалить.
Коротко: порядок действий
- Отдельный пользователь
agentбез прав администратора, вход по ключу. curl -fsSL https://opencode.ai/install | bash, затем перезайти в систему.- Проверка бесплатной моделью:
opencode run --model opencode/big-pickle. - Свой ключ через
opencode auth login, модель по умолчанию — в настройках. - Правила
permission: удаление и sudo запрещены, остальное спрашивается. - Работа в
tmux, чтобы обрыв связи не прерывал задачу. - Браузерный интерфейс —
opencode serve --port 4096и туннель SSH. - Goose ставится рядом, если нужны повторяющиеся задачи: рецепт и строка в cron.
Частые вопросы
Отдельная машина под агента — тот случай, когда проект остаётся на своём сервере, а агенту достаётся только рабочая копия репозитория. Сборки и тестов на ней нет, поэтому требования падают до 2 ГБ памяти и 20 ГБ диска.
Под эти требования в каталоге подходит 108 тарифов, от 429 ₽/мес (AdminVPS, 2 ГБ, 30 ГБ NVMe).
Тарифы от 2 ГБ RAM→