SSD Nodes Learn 🎉 VPS da $5.50/mese
Guide Matt ConnorDi Matt Connor · Aggiornato 2026-08-07

Come eseguire sandbox per agenti con Dormice su un VPS

Scopri come installare Dormice su un VPS, eseguire codice non attendibile in sandbox compatibili con E2B, verificare l’isolamento e dimensionare l’host.

Che cos’è Dormice e che cosa non è

Dormice è un ambiente sandbox per agenti, gestito autonomamente: un singolo daemon su un VPS Linux di tua proprietà, che il codice dell’agente richiama tramite HTTP per eseguire codice non attendibile all’interno di un container isolato. Il programma richiede una sandbox per nome, riceve la stessa sandbox indipendentemente dallo stato in cui si trovava, esegue un comando al suo interno e legge l’output. La sandbox è una risorsa programmatica, non una macchina a cui accedere tramite login.

Questo modello è diverso dall’assegnare a un agente un intero computer. Una VM temporanea per un agente di sviluppo è un sistema a cui accedi tramite SSH, lasci che l’agente lo modifichi o danneggi, quindi lo elimini. Dormice opera a un livello inferiore: è l’API di esecuzione che il programma richiama quando dispone già del codice e ha bisogno di un ambiente sicuro in cui eseguirlo. Usa la VM temporanea quando l’unità di lavoro è un intero sistema. Usa Dormice quando l’unità di lavoro è una singola chiamata exec e vuoi eseguirne cento al giorno senza creare cento VM.

Il progetto si definisce compatibile con E2B. E2B è un servizio sandbox gestito, la cui libreria client è già importata da molti framework per agenti. Dormice espone lo stesso protocollo usando i propri prefissi URL, quindi un’applicazione sviluppata sulla base del pacchetto e2b ufficiale continua a funzionare quando la si configura per usare il tuo server. Il codice dell’applicazione non cambia. Cambiano 2 URL e 1 prefisso della chiave API.

Che cosa significa in pratica «la SQLite dei sandbox per agenti»

SQLite è un database incorporato nell'applicazione, non un servizio da gestire, e Dormice riprende direttamente questo confronto. Un demone, un file SQLite per il ledger e una porta TCP. Nessun Kubernetes, nessun database separato, nessuno scheduler. Il demone crea un lock accanto al ledger e rifiuta l'avvio quando il ledger e la macchina rilevata non possono appartenere alla stessa installazione. In questo modo lo split brain non può verificarsi senza essere rilevato. Il progetto è pensato per una sola macchina. Se serve una farm distribuita su più host, il README indica chiaramente di scegliere un'altra soluzione: è un'indicazione da seguire.

La seconda parte dell'idea riguarda i costi. Un sandbox in hosting viene fatturato per ogni secondo in cui rimane attivo, quindi i sandbox in hosting sono progettati per essere temporanei. Dormice viene eseguito su hardware già disponibile, quindi i suoi sandbox sono permanenti e costano meno quanto più a lungo rimangono inattivi. Un sandbox passa gradualmente a uno stato di minore attività: attivo, poi congelato, quindi arrestato e infine archiviato. Qualsiasi operazione acquire lo riporta allo stato operativo dal livello raggiunto.

Il congelamento è l'aspetto più importante da comprendere, perché rende economicamente sostenibile conservare per sempre il sandbox di ogni agente. Questi sono i dati pubblicati dal progetto, misurati sul relativo hardware e non sul tuo.

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
  }
]

Un sandbox inattivo che utilizza 1024 MiB di memoria scende a 5 MiB di memoria residente dopo il congelamento e torna operativo in circa 50 ms. I processi vengono sospesi e ripresi nello stesso punto, quindi un agente di lunga durata conserva lo stato della shell e il lavoro parzialmente completato anche dopo il congelamento. Riproduci questa misura sul tuo host prima di pianificare la capacità necessaria.

Cosa serve all'host prima dell'installazione

L'host deve eseguire Ubuntu o Debian su x86_64 e l'installer richiede l'account root. Il demone mantiene root durante l'esecuzione perché crea loop mount e scrive nei cgroup.

Le sandbox vengono eseguite tramite Docker con gVisor, un runtime per container che inserisce un kernel in userspace tra il container e il kernel dell'host. Questo fornisce il runtime runsc utilizzato da ogni sandbox. Il demone viene eseguito con Node 22 o versioni successive. L'installer include una propria copia di Node, quindi il Node di sistema non viene modificato.

