SSD Nodes Learn 🎉 VPS от $5.50/мес
Руководства Matt ConnorАвтор: Matt Connor

Как разместить Dormice для sandbox агентов на VPS

Установите Dormice на свой Linux VPS, запускайте код через E2B-совместимый API, проверьте изоляцию sandbox и рассчитайте требования к хосту.

Что такое Dormice и чем он не является

Dormice — это самостоятельно размещаемая среда для запуска агентов: один daemon на принадлежащем вам Linux VPS. Код агента обращается к daemon по HTTP, чтобы выполнять непроверенный код внутри изолированного контейнера. Программа запрашивает sandbox по имени, получает тот же sandbox независимо от его состояния, выполняет в нём команду и читает результат. Sandbox — это программный ресурс, а не машина, к которой вы подключаетесь.

Это не то же самое, что предоставить агенту целый компьютер. Временная VM для агента, который пишет код — это система, к которой вы подключаетесь по SSH, позволяете агенту изменить её, а затем удаляете. Dormice находится уровнем ниже: это API выполнения, к которому обращается программа, когда у неё уже есть код и нужно безопасное место для его запуска. Используйте временную VM, если единицей работы является целая машина. Используйте Dormice, если единицей работы является один вызов exec и вам нужно выполнять сто таких вызовов в день без создания ста VM.

Проект заявляет о совместимости с E2B. E2B — это размещаемый сервис sandbox, клиентскую библиотеку которого уже импортируют многие платформы для агентов. Dormice предоставляет тот же протокол по собственным префиксам URL. Поэтому приложение, написанное с использованием официального пакета e2b, продолжит работать после перенаправления запросов на ваш сервер. Код приложения менять не нужно. Изменяются два URL и один префикс API key.

Что на практике означает «SQLite для изолированных сред агентов»

SQLite — это база данных, которую встраивают в приложение, а не отдельный сервис, которым нужно управлять. Dormice напрямую использует это сравнение. Один daemon, один файл SQLite для журнала состояния и один TCP-порт. Kubernetes, отдельная база данных и scheduler не нужны. Daemon блокирует файл рядом со своим журналом состояния и отказывается запускаться, если журнал и обнаруженная им машина не могут относиться к одной системе. Поэтому split brain не возникает незаметно. Архитектура рассчитана на одну машину. Если вам нужен fleet на нескольких хостах, README прямо рекомендует выбрать другое решение. К этому совету следует прислушаться.

Вторая часть идеи связана со стоимостью. Hosted sandbox оплачивается за каждую секунду существования, поэтому hosted sandboxes изначально рассчитаны на удаление. Dormice работает на оборудовании, за которое вы уже платите. Поэтому его sandboxes могут существовать постоянно, а их стоимость снижается по мере простоя. Sandbox поэтапно переходит в неактивное состояние: active, затем frozen, затем stopped, затем archived. Любой acquire возвращает его из достигнутого состояния.

Наиболее важен механизм freezing. Именно он делает постоянное хранение sandbox для каждого агента доступным по цене. Ниже приведены опубликованные авторами проекта показатели. Они измерены на их оборудовании, а не на вашем.

ChartOne idle sandbox before and after freezing, figures published by the project
The data behind this chart
[
  {
    "label": "Active, holding 1 GiB",
    "resident_memory_mib": 1024,
    "wake_ms": 0
  },
  {
    "label": "Frozen",
    "resident_memory_mib": 5,
    "wake_ms": 50
  }
]

Неактивный sandbox, занимающий 1024 MiB памяти, после freezing занимает 5 MiB resident memory и возвращается в рабочее состояние примерно за 50 ms. Процессы приостанавливаются и возобновляются на месте. Поэтому долгоживущий агент сохраняет состояние shell и незавершённую работу после freezing. Перед планированием capacity воспроизведите этот сценарий на собственном хосте.

Что требуется на хосте до установки

На хосте должна быть установлена Ubuntu или Debian для x86_64, а установщику требуются права root. Демон работает от имени root, поскольку выполняет loop mounts и записывает данные в cgroups.

Песочницы запускаются в Docker с gVisor — средой выполнения контейнеров, которая размещает ядро пользовательского пространства между контейнером и ядром хоста. Она предоставляет среду выполнения runsc, которую использует каждая песочница. Демон работает на Node 22 или более новой версии. Установщик устанавливает собственную копию Node, поэтому системная версия Node не изменяется.

