Як розгорнути Dormice для пісочниць агентів
Запустіть E2B-сумісні пісочниці Dormice на власному Linux VPS: встановіть daemon, виконайте код, перевірте ізоляцію та оцініть ресурси хоста.
Що таке Dormice і чим він не є
Dormice — це self-hosted пісочниця для агентів: один daemon на вашому Linux VPS, до якого код агента звертається через HTTP, щоб виконати недовірений код в ізольованому контейнері. Програма запитує пісочницю за іменем, отримує ту саму пісочницю незалежно від її попереднього стану, виконує в ній команду та читає вивід. Пісочниця є програмним ресурсом, а не машиною, до якої потрібно входити.
Це інша модель, ніж надання агенту цілого комп’ютера. Тимчасова VM для агента кодування — це система, до якої ви підключаєтеся через SSH, дозволяєте агенту змінювати або пошкоджувати її, а потім видаляєте. Dormice працює рівнем нижче: це API виконання, до якого звертається ваша програма, коли код уже є і для нього потрібне безпечне середовище виконання. Використовуйте тимчасову VM, коли одиницею роботи є ціла машина. Використовуйте Dormice, коли одиницею роботи є один виклик exec і вам потрібно виконувати сотню таких викликів на день без створення сотні VM.
Проєкт називає себе сумісним з E2B. E2B — це hosted-сервіс пісочниць, клієнтську бібліотеку якого вже імпортують багато фреймворків для агентів. Dormice підтримує той самий протокол за власними префіксами URL, тому застосунок, написаний для офіційного пакета e2b, продовжує працювати після перенаправлення його на ваш власний сервер. Код застосунку змінювати не потрібно. Змінюються два URL і один префікс API key.
Що на практиці означає «SQLite для пісочниць агентів»
SQLite — це база даних, яку вбудовують у застосунок, а не окремий сервіс, яким потрібно керувати. Dormice безпосередньо використовує це порівняння. Один daemon, один файл SQLite для ledger і один TCP-порт. Без Kubernetes, окремої бази даних і scheduler. daemon створює lock поруч із ledger і відмовляється запускатися, якщо ledger і знайдена ним машина не можуть належати одній системі. Тому split brain не виникає непомітно. Архітектура розрахована на одну машину. Якщо вам потрібен fleet на багатьох hosts, README прямо радить вибрати інше рішення. До цієї поради варто дослухатися.
Друга частина ідеї стосується вартості. Hosted sandbox оплачується за кожну секунду існування, тому hosted sandboxes за задумом призначені для одноразового використання. Dormice працює на hardware, за яке ви вже платите, тому його sandboxes є постійними, а їхня вартість зменшується, якщо вони довше залишаються без активності. Sandbox поступово переходить між станами: active, потім frozen, потім stopped і нарешті archived. Будь-який acquire повертає його зі стану, якого він досяг.
Найважливіше зрозуміти freeze, оскільки саме він робить постійне зберігання sandbox кожного agent доступним за ціною. Нижче наведено власні опубліковані показники проєкту, виміряні на його hardware, а не на вашому.
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
}
]Idle sandbox, який використовує 1024 MiB пам’яті, після freeze займає 5 MiB resident memory і повертається до роботи приблизно за 50 ms. Процеси призупиняються та відновлюються на тому самому місці, тому довготривалий agent зберігає стан shell і незавершену роботу після freeze. Відтворіть це на власному host, перш ніж планувати capacity на підставі цих показників.
Що потрібно хосту перед інсталяцією
Хост має працювати під Ubuntu або Debian на x86_64, а інсталятору потрібні права root. Демон працює від імені root, оскільки виконує loop mounts і записує дані до cgroups.
Пісочниці працюють у Docker з gVisor — середовищем виконання контейнерів, яке розміщує kernel userspace між контейнером і kernel хоста. Воно надає runtime runsc, який використовує кожна пісочниця. Демон працює на Node 22 або новішій версії. Інсталятор постачає власну копію, тому системний Node залишається без змін.
Має бути налаштовано swap, а значення vm.swappiness має дорівнювати 100. Це не рекомендація з оптимізації, а функціональна вимога. Під час заморожування пам’ять неактивної пісочниці переміщується до swap. gVisor зберігає пам’ять пісочниці як shared memory, а kernel не переміщує shared memory до swap за стандартного значення swappiness. Проєкт виміряв, що за стандартного значення вивільняється 0 байтів, а за значення 100 — 99.5 відсотка. Перевірте значення, яке фактично використовує kernel, оскільки деякі 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 при цьому не змінюється.
Код розміщується в /opt/dormice, конфігурація — у /etc/dormice/env, дані sandbox — у /var/lib/dormice, а команди dormice і dor — у /usr/local/bin. Інсталятор генерує токен API під час встановлення та записує його в /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, щоб перевірити роботу runtime, а не покладатися на список пакетів. Запускайте її повторно щоразу, коли daemon працює неправильно.
sudo dor doctor
systemctl is-active dormicesystemctl is-active dormice має вивести active. Якщо виводиться failed, причина міститься в journalctl -u dormice -n 50. Невдалий запуск зазвичай спричинений swap або невиконаною передумовою gVisor, а не самим daemon.
Інсталятор також встановлює Caddy на сервер, тому перед завершенням роботи з firewall перевірте, які порти прослуховуються.
sudo ss -lntpDaemon прив’язується до 127.0.0.1:3676 і навмисно не має параметра для зміни цього значення. Доступ до нього з вашого ноутбука потрібно відкривати свідомо. Найпростіший варіант — SSH tunnel.
ssh -L 3676:127.0.0.1:3676 root@your-serverКоли tunnel відкрито, http://127.0.0.1:3676/console на вашому ноутбуці є вебконсоллю. Увійдіть за допомогою токена один раз. Після цього він перетворюється на cookie сесії httpOnly, тому сам токен не зберігається там, де його може прочитати вебсторінка. На сторінці Connect відображаються готові для копіювання фрагменти клієнтської конфігурації, уже спрямовані на ваш endpoint.
Створення sandbox і виконання коду в ньому
Одна операція створює sandbox: acquire. Вона ідемпотентна, тому той самий ключ завжди повертає той самий sandbox, створюючи його, пробуджуючи, запускаючи або відновлюючи за потреби. Будь-яка інша команда повертає 404 для ключа, якого ще не було. У dor CLI немає команди acquire, тому перший 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. Помилка автентифікації означає, що скопійований рядок токена містив ім’я змінної.
Файли передаються за допомогою dor sandbox push my-agent ./script.py і зберігаються за шляхом /home/user/script.py. Команда dor sandbox pull my-agent notes.txt повертає файл назад. Вбудовані команди роботи з файлами обмежують розмір одного файлу до 16 MiB, тоді як файловий інтерфейс E2B передає дані потоком, і єдиним обмеженням залишається квота диска sandbox.
Знищення — єдина команда, яка видаляє дані. Це також показовий приклад віку проєкту: основний 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 tsximport { 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_ перед ним. Саме такий формат очікує compatibility layer.
Це не заглушка сумісності. Потокове передавання stdout і stderr, фонові команди, інтерактивний PTY, підписані URL для завантаження та вивантаження, відстеження каталогів і port proxy перевіряються через офіційний пакет у реальному Docker і daemon gVisor набором end-to-end тестів проєкту. Перед міграцією реальних робочих навантажень врахуйте кілька відмінностей:
- Збирання шаблонів не реалізовано. Шаблон — це docker image, який ви самостійно збираєте та реєструєте через
dor template add, аSandbox.create('name')знаходить його. Для незареєстрованого імені повертається 404, а не імітується успішний результат. - Sandboxes, створені через поверхню E2B, отримують реальні дедлайни, оскільки цього вимагає семантика E2B. Для sandboxes, створених через native API, дедлайни ніколи не встановлюються.
- Заморожений sandbox зберігає свої процеси та відновлює їхнє виконання з того самого місця. Тому pause і resume тут не означають stop і cold start, до яких ви могли звикнути.
Що sandbox блокує, а що — ні
gVisor перехоплює системні виклики контейнера в userspace і сам їх обробляє, тому код у sandbox не взаємодіє безпосередньо з kernel хоста. Усередині sandbox усе виконується від імені непривілейованого користувача з uid 1000. Цього достатньо для типових випадків: згенерований скрипт, який запускає rm -rf /, заповнює диск або створює процеси, доки система не завершить їх, пошкоджує лише власний sandbox і на цьому зупиняється.
Ось що sandbox не блокує. За це відповідаєте ви.
- Sandbox має робочий вихідний network-доступ. Згенерований код може завантажувати все, що завгодно, і надсилати все, що знайде. Мережеве посилення безпеки інсталятора охоплює два конкретні аспекти: воно блокує трафік контейнера до cloud metadata service у діапазоні 169.254.0.0/16, через який cloud передає облікові дані інстансу всьому, що може до нього звернутися, і вимикає трафік між контейнерами за допомогою
"icc": falseу Dockerdaemon.json. Більше нічого не блокується. Прочитайтеsudo iptables -S DOCKER-USERі додайте власні правила DROP для приватних діапазонів, до яких sandbox не повинен мати доступу. - Docker вставляє власні правила перед правилами вашого firewall, тому опублікований порт контейнера може відповідати на запити з інтернету, навіть якщо ufw вважає його закритим. Перед тим як відкривати доступ до будь-чого на цьому хості, прочитайте як Docker публікує порти в обхід ufw і основи firewall ufw для VPS.
- gVisor — це kernel у userspace, а не hypervisor. Це свідомий компроміс, оскільки для заморожування стану sandbox мають бути процесами, а вимога KVM унеможливила б встановлення в потрібних середовищах. Якщо ваша модель загроз вимагає апаратної віртуалізації, використовуйте ізоляцію рівня Firecracker і враховуйте операційні витрати, пов’язані з нею.
- API token — це вся межа безпеки на стороні клієнта. Будь-хто, хто має
DORMICE_API_TOKEN, може створювати, читати та знищувати кожен sandbox на машині. Запускайте процес агента від імені окремого непривілейованого користувача на VPS і поводьтеся з token так само, як із SSH key. Практики з безпечного запуску Claude Code на VPS безпосередньо застосовні й тут.
Сам daemon працює від імені root на вашому хості. gVisor захищає хост від коду всередині sandbox, але ніщо не захищає хост від daemon або від того, хто має його token. Тому машина, на якій працює Dormice, має виконувати лише це завдання. Якщо ваш agent також підключається до інструментів через MCP (model context protocol), з тієї самої причини розміщуйте ці MCP servers на окремому VPS.
Скільки sandbox поміститься на 4 GB і 8 GB?
Пам’ять споживають дві складові: базове споживання самого хоста та робочий набір кожного sandbox, який наразі активний. Зарезервуйте приблизно 1 GB для Ubuntu, Docker і daemon, а потім поділіть залишок на фактичне споживання одного sandbox. Sandbox із запущеним скриптом Python, який читає кілька файлів, використовує близько 200–300 MiB. Sandbox із компілятором або повним набором тестів може використовувати понад 1 GiB.
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 активних sandbox, якщо кожен використовує 512 MiB, або 3, якщо кожен використовує повний 1 GiB. Для VPS на 8 GB ці значення становлять 14 і 7. Це граничні значення для одночасної роботи, а не результати бенчмарку, тому стежте за free -m під час роботи власного навантаження.
Для призупинених sandbox обмеженням є swap, а не RAM — у цьому й полягає основна ідея конструкції. Призупинений sandbox, який використовував 1 GiB, зберігає приблизно стільки ж даних у swap і майже нічого не займає в RAM, тому типовий файл swap на 16 GB, який створює інсталятор, вміщує приблизно 16 таких sandbox. Після цього вони мають перейти до стану stopped, у якому використовують лише дисковий простір. Саме диск є фактичним довгостроковим обмеженням: кожен sandbox зберігає власну файлову систему, а кілька десятків агентів із власним каталогом node_modules заповнять невеликий том задовго до того, як використання пам’яті стане критичним.
Заморожений, зупинений, архівований: параметри життєвого циклу
За замовчуванням sandbox заморожується після 10 хвилин бездіяльності, зупиняється після 3 днів, а після 7 днів архівується, якщо архівування налаштовано. Якщо встановити stopAfterSeconds у null, агент залишається резидентним: він може заморожуватися під час бездіяльності, але холодний запуск ніколи не виконується.
Архівування необов’язкове, і daemon повідомляє про його стан. Установіть чотири змінні DORMICE_S3_* — і диск зупиненого sandbox буде запаковано за допомогою tar та zstd, передано до будь-якого сумісного із S3 bucket і звільнено локально. Цим bucket може бути bucket MinIO, який ви розміщуєте самостійно на іншій вашій машині. Якщо залишити змінні невстановленими, sandbox назавжди залишатиметься у стані stopped, а політику, яка вимагає архівування, буде відхилено, а не непомітно проігноровано. Відновлення виконується прозоро: наступний acquire одразу повертає статус restoring і значення прогресу, а після відновлення диска переходить у стан ready.
Чи варто вже покладатися на нього?
Коротка відповідь: ні, якщо ви не можете відновити систему з нуля. Перший коміт у репозиторії датовано 8 July 2026. Станом на 4 August 2026 репозиторій має 446 stars, 37 forks, ліцензію Apache-2.0 і взагалі не має позначених релізів. У власному рядку стану README зазначено, що нічого ще не готове до production.
Це поєднання створює цілком конкретний профіль ризику. Код змінюється під час роботи, оскільки інсталятор відстежує main. Інтерфейс ще стабілізується. Саме тому verb для видалення має дві різні назви у двох файлах одного репозиторію. А проєкт, якому лише чотири тижні, може просто припинити розробку, оскільки жоден пункт ліцензії не зобов’язує продовжувати її.
Ризик можна контролювати завдяки сумісності з E2B. Ваш застосунок взаємодіє з протоколом, для якого існує hosted implementation. Тому, якщо Dormice припинить розвиток, достатньо змінити два URL і продовжити роботу. Реалізуйте agent поверх E2B surface, а не native API, щоб зберегти цей варіант міграції. Пакет native @dormice/sdk також ще не опубліковано в npm. Для його використання потрібно збирати пакет із репозиторію, і це ще одна причина почати із сумісного шляху.
Запускайте його там, де втрата системи не буде критичною. Відновлюйте host зі script, не зберігайте token у жодному prompt або commit і виводьте все важливе із sandboxes у власну систему резервного копіювання.
FAQ
Чи готовий Dormice до використання в production?
Ні, і сам проєкт прямо про це повідомляє. У README зазначено, що наразі нічого не готове до використання в production. Станом на 4 August 2026 репозиторію близько чотирьох тижнів, у ньому немає git tags і releases, тому немає номера версії, який можна зафіксувати. Інсталятор клонує гілку main, тому кожен запуск отримує найновіший commit. Після кожної інсталяції зберігайте git -C /opt/dormice rev-parse HEAD, а всі цінні дані зберігайте за межами sandbox.
Чим Dormice відрізняється від надання агенту одноразової VM?
Одноразова VM — це машина з SSH, яку ви створюєте для сеансу, а потім видаляєте. Dormice — це API виконання: ваша програма викликає acquire, потім exec і отримує stdout та код завершення без проміжного shell-сеансу. VM підходить людині або агенту, якому на певний час потрібен цілий комп’ютер. Dormice підходить застосунку, який багато разів на день виконує згенерований код і не хоче щоразу витрачати ресурси на підготовку та видалення цілої машини.
Чи справді офіційний E2B SDK працює без змін у коді?
Так, але потрібно змінити конфігурацію. Вкажіть apiUrl і sandboxUrl на /e2b/api і /e2b/envd вашого daemon, а token Dormice передайте як API key із префіксом e2b_. Виконання команд, PTY-сеанси, передавання файлів, підписані URL і port proxy покриває end-to-end suite проєкту, яка працює через офіційний package. Помітний виняток — створення template: e2b template build не реалізовано, тому template — це docker image, який ви створюєте та реєструєте за допомогою dor template add.
Скільки sandbox поміститься на VPS із 4 GB?
Приблизно 6 активних одночасно, якщо кожен sandbox використовує 512 MiB, або 3, якщо кожен використовує повний gibibyte. Це значення наведено після резервування приблизно 1 GB для операційної системи, Docker і daemon. Кількість заморожених sandbox обмежена swap, тому стандартний файл swap розміром 16 GB, який створює інсталятор, дає змогу розмістити приблизно 16 sandbox, кожен із яких використовував gibibyte. Вимірюйте власні значення за допомогою free -m під реальним навантаженням, оскільки sandbox із test suite використовує в кілька разів більше пам’яті, ніж sandbox із невеликим script.
Чому Dormice потребує значення vm.swappiness, установленого на 100?
Заморожування sandbox означає переміщення його неактивної пам’яті у swap. gVisor зберігає пам’ять sandbox як shared memory, а ядро Linux не переміщує shared memory у swap за стандартного значення swappiness. Тому за стандартного значення freeze нічого не звільняє, і sandbox продовжує споживати весь обсяг пам’яті. Проєкт виміряв 0 bytes звільненої пам’яті за стандартного значення та 99.5 percent за значення 100. Перевіряйте фактичне значення за допомогою sysctl vm.swappiness, а не читанням конфігураційних файлів, оскільки деякі cloud images постачаються зі значенням 0.