Deve essere presente la swap e vm.swappiness deve essere impostato su 100. Non è un suggerimento di tuning, ma un requisito funzionale. Il congelamento funziona spostando nella swap la memoria di una sandbox inattiva. gVisor mantiene la memoria della sandbox come memoria condivisa e, con il valore predefinito di swappiness, il kernel non sposta la memoria condivisa nella swap. Il progetto ha misurato 0 byte recuperati con il valore predefinito e il 99.5 percento con il valore 100. Controlla il valore effettivamente utilizzato dal kernel, perché alcune immagini cloud impostano vm.swappiness = 0 in un file che normalmente non penseresti di controllare.

sysctl vm.swappiness
swapon --show

sysctl vm.swappiness dovrebbe stampare vm.swappiness = 100, mentre swapon --show dovrebbe elencare un file di swap. Se swappiness restituisce 0, ogni congelamento non produce alcun effetto e continui a usare tutta la memoria prevista per ogni sandbox inattiva.

Installare Dormice su Ubuntu

L'installazione documentata consiste nell'eseguire una pipe verso bash:

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

Scaricare lo script e leggerlo prima di eseguirlo. Lo script viene eseguito come root e modifica l'host: installa Docker se non è presente, scarica gVisor e Caddy verificandone i checksum, crea un file di swap, scrive le unità systemd e aggiunge regole 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 imposta la dimensione del file di swap e il valore predefinito è 16, una quantità elevata di spazio da destinare allo swap su un VPS di piccole dimensioni. --mirror cn reindirizza i download verso mirror raggiungibili dalla Cina continentale. Eseguire nuovamente l'installer aggiorna il codice e corregge le differenze rispetto alla configurazione prevista; non ruota mai il token API.

Il codice viene installato in /opt/dormice, la configurazione in /etc/dormice/env, i dati della sandbox in /var/lib/dormice e i comandi dormice e dor in /usr/local/bin. Durante l'installazione, l'installer genera il token API e lo scrive in /etc/dormice/env con modalità 600.

Non esiste una release con tag su cui basare l'installazione. Al 4 agosto 2026 il repository non contiene tag git né release GitHub. L'installer clona quindi main e installa qualunque modifica sia stata pubblicata quella mattina. Per fissare una versione è quindi necessario annotare il commit effettivamente installato.

git -C /opt/dormice rev-parse HEAD

Salvare questo hash nelle note del deploy. Se un aggiornamento causa problemi, quel commit è l'unico modo per tornare alla versione precedente, perché non esiste un numero di versione da indicare.

L'installer termina eseguendo dor doctor, un controllo dell'host in sola lettura che avvia container gVisor reali per verificare il funzionamento del runtime, invece di basarsi sull'elenco dei pacchetti installati. Eseguirlo nuovamente ogni volta che il daemon presenta anomalie.

sudo dor doctor
systemctl is-active dormice

systemctl is-active dormice dovrebbe stampare active. Se stampa failed, journalctl -u dormice -n 50 contiene il motivo. Un avvio non riuscito dipende in genere dal prerequisito dello swap o di gVisor, non dal daemon stesso.

L'installer installa anche Caddy sull'host. Prima di considerare completata la configurazione del firewall, verificare quindi quali servizi sono in ascolto.

sudo ss -lntp

Il daemon si associa a 127.0.0.1:3676 e, per scelta progettuale, non dispone di un'impostazione per modificarlo. Raggiungerlo dal laptop è un'operazione deliberata; la soluzione più semplice consiste nell'usare un tunnel SSH.

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

Con il tunnel aperto, http://127.0.0.1:3676/console sul laptop apre la console web. Effettuare l'accesso con il token una sola volta: il token viene quindi sostituito da un cookie di sessione httpOnly e non viene mai memorizzato in un punto leggibile dalla pagina. La pagina Connect mostra snippet client già configurati per puntare al proprio endpoint, pronti per essere copiati e incollati.

Creare un sandbox ed eseguire codice al suo interno

Un'operazione crea un sandbox: acquire. È idempotente, quindi la stessa chiave restituisce sempre lo stesso sandbox, creandolo, riattivandolo, avviandolo o ripristinandolo in base alle necessità. Tutti gli altri verbi restituiscono 404 per una chiave mai utilizzata. La CLI dor non dispone del verbo acquire, quindi il primo sandbox deve essere creato dalla console o da una libreria client.