В системе должен быть настроен swap, а значение vm.swappiness должно быть равно 100. Это не рекомендация по настройке, а обязательное функциональное требование. При заморозке память неактивной песочницы перемещается в swap. gVisor хранит память песочницы как shared memory, а ядро при стандартном значении swappiness не перемещает shared memory в swap. Проект измерил, что при стандартном значении освобождается 0 байт, а при значении 100 — 99.5 процента памяти. Проверьте фактическое значение, которое использует ядро: некоторые cloud images задают vm.swappiness = 0 в файле, который обычно не приходит в голову проверять.

sysctl vm.swappiness
swapon --show

Команда sysctl vm.swappiness должна вывести vm.swappiness = 100, а команда swapon --show — показать swapfile. Если swappiness имеет значение 0, каждая операция заморозки ничего не делает, и за каждую неактивную песочницу приходится платить полной стоимостью занимаемой ею памяти.

Установка Dormice в Ubuntu

Документированный способ установки выполняется одной командой через pipe в bash:

curl -fsSL https://raw.githubusercontent.com/BitMiracle-AI/Dormice/main/deploy/install.sh | bash

Сначала загрузите этот скрипт и прочитайте его. Не запускайте его сразу. Скрипт выполняется от имени root и изменяет конфигурацию хоста: устанавливает Docker, если он отсутствует, загружает gVisor и Caddy с проверкой контрольных сумм, создаёт swapfile, записывает systemd units и добавляет правила firewall.

curl -fsSL https://raw.githubusercontent.com/BitMiracle-AI/Dormice/main/deploy/install.sh -o dormice-install.sh
less dormice-install.sh
sudo bash dormice-install.sh --swap-gb 8

Параметр --swap-gb задаёт размер swapfile. По умолчанию используется значение 16, а для небольшого VPS это слишком большой объём диска. Параметр --mirror cn переключает загрузку на зеркала, доступные из материкового Китая. Повторный запуск установщика обновляет код и исправляет расхождения в конфигурации. API token при этом не меняется.

Код устанавливается в /opt/dormice, конфигурация хранится в /etc/dormice/env, данные sandbox — в /var/lib/dormice, а команды dormice и dor — в /usr/local/bin. Установщик создаёт API token во время установки и записывает его в /etc/dormice/env с mode 600.

У проекта нет помеченного релиза, на который можно установить систему. По состоянию на 4 August 2026 в repository нет git tags и GitHub releases. Поэтому установщик клонирует main, и вы получаете состояние кода, добавленное в repository этим утром. Чтобы зафиксировать версию, запишите commit, который был фактически установлен.

git -C /opt/dormice rev-parse HEAD

Сохраните этот hash вместе с заметками о развёртывании. Если обновление что-либо сломает, этот commit будет единственным способом вернуться к рабочему состоянию, поскольку номера версии нет.

В конце установщик запускает dor doctor. Это проверка хоста только для чтения. Она запускает реальные gVisor containers и проверяет работоспособность runtime, а не просто наличие пакетов. Запускайте её повторно при каждом нестабильном поведении daemon.

sudo dor doctor
systemctl is-active dormice

Команда systemctl is-active dormice должна вывести active. Если она выводит failed, причина указана в journalctl -u dormice -n 50. Обычно неудачный запуск связан с prerequisite для swap или gVisor, а не с самим daemon.

Установщик также устанавливает Caddy на сервер. Поэтому перед завершением настройки firewall проверьте, какие сервисы слушают порты.

sudo ss -lntp

Daemon привязывается к 127.0.0.1:3676. Настройки для изменения этого адреса нет, и это сделано намеренно. Доступ к daemon с вашего laptop нужно разрешить отдельно. Самый простой вариант — SSH tunnel.

ssh -L 3676:127.0.0.1:3676 root@your-server

После открытия tunnel адрес http://127.0.0.1:3676/console на вашем laptop открывает web console. Один раз войдите с помощью token. После этого он преобразуется в httpOnly session cookie, поэтому сам token не сохраняется там, где его может прочитать страница. На странице Connect отображаются готовые client snippets для копирования и вставки, уже настроенные на ваш endpoint.

Создайте sandbox и выполняйте в нём код

Одна операция создаёт sandbox: acquire. Она идемпотентна, поэтому один и тот же ключ всегда возвращает один и тот же sandbox, при необходимости создавая, пробуждая, запуская его или восстанавливая. Любой другой verb возвращает 404 для ключа, который ещё не использовался. В CLI dor нет acquire verb, поэтому первый sandbox нужно создать через консоль или клиентскую библиотеку.

