Как запустить sandboxd на собственном VPS
Пошаговое руководство по развертыванию sandboxd для создания AI приложений. Настройка Docker, ключей моделей, HTTPS через Traefik, лимитов RAM и очистка старых контейнеров.
Что такое sandboxd и что дает его самостоятельный запуск
Для самостоятельного размещения sandboxd вам потребуется один Linux-сервер с Docker и доменное имя. Вы отправляете запрос (prompt), агент по написанию кода создает полноценное приложение внутри изолированного контейнера, и это приложение становится доступным по собственному URL для предварительного просмотра. Генераторы приложений по запросу — самая популярная категория сервисов в 2026 году, а sandboxd — это решение, которое работает на вашем VPS под лицензией MIT, при этом сгенерированный код хранится на вашем собственном диске.
Архитектура намеренно сделана компактной. Панель управления на Go управляет Docker, Traefik v3 маршрутизирует каждое имя хоста для предварительного просмотра, SQLite хранит состояние, а каждое приложение работает в отдельном контейнере. Здесь нет Kubernetes и отдельного сервера баз данных, поэтому система способна работать даже на машине с 2 vCPU.
Вся модель строится на четырех объектах. App (приложение) — это постоянный проект, содержащий свое имя, метаданные git и секреты. Sandbox (песочница) — это Docker-контейнер, в котором работает приложение; одно приложение в каждый момент времени связано с одной песочницей. Workspace (рабочая область) — это файлы приложения, которые находятся на хосте и сохраняются после остановки контейнера. Task (задача) — это один запрос, переданный агенту внутри песочницы. Остановка песочницы освобождает память, но сохраняет файлы. Удаление песочницы уничтожает контейнер, после чего приложение может запустить новый.
В чем разница между sandboxd, Dify и OpenHands?
Эти три инструмента часто путают, так как все они запускают LLM (большую языковую модель) на вашем сервере, но результат их работы различается. Dify создает приложения на базе LLM: чат-интерфейсы, конвейеры поиска (retrieval pipelines) и рабочие процессы, которые обращаются к модели при каждом использовании. Модель является частью готового продукта. OpenHands работает с уже существующим репозиторием: вы указываете путь к коду, и инструмент читает файлы, выполняет команды и предлагает изменения. sandboxd начинает с нуля. Он создает каркас проекта на основе шаблона, собирает его в изолированном контейнере и предоставляет URL для просмотра. На выходе получается обычное приложение на React или FastAPI, которому для работы не требуется модель.
Выбирайте инструмент в зависимости от того, что вы хотите получить в итоге. sandboxd предназначен для создания проекта из текстового описания с последующим сохранением кода. Два других инструмента подходят для случаев, когда репозиторий или продукт на базе модели уже существуют.
Другое различие заключается в возрасте проекта, и это фактор, который стоит оценить перед тем, как строить на его основе что-то серьезное.
Данные, на которых построен график
[
{
"tool": "sandboxd",
"github_stars": "875",
"forks": "50"
},
{
"tool": "OpenHands",
"github_stars": "83,091",
"forks": "10,711"
},
{
"tool": "Dify",
"github_stars": "151,320",
"forks": "23,886"
}
]У sandboxd 875 звезд, у OpenHands — 83,091, а у Dify — 151,320. Репозиторий был создан 3 июня 2026 года, поэтому по состоянию на август 2026 года проекту два месяца, в то время как OpenHands существует с марта 2024 года, а Dify — с апреля 2023 года. Релиз v0.1.0 вышел 6 июня 2026 года, а v0.3.6 — 1 августа 2026 года. Проект позиционирует себя как бета-версию и предупреждает, что релизы 0.x могут нарушать обратную совместимость. Воспринимайте эти цифры как риск при выборе зависимости, а не как оценку качества: двухмесячный проект прошел лишь два месяца тестирования другими пользователями, которые находили в нем ошибки.
Что нужно серверу и что ломается при нехватке ресурсов
В документации проекта указано, что для запуска достаточно 2 vCPU и 4 GB RAM. Это верно для управляющей плоскости (control plane) и одной небольшой песочницы, но недостаточно для одновременной работы двух пользователей. Распределяйте память по частям. Traefik и управляющая плоскость на Go потребляют мало ресурсов. Каждая запущенная песочница содержит полный набор инструментов Node или Python, а пиковая нагрузка возникает при npm install, за которой следует сборка production-версии. Планируйте 8 GB для сервера, который будет поддерживать несколько приложений, и рассматривайте swap как страховку, а не как основной объем памяти, так как сборка, использующая swap, занимает минуты вместо секунд.
При нехватке памяти возникают два разных типа сбоев, которые выглядят совершенно по-разному. Внутри песочницы контейнер достигает жесткого лимита --memory, установленного sandboxd, и ядро завершает самый ресурсоемкий процесс, поэтому сборка прерывается без полезных сообщений от агента. docker ps -a показывает код завершения 137 для этого контейнера, а docker inspect сообщает о "OOMKilled": true. Сборка на Node, которая завершается таким образом, часто сначала выводит JavaScript heap out of memory.
Второй тип сбоя происходит на хосте. sandboxd запускает механизм очистки по давлению (pressure reaper), который останавливает песочницы при нехватке памяти хоста, поэтому на маленьком сервере песочница может исчезнуть прямо во время просмотра превью. Файлы остаются в сохранности, и следующий запрос к URL превью активирует её снова, но задача, которая выполнялась в момент остановки контейнера, не возобновляется.
Диск — это менее очевидная проблема. Каждое приложение хранит свое рабочее пространство на хосте, а JavaScript-проект содержит дерево node_modules размером в сотни мегабайт. Десять приложений — это несколько гигабайт зависимостей, не считая образов. Начинайте с 40 GB и следите за свободным местом:
docker system df
sudo du -sh /var/lib/sandboxed/workspacesВ версии v0.3.6, на которой основано это руководство, директория данных по умолчанию — /var/lib/sandboxed, написанная с дополнительным e. Ввод /var/lib/sandboxd в этом случае ничего не даст и приведет к пяти минутам путаницы. Это изменилось в версии v0.3.9 (25 августа 2026). Новые установщики размещают свежие установки в /var/lib/sandboxd, а /var/lib/sandboxed сохраняют только для уже существующих инсталляций. На сервере, настроенном с использованием более поздней версии, используйте путь без e во всех приведенных ниже командах.
Установка фиксированной версии sandboxd
На сервере должны быть предварительно установлены Docker Engine с плагином Compose и git. В руководстве Установка Docker на VPS описан этот процесс.
docker compose version
git --versionОбе команды должны вывести версию. Ошибка docker: 'compose' is not a docker command означает, что отсутствует плагин Compose v2. Установщик отдает предпочтение плагину, но при его отсутствии использует автономный бинарный файл docker-compose, и завершает работу с ошибкой Docker Compose not found только если не найдено ни того, ни другого. Команды в этом руководстве используют docker compose, поэтому установка плагина является более простым решением.
Установщик представляет собой shell-скрипт, загружаемый из сети, поэтому изучите его содержимое перед запуском и зафиксируйте версию.
curl -fsSL https://raw.githubusercontent.com/tastyeffectco/sandboxd/v0.3.6/install.sh -o install-sandboxd.sh
less install-sandboxd.sh
SANDBOXD_REF=v0.3.6 bash install-sandboxd.shSANDBOXD_REF — это git-ссылка, которую установщик использует для оформления версии в $HOME/.sandboxd/src; по умолчанию используется main. Если оставить эту переменную не заданной, установленная версия будет соответствовать последним изменениям, внесенным в репозиторий на текущий момент. Это критично для проекта, который только в июле 2026 года выпустил шесть релизов. Зафиксируйте версию и обновляйтесь осознанно после прочтения списка изменений. По состоянию на 12 октября 2026 года новейшим релизом является v0.3.22, что на шестнадцать релизов новее зафиксированной здесь версии v0.3.6.
Скрипт клонирует исходный код, собирает образы, запускает стек с помощью docker compose up -d и в конце выводит URL консоли и API-токен. Сохраните этот токен в надежном месте. Это учетные данные для API, который управляет Docker с правами root.
curl http://127.0.0.1:9090/healthzЭта команда выводит ok, когда панель управления запущена. Если вывод пуст, значит, стек не запустился: выполните docker compose ps из директории ~/.sandboxd/src, чтобы увидеть, какой сервис не работает, а затем docker compose logs sandboxd, чтобы выяснить причину.
Доступ к консоли на удаленном сервере
Консоль обслуживается через Traefik на HTTP_PORT, который по умолчанию использует порт 80, по имени хоста http://console.localhost. Traefik выполняет маршрутизацию на основе имени хоста, поэтому ввод IP-адреса вашего сервера в браузере не соответствует ни одному правилу и возвращает ошибку 404. Пока вы не настроили реальный домен, выполните проброс порта и сохраните имя хоста:
ssh -L 8080:127.0.0.1:80 you@your-vpsЗатем откройте http://console.localhost:8080 на вашем ноутбуке. В Linux и macOS любое имя, заканчивающееся на .localhost, разрешается в 127.0.0.1, поэтому запрос проходит через туннель с корректным заголовком Host. Установите пароль для консоли при первом посещении.
Назначение модели агенту
В базовый образ включены два агента для написания кода: OpenCode и Claude Code. SANDBOXD_DEFAULT_AGENT определяет, какой из них выполнит задачу, если агент не указан явно; по умолчанию используется opencode. Если ключ не подключен, задачи выполняются с использованием бесплатных моделей OpenCode Zen без ключа. Таким образом, первая сборка не требует затрат, и вы можете протестировать весь цикл работы перед оплатой.
Подключите собственный ключ, если вам нужна более мощная модель. Ключи передаются в плоскость управления (control plane) и никогда не попадают в песочницу: они хранятся в зашифрованном виде в каталоге данных и передаются по сети через прокси учетных данных. Благодаря этому ни агент, ни написанный им код не могут прочитать эти ключи.
export API=http://127.0.0.1:9090
export SANDBOXD_TOKEN=sk_... # printed by the installer
export AUTH="Authorization: Bearer $SANDBOXD_TOKEN"
curl -s -XPOST $API/v1/agents/claude-code/api-key -H "$AUTH" \
-H 'content-type: application/json' \
-d '{"api_key":"sk-ant-..."}'То же самое можно сделать в консоли в разделе Settings, AI Agents. Там доступен пошаговый процесс OAuth, если вы хотите использовать подписку Claude вместо API-ключа. Модель, используемая агентом по умолчанию, настраивается на той же панели, при этом для отдельной задачи её можно переопределить.
Создание небольшого приложения от начала до конца
Создайте приложение, запустите его изолированную среду (sandbox), а затем отправьте запрос. Идентификаторы возвращаются в формате JSON, и руководство по быстрому старту извлекает их с помощью sed, поэтому вам не нужно устанавливать jq.
APP=$(curl -s -XPOST $API/v1/apps -H "$AUTH" \
-H 'content-type: application/json' \
-d '{"name":"todo","runtime_preset":"react-vite"}' \
| sed -E 's/.*"id":"([^"]+)".*/\1/')
SB=$(curl -s -XPOST $API/v1/apps/$APP/sandbox -H "$AUTH" \
-H 'content-type: application/json' -d '{"ports":[3000]}' \
| sed -E 's/.*"id":"([^"]+)".*/\1/')
echo "app=$APP sandbox=$SB"Обе переменные должны содержать идентификатор. Пустое значение $SB означает, что изолированная среда не была запущена; обычно это происходит из-за того, что базовый образ всё ещё собирается или на хосте закончилась оперативная память. Значение 401 вместо идентификатора означает, что bearer token указан неверно.
curl -s -XPOST $API/v1/sandboxes/$SB/tasks -H "$AUTH" \
-H 'content-type: application/json' \
-d '{"prompt":"Add a todo list with a text input, an add button, and a delete button on each row. Keep the list in localStorage.","agent":"opencode"}'Ответ содержит идентификатор задачи. GET /v1/sandboxes/$SB/tasks/<task id> возвращает результат выполнения, а путь /events для той же задачи предоставляет поток SSE (server sent events) в реальном времени, отображающий действия агента. Консоль выводит тот же поток в виде чата.
Приложение становится доступным по адресу http://s-<sandbox id>-3000.preview.localhost, где 3000 — это порт, который вы запросили. Если изолированная среда находилась в спящем режиме, первый запрос попадает на catch-all в Traefik, sandboxd запускает контейнер, ожидает ответа от порта и выдаёт короткую страницу прогрева, которая автоматически обновляется до вашего приложения. Если страница предварительного просмотра не обновляется, это означает, что процесс внутри контейнера не слушает порт, указанный в sandbox.yaml приложения.
Размещение превью на реальном домене с HTTPS
Каждый песочница получает собственное имя хоста, поэтому одна wildcard DNS-запись покрывает их все. Укажите *.preview.yourdomain.com на IP-адрес сервера с помощью A-записи. Затем задайте переменные превью в .env в файле ~/.sandboxd/src:
PREVIEW_DOMAIN=yourdomain.com
PREVIEW_ENTRYPOINT=websecure
PREVIEW_TLS=true
SANDBOXD_API_AUTH_DISABLED=falseTraefik требует соответствующей настройки: включите точку входа websecure в traefik/traefik.yml и добавьте резолвер сертификатов. Используйте DNS-01 challenge, так как один wildcard-сертификат покроет все имена хостов для превью. При использовании HTTP-01 для каждой новой песочницы потребовался бы отдельный выпуск сертификата, и активная работа по сборке привела бы к достижению лимитов Let's Encrypt. В Wildcard certificates through the DNS-01 challenge описана настройка DNS для этого случая.
cd ~/.sandboxd/src
docker compose up -dURL-адреса превью примут вид https://s-<id>-3000.preview.yourdomain.com. Откройте порты 80 и 443 на межсетевом экране, а порт 9090 оставьте закрытым для внешнего доступа: см. basic ufw firewall rules. Помните, что любой, кто сможет угадать имя хоста превью, сможет загрузить приложение, поэтому относитесь к превью как к публичным ресурсам.
Если вы предпочитаете полностью отказаться от настройки домена, DNS и сертификатов, разработчики теперь предлагают сервис sandboxd Cloud. Он предоставляет вашему серверу публичный HTTPS-адрес в домене sandboxd.io по цене 9.99 долларов за сервер в месяц или 4.99 с учетом стартовой скидки (по состоянию на октябрь 2026 года). Проверьте, какая версия релиза требуется для работы с ним, прежде чем фиксировать версию v0.3.6.
Где сохраняется сгенерированный код и можно ли его экспортировать?
На хосте, внутри каталога данных. Каждое рабочее пространство представляет собой обычный каталог по пути /var/lib/sandboxed/workspaces/<id>/ в версии v0.3.6, который монтируется в контейнер, а файлы приложения находятся в /home/sandbox/workspace/app внутри песочницы. Состояние панели управления хранится в одном файле SQLite по пути state/sandboxd.db, а зашифрованные учетные данные агента — в agent-auth/. Никакие данные не скрыты внутри слоев контейнера, поэтому для резервного копирования достаточно скопировать каталог и файл базы данных. резервное копирование restic на VPS позволяет выполнять обе задачи.
sudo ls /var/lib/sandboxed/workspaces
sudo du -sh /var/lib/sandboxed/workspaces/*Экспорт в Git является встроенной функцией, а не внешним дополнением. API предоставляет статус и diff для чтения, а также команды commit и push:
curl -s $API/v1/apps/$APP/git/status -H "$AUTH"
curl -s -XPOST $API/v1/apps/$APP/git/commit -H "$AUTH" \
-H 'content-type: application/json' \
-d '{"message":"todo list, first pass"}'
curl -s -XPOST $API/v1/apps/$APP/git/push -H "$AUTH" \
-H 'content-type: application/json' -d '{"branch":"todo-first-pass"}'Команда push всегда отправляет изменения в новую ветку. Если не указывать branch, по умолчанию используется sandboxd/<slug>-<shortsha>. Операции с main, master и веткой, из которой был выполнен импорт, отклоняются, поэтому слияние необходимо выполнять на стороне удаленного репозитория.
Для работы с приватным удаленным репозиторием требуется персональный токен доступа (personal access token), который настраивается один раз в консоли в разделе Settings, Git credentials. Он хранится в зашифрованном виде вне песочницы, поэтому агент не может прочитать его или выполнить push без вашего ведома. Выполняйте push часто и на ранних этапах. Пока вы этого не сделали, каталог рабочего пространства является единственной копией кода, а команда DELETE /v1/apps/<id> удаляет его без возможности восстановления.
Во сколько обходится сборка в токенах модели?
sandboxd не отслеживает ваши расходы, поэтому итоговые цифры доступны только в консоли вашего провайдера. Бесплатные модели OpenCode Zen не требуют оплаты, но они медленнее и слабее платных моделей, что приводит к большему количеству итераций исправления для любых задач сложнее учебных приложений.
Структура счета зависит от принципа работы цикла агента. Каждый шаг отправляет необходимый контекст заново, поэтому стоимость зависит от количества итераций, а не от количества приложений. Один успешный промпт стоит недорого. Пятнадцать итераций запроса «исправь отступы» для проекта из пятидесяти файлов обойдутся дорого, так как содержимое файлов передается каждый раз. Входящие и исходящие токены тарифицируются по-разному, а в статье сколько стоит сессия агента для написания кода приведены реалистичные диапазоны цен. Установите жесткий лимит расходов у провайдера, прежде чем запускать цикл без присмотра.
Очистка неактивных песочниц
Idle reaper останавливает любую песочницу, которая простаивает дольше SANDBOXD_IDLE_THRESHOLD_SECONDS, значение по умолчанию составляет 2100 секунд, или 35 минут. Это освобождает оперативную память и сохраняет файлы, а следующий запрос к URL предварительного просмотра запускает контейнер. Уменьшите это значение на сервере с ограниченными ресурсами, так как 35 минут простоя контейнеров — это 35 минут памяти, которую вы не можете использовать.
Остановка не означает удаление, именно поэтому диски постепенно заполняются. Остановленная песочница по-прежнему владеет своим рабочим пространством и контейнером. Удаление песочницы при сохранении приложения — это DELETE для песочницы, что удаляет контейнер и рабочее пространство вместе с ней. Удаление приложения удаляет всё без возможности восстановления.
curl -s -XPOST $API/v1/sandboxes/$SB/stop -H "$AUTH" # frees RAM, keeps files
curl -s -XDELETE $API/v1/sandboxes/$SB -H "$AUTH" # container and workspace gone
curl -s -XDELETE $API/v1/apps/$APP -H "$AUTH" # app and everything under itЧерез несколько недель экспериментов docker system df покажет больше места, которое можно освободить, чем вы ожидаете, так как каждое приложение, загрузившее собственный набор инструментов, оставило после себя слои. docker image prune очищает «висячие» (dangling) слои. Сначала проверьте GET /v1/apps, так как образ, на который всё ещё ссылается спящая песочница, не является мусором.
Что дает и чего не дает граница контейнера
Каждая «песочница» запускается от имени непривилегированного пользователя с файловой системой root в режиме «только чтение», с отключенными возможностями Linux (capabilities), установленным no-new-privileges, ограничением по памяти и лимитом на количество процессов. Проект открыто заявляет об ограничениях такого подхода: контейнер Linux с общим ядром — это надежная граница изоляции, но слабая граница безопасности. Ошибка в ядре означает компрометацию хоста.
Два факта требуют принятия мер. Исходящий сетевой трафик из «песочницы» в self-hosted сборке разрешен, поэтому сгенерированный код может обращаться к интернету, вашей локальной сети и конечным точкам метаданных облачных провайдеров. Подсистема исходящего трафика на базе nftables присутствует в исходном коде, но отключена при компиляции в переносимой сборке Docker Compose, а это значит, что ограничения должны накладываться на уровне межсетевого экрана хоста. Кроме того, API плоскости управления (control plane) фактически обладает правами root на хосте, так как управляет Docker socket. По умолчанию он привязывается к 127.0.0.1:9090, параметр SANDBOXD_API_AUTH_DISABLED должен оставаться false, и его ни в коем случае нельзя публиковать в интернет.
Если вы планируете позволить другим пользователям отправлять запросы (промпты) в вашу среду, этой модели защиты недостаточно. Проект рекомендует использовать gVisor с SANDBOXD_RUNTIME=runsc, который помещает ядро в пространстве пользователя между «песочницей» и хостом. Согласно собственным замерам проекта, это замедляет установку пакетов примерно в 1.7 раза, а задачи с интенсивным использованием системных вызовов — примерно в 4 раза. Более надежное решение — выделение отдельной машины на каждого пользователя; это тот же аргумент, что и в пользу запуска агентов для программирования в одноразовых VM.
Стоит ли использовать проект двухмесячной давности?
Для личного сервера сборки — да, при соблюдении очевидных мер предосторожности: зафиксируйте версию SANDBOXD_REF, создайте резервную копию каталога данных (/var/lib/sandboxed в версии v0.3.6, /var/lib/sandboxd при чистой установке v0.3.9 или новее) и отправляйте все важные приложения в удаленный git-репозиторий. Если проект предназначен для клиентов, дождитесь версии 1.0 или заложите бюджет на возможные поломки, так как разработчики прямо предупреждают, что версии 0.x могут измениться в любой момент. Разработчики также предлагают управляемую установку: 199 долларов за настройку и 79 долларов в месяц за поддержку по состоянию на октябрь 2026 года. Эту информацию стоит учитывать при оценке перспективности проекта.
Риск оправдан результатом работы. sandboxd создает обычное приложение в обычном git-репозитории, поэтому, если развитие проекта остановится, вы сохраните код и потеряете только оболочку. Это гораздо более выгодная позиция, чем использование облачного конструктора, который владеет вашим проектом. Чтобы узнать больше о том, что стоит размещать на своем сервере в этом году, см. что стоит хостить самостоятельно в 2026 году.
FAQ
Каковы минимальные системные требования для sandboxd?
Проект указывает, что для запуска достаточно 2 vCPU и 4 ГБ оперативной памяти; этого хватит для control plane, Traefik и одной небольшой «песочницы» (sandbox). Используйте 8 ГБ ОЗУ и 40 ГБ дискового пространства, если планируете запускать несколько приложений одновременно, так как каждая активная «песочница» содержит полный набор инструментов Node или Python, а каждое рабочее пространство хранит собственное дерево зависимостей на диске. При нехватке ресурсов на хосте механизм pressure reaper в sandboxd останавливает «песочницы» для освобождения памяти, а сборка, превышающая лимит памяти контейнера, принудительно завершается ядром: docker ps -a показывает для таких случаев код завершения 137.
Чем sandboxd отличается от Dify или OpenHands?
Они создают разные артефакты. Dify строит приложения, которые обращаются к модели во время выполнения, например, чат-интерфейсы или конвейеры поиска (retrieval pipelines). OpenHands редактирует уже существующий репозиторий, выполняя команды и предлагая изменения в коде. sandboxd создает новый проект с нуля на основе промпта, собирает его внутри собственного контейнера и предоставляет URL для предварительного просмотра; результат — обычное веб-приложение, которому не требуется модель для работы.
Где физически находится код, написанный агентом?
В файловой системе хоста, а не внутри образа контейнера. Каждое приложение получает каталог по пути /var/lib/sandboxed/workspaces/<id>/ в версии v0.3.6 (/var/lib/sandboxd/workspaces/<id>/ при чистой установке версии v0.3.9 или новее), который монтируется (bind mount) в «песочницу», где файлы становятся доступны по пути /home/sandbox/workspace/app. Состояние control plane хранится в одном файле SQLite по пути state/ в той же директории данных. Вы можете выполнить commit и push в новую ветку удаленного git-репозитория через вкладку Git в консоли или через эндпоинты /v1/apps/<id>/git/commit и /git/push. Токен для доступа к приватным репозиториям хранится в зашифрованном виде на стороне control plane и не передается в «песочницу».
Безопасно ли открывать доступ к sandboxd из Интернета?
Открывайте доступ к URL для предварительного просмотра и к консоли, но никогда — к API control plane. Этот API управляет Docker на хосте, поэтому его права эквивалентны правам root, и по этой причине он по умолчанию привязан к 127.0.0.1:9090. В self-hosted сборке «песочницы» также имеют открытый исходящий сетевой доступ, что означает, что код, написанный агентом, может достичь вашей локальной сети и эндпоинтов метаданных облачных провайдеров. Настройте правила межсетевого экрана на хосте, если в сети есть другие узлы, требующие защиты. Если вы работаете с промптами от пользователей, которым не доверяете, запускайте по одному хосту на каждого клиента, не полагаясь только на изоляцию контейнеров.