La console è il metodo più rapido. Apri /console tramite il tunnel e crea un sandbox denominato my-agent. La CLI potrà quindi utilizzarlo.

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 elenca ogni sandbox con il relativo stato del ciclo di vita. Puoi usarlo per monitorare il passaggio da attivo a congelato. dor sandbox exec visualizza la versione di Python 3.12, perché l'immagine standard è Ubuntu 24.04 con Python 3.12, Node 24, git e ripgrep già installati. Un errore di autenticazione indica invece che la riga del token copiata includeva il nome della variabile.

I file vengono trasferiti con dor sandbox push my-agent ./script.py, che li salva in /home/user/script.py, mentre dor sandbox pull my-agent notes.txt ne recupera uno. I verbi nativi per i file limitano la dimensione a 16 MiB per file; l'interfaccia per i file di E2B esegue invece lo streaming e lascia che l'unico limite sia la quota del disco del sandbox.

La distruzione è l'unico verbo che comporta la perdita dei dati. È anche un esempio significativo dell'età del progetto: il README principale e la skill dell'agente inclusa documentano dor sandbox destroy <key>, mentre il README del pacchetto CLI documenta dor sandbox release <key>. Esegui dor sandbox --help sulla tua build e considera quello il riferimento corretto.

Indirizza il codice E2B esistente verso il tuo server

Questo è il motivo per cui vale la pena farlo. Il pacchetto ufficiale e2b di npm, senza modifiche, comunica con Dormice. Esegui questo comando dal laptop con il tunnel SSH aperto, così sul server non viene messo in ascolto nulla di nuovo.

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

Un'esecuzione corretta restituisce il codice di uscita 0 e 42. La chiave API è il token Dormice con il prefisso e2b_ davanti, cioè il formato previsto dal livello di compatibilità.

La compatibilità non è uno stub. La suite end-to-end del progetto verifica lo streaming di stdout e stderr, i comandi in background, una PTY interattiva, gli URL firmati per upload e download, il monitoraggio delle directory e un proxy per le porte. Tutti questi test vengono eseguiti tramite il pacchetto ufficiale contro daemon Docker e gVisor reali. Prima di migrare sistemi reali, considera alcune differenze:

  • La creazione di template non è implementata. Un template è un'immagine Docker che devi creare e registrare con dor template add; Sandbox.create('name') la risolve. Un nome non registrato restituisce 404 invece di simulare una risorsa esistente.
  • Le sandbox create tramite l'interfaccia E2B hanno scadenze effettive, perché la semantica E2B le richiede. Le sandbox create tramite l'API nativa non hanno mai scadenze imposte.
  • Una sandbox congelata mantiene i processi e li riprende nel punto in cui si trovavano. In questo caso, quindi, pausa e ripresa non equivalgono all'arresto e al riavvio completo a cui potresti essere abituato.

Cosa blocca la sandbox e cosa non blocca

gVisor intercetta le chiamate di sistema del container nello userspace e le gestisce direttamente. Il codice nella sandbox non comunica quindi direttamente con il kernel dell'host. All'interno della sandbox, tutto viene eseguito da un utente senza privilegi, uid 1000. Questa combinazione gestisce il caso ordinario: uno script generato che esegue rm -rf /, riempie il disco o crea processi con fork fino a causare un arresto danneggia la propria sandbox e non va oltre.

Ecco cosa non blocca. Questi aspetti sono di tua responsabilità.

  • Una sandbox dispone di connettività di rete in uscita. Il codice generato può scaricare qualsiasi contenuto e inviare qualsiasi dato trovi. L'hardening di rete dell'installer copre due aspetti specifici: blocca il traffico dei container verso il servizio di metadati cloud nella rete 169.254.0.0/16, che è il punto in cui un cloud fornisce le credenziali dell'istanza a qualsiasi elemento in grado di raggiungerlo, e disattiva il traffico tra container con "icc": false nel file daemon.json di Docker. Non viene bloccato altro. Leggi sudo iptables -S DOCKER-USER e aggiungi le tue regole DROP per gli intervalli privati che una sandbox non dovrebbe poter raggiungere.
  • Docker inserisce le proprie regole prima di quelle del firewall. Di conseguenza, una porta pubblicata dal container può rispondere da Internet anche se ufw la considera chiusa. Leggi come Docker pubblica le porte oltre ufw e le nozioni di base sul firewall ufw per un VPS prima di esporre qualsiasi servizio su questo host.
  • gVisor è un kernel nello userspace, non un hypervisor. È una scelta deliberata, perché il congelamento richiede che le sandbox siano processi e perché imporre KVM impedirebbe l'installazione ovunque. Se il tuo modello di minaccia richiede la virtualizzazione hardware, usa un isolamento di classe Firecracker e accetta il relativo costo operativo.
  • Il token API costituisce l'intero perimetro di sicurezza lato client. Chiunque disponga di DORMICE_API_TOKEN può creare, leggere e distruggere ogni sandbox sulla macchina. Assegna al processo dell'agente un proprio utente con privilegi minimi sul VPS e tratta il token come tratteresti una chiave SSH. Le procedure descritte in eseguire Claude Code in sicurezza su un VPS si applicano direttamente.