Самый быстрый способ — через консоль. Откройте /console через tunnel и создайте sandbox с именем my-agent. После этого CLI будет работать с ним.

sudo grep DORMICE_API_TOKEN /etc/dormice/env
export DORMICE_ENDPOINT=http://127.0.0.1:3676
export DORMICE_API_TOKEN=paste-the-value-here
dor sandbox ls
dor sandbox exec my-agent 'python3 --version'

Команда dor sandbox ls выводит список sandbox и их состояния жизненного цикла. Так можно отслеживать переход sandbox из active в frozen. Команда dor sandbox exec выводит версию Python 3.12, поскольку в стандартном образе Ubuntu 24.04 уже установлены Python 3.12, Node 24, git и ripgrep. Ошибка аутентификации означает, что в скопированной строке с token также оказалось имя переменной.

Файлы передаются с помощью dor sandbox push my-agent ./script.py, при этом файл сохраняется в /home/user/script.py, а команда dor sandbox pull my-agent notes.txt загружает его обратно. Ограничение native file verbs составляет 16 MiB на файл. При работе через E2B file surface данные передаются потоком, поэтому единственным ограничением становится disk quota sandbox.

Только verb уничтожения приводит к потере данных. Это также показательный пример того, как проект развивался: основной README и встроенный agent skill документируют dor sandbox destroy <key>, а README пакета CLI документирует dor sandbox release <key>. В собственной сборке выполните dor sandbox --help и ориентируйтесь на его результат.

Подключите существующий код E2B к собственному серверу

В этом и заключается практическая ценность. Официальный пакет e2b из npm без изменений обращается к Dormice. Запустите этот код на своём ноутбуке при открытом SSH-туннеле. Поэтому на сервере не будет открыто ничего нового.

npm init -y
npm i e2b tsx
import { Sandbox } from 'e2b';

const sbx = await Sandbox.create({
  apiKey: `e2b_${process.env.DORMICE_API_TOKEN}`,
  apiUrl: 'http://127.0.0.1:3676/e2b/api',
  sandboxUrl: 'http://127.0.0.1:3676/e2b/envd',
});

const result = await sbx.commands.run('python3 -c "print(6 * 7)"');
console.log(result.exitCode, result.stdout);

await sbx.kill();
DORMICE_API_TOKEN=paste-the-value-here npx tsx index.ts

При успешном выполнении выводятся код завершения 0 и 42. В качестве API key используется ваш токен Dormice с префиксом e2b_. Именно такой формат ожидает слой совместимости.

Это не заглушка. Официальный пакет проверяет потоковую передачу stdout и stderr, фоновые команды, интерактивный PTY, подписанные URL для загрузки и скачивания, мониторинг каталогов и прокси порта. Проверки выполняются в отношении реальных daemon Docker и gVisor в составе end-to-end suite проекта. Перед миграцией рабочих систем учтите несколько отличий:

  • Сборка template не реализована. Template — это docker image, который вы самостоятельно собираете и регистрируете с помощью dor template add. Затем Sandbox.create('name') разрешает его имя. Для незарегистрированного имени возвращается ошибка 404, а не создаётся фиктивный объект.
  • Для sandbox, созданных через интерфейс E2B, действуют реальные deadlines, поскольку этого требует семантика E2B. Для sandbox, созданных через native API, deadlines никогда не устанавливаются.
  • При заморозке sandbox его процессы сохраняются и продолжают выполнение после возобновления. Поэтому pause и resume здесь не означают остановку и последующий полный запуск, как это может быть в других системах.

Что sandbox блокирует, а что — нет

gVisor перехватывает системные вызовы контейнера в userspace и обрабатывает их самостоятельно. Поэтому код в sandbox не обращается напрямую к kernel хоста. Внутри sandbox всё выполняется от имени непривилегированного пользователя с uid 1000. Такая комбинация закрывает обычные сценарии: сгенерированный скрипт, который запускает rm -rf /, заполняет диск или создаёт процессы до сбоя, повреждает только собственный sandbox и останавливается на этом.