Il daemon viene eseguito come root sull'host. gVisor protegge l'host dal codice all'interno di una sandbox, ma nulla protegge l'host dal daemon o da chiunque disponga del suo token. La macchina che esegue Dormice dovrebbe quindi essere dedicata esclusivamente a questo scopo. Se il tuo agente accede anche a strumenti tramite MCP (model context protocol), mantieni gli server MCP su un VPS separato per lo stesso motivo.

Quanti sandbox entrano in 4 GB e 8 GB?

La memoria viene consumata da due componenti: la quantità riservata al sistema host e il working set di ogni sandbox attivo. Riserva circa 1 GB per Ubuntu, Docker e il daemon, quindi dividi la memoria rimanente per quella effettivamente utilizzata da un sandbox. Un sandbox che esegue uno script Python e legge pochi file usa circa da 200 a 300 MiB. Un sandbox che esegue un compilatore o un'intera suite di test può superare 1 gibibyte.

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
  }
]

Un VPS da 4 GB può mantenere attivi contemporaneamente circa 6 sandbox se ciascuno usa 512 MiB, oppure 3 se ciascuno usa 1 gibibyte intero. Con un VPS da 8 GB si passa a 14 e 7. Sono limiti per l'esecuzione simultanea, calcolati aritmeticamente e non ottenuti tramite benchmark; monitora quindi free -m mentre esegui il tuo carico di lavoro.

I sandbox sospesi sono limitati dallo swap anziché dalla RAM, che è lo scopo principale di questo design. Un sandbox sospeso che utilizzava 1 gibibyte mantiene all'incirca la stessa quantità nello swap e quasi nulla nella RAM, quindi il file di swap predefinito da 16 GB dell'installer può contenere circa 16 sandbox di questo tipo. Oltre questo limite, devono raggiungere lo stato stopped, nel quale consumano soltanto spazio su disco. Il disco è il vero limite nel lungo periodo: ogni sandbox conserva il proprio filesystem e alcune decine di agenti, ciascuno con una directory node_modules, possono riempire un volume di piccole dimensioni molto prima che la memoria diventi un problema.

Congelamento, arresto, archiviazione: i parametri del ciclo di vita

I valori predefiniti sono il congelamento dopo 10 minuti di inattività, l'arresto dopo 3 giorni e l'archiviazione dopo 7 giorni quando l'archiviazione è configurata. Impostando stopAfterSeconds su null si ottiene un agent residente: può congelarsi quando è inattivo e non esegue mai un avvio a freddo.

L'archiviazione è facoltativa e il daemon lo comunica esplicitamente. Imposta le quattro variabili DORMICE_S3_*: il disco di un sandbox arrestato viene impacchettato con tar e zstd, trasferito in un bucket compatibile con S3 e liberato localmente. Il bucket può essere un bucket MinIO gestito autonomamente su un altro server di tua proprietà. Se lasci le variabili non impostate, i sandbox restano arrestati indefinitamente e una policy che richiede l'archiviazione viene rifiutata invece di essere ignorata senza avviso. I ripristini sono visibili: la richiesta acquire successiva restituisce immediatamente uno stato di ripristino e un valore di avanzamento, quindi passa allo stato ready quando il disco è stato ripristinato.

Conviene già affidarsi a questo progetto?

Risposta breve: non per attività che non puoi ricostruire. Il primo commit nel repository è datato 8 luglio 2026. Al 4 agosto 2026 il progetto mostra 446 stelle, 37 fork, una licenza Apache-2.0 e nessuna release contrassegnata. La riga sullo stato presente nel README stesso indica che nulla è pronto per la produzione.