Ниже перечислено то, что sandbox не блокирует. За это отвечаете вы.

  • У sandbox есть рабочий исходящий network. Сгенерированный код может скачать всё, что ему нужно, и отправить наружу найденные данные. Установщик настраивает защиту network в двух конкретных случаях: он блокирует трафик контейнера к cloud metadata service в диапазоне 169.254.0.0/16, через который cloud передаёт credentials инстанса любому объекту с доступом к этому адресу, и отключает трафик между контейнерами с помощью "icc": false в daemon.json Docker. Больше ничего не блокируется. Прочитайте sudo iptables -S DOCKER-USER и добавьте собственные правила DROP для private ranges, к которым sandbox не должен обращаться.
  • Docker добавляет собственные правила раньше правил вашего firewall. Поэтому опубликованный порт контейнера может отвечать из Интернета, даже если ufw считает его закрытым. Перед публикацией чего-либо на этом host прочитайте как Docker публикует порты в обход ufw и основы firewall ufw для VPS.
  • gVisor — это kernel в userspace, а не hypervisor. Это осознанный компромисс. Для freeze sandbox должны быть процессами, а требование KVM не позволило бы устанавливать систему где угодно. Если ваша модель угроз требует hardware virtualisation, используйте изоляцию уровня Firecracker и примите связанные с этим эксплуатационные затраты.
  • API token — это вся граница безопасности на стороне клиента. Любой, у кого есть DORMICE_API_TOKEN, может создавать, читать и уничтожать любой sandbox на машине. Запускайте agent process от имени отдельного пользователя с минимальными привилегиями на VPS и обращайтесь с token так же, как с SSH key. Рекомендации из материала безопасный запуск Claude Code на VPS применимы напрямую.

Сам daemon работает на host от имени root. gVisor защищает host от кода внутри sandbox, но ничто не защищает host от daemon или владельца его token. Поэтому машина, на которой работает Dormice, должна использоваться только для этой задачи. Если ваш agent также обращается к инструментам через MCP (model context protocol), по той же причине разместите эти MCP servers на отдельном VPS.

Сколько песочниц помещается в 4 GB и 8 GB?

Память расходуется по двум направлениям: базовая нагрузка самого хоста и рабочий набор каждой песочницы, которая сейчас активна. Выделите около 1 GB на Ubuntu, Docker и daemon, а оставшийся объём разделите на фактическое потребление одной песочницы. Песочница, в которой выполняется Python-скрипт и читается несколько файлов, обычно использует от 200 до 300 MiB. Песочница с компилятором или полным набором тестов может потреблять больше 1 GiB.

ChartConcurrent sandboxes by host RAM, arithmetic after a 1 GB host reserve
The data behind this chart
[
  {
    "host": "4 GB VPS",
    "active_at_512_mib": 6,
    "active_at_1_gib": 3,
    "frozen_on_16gb_swap": 16
  },
  {
    "host": "8 GB VPS",
    "active_at_512_mib": 14,
    "active_at_1_gib": 7,
    "frozen_on_16gb_swap": 16
  }
]

VPS с 4 GB одновременно поддерживает около 6 активных песочниц, если каждая использует 512 MiB, или 3, если каждая использует полный gibibyte. Для VPS с 8 GB эти значения составляют 14 и 7. Это предельные значения для параллельной работы, а не результаты тестирования производительности. Поэтому отслеживайте free -m во время работы собственной нагрузки.

Для замороженных песочниц ограничивающим ресурсом становится swap, а не RAM. В этом и состоит основной принцип такой схемы. Если замороженная песочница занимала 1 GiB, примерно такой же объём сохраняется в swap, тогда как в RAM она почти ничего не занимает. Поэтому swapfile размером 16 GB, который создаётся установщиком по умолчанию, позволяет разместить около 16 таких песочниц. После этого их нужно перевести на остановленный уровень, где они будут занимать только место на диске. В долгосрочной перспективе именно диск становится основным ограничением: каждая песочница сохраняет свою файловую систему, и несколько десятков агентов, каждый со своей директорией node_modules, заполнят небольшой том задолго до того, как потребление памяти станет проблемой.

Заморозка, остановка, архивирование: параметры жизненного цикла

По умолчанию окружение замораживается после 10 минут бездействия, останавливается после 3 дней, а через 7 дней архивируется, если архивирование настроено. Если задать stopAfterSeconds как null, агент будет постоянно доступен: при бездействии он может заморозиться, но холодный запуск никогда не выполняется.

Архивирование необязательно, и демон явно сообщает о его состоянии. Задайте четыре переменные DORMICE_S3_* — тогда диск остановленной песочницы упаковывается с помощью tar и zstd, передаётся в любой совместимый с S3 bucket и освобождается локально. Это может быть bucket MinIO, размещённый вами самостоятельно на другом вашем компьютере. Если оставить переменные незаданными, песочницы навсегда остаются в состоянии stopped, а политика, требующая архивирования, отклоняется, а не игнорируется без уведомления. Восстановление также отображается явно: следующий запрос acquire сразу возвращает статус restoring и значение прогресса, а после восстановления диска статус меняется на ready.