Questa combinazione determina un rischio specifico. Il codice può cambiare senza preavviso, perché l’installer segue main. Anche l’interfaccia è ancora in fase di definizione: il verbo per l’eliminazione ha infatti due nomi diversi in due file dello stesso repository. Inoltre, un progetto con quattro settimane di vita può semplicemente interrompersi, perché nessuna clausola della licenza obbliga qualcuno a proseguirne lo sviluppo.

La compatibilità E2B rende il rischio gestibile. La tua applicazione comunica con un protocollo che dispone di un’implementazione hosted, quindi, se Dormice si blocca, puoi modificare 2 URL e continuare a lavorare. Scrivi l’agente utilizzando la superficie E2B invece dell’API nativa, così mantieni questa possibilità di uscita. Anche il pacchetto nativo @dormice/sdk non è ancora disponibile su npm; per usarlo devi quindi compilarlo dal repository. Questo è un ulteriore motivo per iniziare dal percorso compatibile.

Eseguilo in un ambiente in cui puoi permetterti di perderlo. Ricrea l’host a partire da uno script, non inserire il token in nessun prompt o commit e trasferisci le informazioni importanti fuori dalle sandbox secondo la tua pianificazione di backup.

FAQ

Dormice è pronto per l'uso in produzione?

No, e il progetto lo dichiara esplicitamente. La riga relativa allo stato nel README indica che nulla è ancora pronto per la produzione. Inoltre, al 4 agosto 2026, il repository ha circa quattro settimane, non contiene tag Git né release e quindi non esiste un numero di versione da fissare. L'installer clona il branch main, quindi ogni esecuzione scarica il commit più recente. Registra git -C /opt/dormice rev-parse HEAD dopo ogni installazione e conserva tutti i dati importanti al di fuori delle sandbox.

In cosa differisce Dormice da una VM temporanea per il mio agent?

Una VM temporanea è una macchina con SSH che crei per una sessione e poi elimini. Dormice è un'API di esecuzione: il programma chiama acquire, poi exec e riceve stdout e un codice di uscita, senza una sessione shell intermedia. La VM è adatta a una persona o a un agent che vuole utilizzare un intero computer per un certo periodo. Dormice è adatto a un'applicazione che esegue codice generato molte volte al giorno e non vuole gestire, a ogni esecuzione, la configurazione e la rimozione di una macchina intera.

L'SDK ufficiale di E2B funziona davvero senza modifiche al codice?

Sì, con modifiche alla configurazione. Imposta apiUrl e sandboxUrl sui valori /e2b/api e /e2b/envd del tuo daemon e passa il token Dormice con il prefisso e2b_ come API key. L'esecuzione dei comandi, le sessioni PTY, il trasferimento dei file, gli URL firmati e il port proxy sono tutti coperti dalla suite end-to-end del progetto, eseguita tramite il pacchetto ufficiale. La creazione dei template è la lacuna principale: e2b template build non è implementato, quindi un template è un'immagine Docker che crei e registri con dor template add.

Quante sandbox possono essere eseguite su un VPS da 4 GB?

Circa 6 contemporaneamente se ogni sandbox utilizza 512 MiB, oppure 3 se ciascuna utilizza un gibibyte intero, dopo aver riservato circa 1 GB per il sistema operativo, Docker e il daemon. Le sandbox congelate sono invece limitate dalla swap. Con il file di swap predefinito da 16 GB dell'installer è possibile mantenere sospese circa 16 sandbox che utilizzavano ciascuna un gibibyte. Esegui le tue misurazioni con free -m sotto carico reale, perché una sandbox che esegue una suite di test utilizza diverse volte la memoria necessaria per uno script di piccole dimensioni.

Perché Dormice richiede di impostare vm.swappiness su 100?

Congelare una sandbox significa spostare la memoria inattiva nella swap. gVisor mantiene la memoria della sandbox come memoria condivisa e il kernel Linux non trasferisce la memoria condivisa nella swap con il valore predefinito di swappiness. Di conseguenza, con il valore predefinito il congelamento non recupera memoria e la sandbox continua a consumare tutta la memoria. Il progetto ha misurato 0 byte recuperati con il valore predefinito e il 99.5 percento con il valore 100. Controlla il valore effettivo con sysctl vm.swappiness invece di leggere i file di configurazione, perché alcune immagini cloud vengono distribuite con valore 0.