Стоит ли уже от него зависеть?

Прямой ответ: нет, если вы не можете пересобрать систему. Первый коммит в репозитории датирован 8 July 2026. По состоянию на 4 August 2026 у проекта 446 звёзд, 37 forks, лицензия Apache-2.0 и вообще нет tagged release. В собственной строке статуса README указано, что проект ещё не готов к эксплуатации в production.

Такое сочетание создаёт вполне определённые риски. Код может измениться в любой момент, потому что installer отслеживает main. Интерфейс ещё формируется. Именно поэтому verb для удаления имеет два разных имени в двух файлах одного репозитория. Проекту всего четыре недели, и он может просто прекратить работу: ни один пункт лицензии не обязывает разработчиков продолжать его поддержку.

Риск можно контролировать благодаря совместимости с E2B. Ваше приложение взаимодействует с протоколом, для которого есть hosted implementation. Поэтому, если Dormice остановит разработку, достаточно изменить два URL. Используйте в agent интерфейс E2B, а не native API. Тогда у вас сохранится этот вариант перехода. Пакет native @dormice/sdk ещё не опубликован в npm. Для его использования потребуется собрать пакет из репозитория. Это ещё одна причина начать с совместимого варианта.

Запускайте систему там, где вы можете позволить себе её потерять. Пересобирайте host из script. Не сохраняйте token ни в одной prompt и ни в одном commit. Всё, что нужно сохранить, извлекайте из sandboxes по собственному расписанию резервного копирования.

FAQ

Готов ли Dormice для использования в production?

Нет, и проект прямо об этом сообщает. В строке статуса README указано, что пока ничего не готово для использования в production. По состоянию на 4 августа 2026 года репозиторию около 4 недель, в нём нет git-тегов и releases, поэтому фиксировать номер версии нельзя. Installer клонирует ветку main, поэтому каждый запуск получает последний commit. После каждой установки записывайте git -C /opt/dormice rev-parse HEAD и храните все ценные данные вне sandbox.

Чем Dormice отличается от выдачи агенту временной VM?

Disposable VM — это машина с SSH, которую вы создаёте на время сессии, а затем удаляете. Dormice — это execution API: программа вызывает acquire, затем exec и получает stdout и exit code без промежуточной shell-сессии. VM подходит человеку или агенту, которому на некоторое время нужен полноценный компьютер. Dormice подходит приложению, которое запускает сгенерированный код много раз в день и не хочет каждый раз выполнять настройку и удаление ресурсов целой машины.

Действительно ли официальный E2B SDK работает без изменений в коде?

Да, но потребуются изменения конфигурации. Укажите /e2b/api и /e2b/envd в качестве значений apiUrl и sandboxUrl на daemon и передайте токен Dormice с префиксом e2b_ в качестве API key. Выполнение команд, PTY-сессии, передача файлов, signed URLs и port proxy поддерживаются end-to-end suite проекта, которая запускается через официальный package. Существенное ограничение — сборка шаблонов: e2b template build не реализован, поэтому template представляет собой docker image, который вы собираете и регистрируете с помощью dor template add.

Сколько sandbox поместится на VPS с 4 GB?

Около 6 одновременно активных sandbox, если каждый использует 512 MiB, или 3, если каждый использует полный gibibyte. При этом примерно 1 GB нужно зарезервировать для операционной системы, Docker и daemon. Frozen sandbox ограничены объёмом swap. Поэтому swapfile размером 16 GB, заданный installer по умолчанию, позволяет приостановить около 16 sandbox, каждый из которых ранее использовал gibibyte. Измерьте показатели в своей среде с помощью free -m при реальной нагрузке. Sandbox, выполняющий test suite, использует в несколько раз больше памяти, чем sandbox, запускающий небольшой script.

Почему для Dormice нужно установить vm.swappiness в 100?

При заморозке sandbox его неиспользуемая память выгружается в swap. gVisor хранит память sandbox как shared memory, а Linux kernel не выгружает shared memory в swap при стандартном значении swappiness. Поэтому при стандартном значении заморозка ничего не освобождает, и sandbox продолжает занимать полный объём памяти. Проект измерил освобождение 0 bytes при стандартном значении и 99.5 percent при значении 100. Проверьте действующее значение с помощью sysctl vm.swappiness, а не чтением конфигурационных файлов, поскольку некоторые cloud images устанавливают значение 0.