One sandbox per end user
Works locallyWorks in the local build today.
This guide is for platforms that give each of their users a machine.
| Rule | Why |
|---|---|
| One VM per end user | A VM is the isolation boundary. Containers inside it share a kernel. |
| Never reuse a VM between users | Files, memory and caches can leak |
no_env: true on every tenant VM |
Nothing of yours enters |
| Egress policy on the host | Your user has root and could remove a firewall inside the VM |
| One label per tenant | Budget, usage and chargeback |
harebox new --name base --no-env
harebox exec base -- ./install-your-stack.sh
harebox template save base --name tenant-base
Template saves remove your secrets by default. Scanning is not perfect, so do not put secrets in a template source.
From your backend:
box = hb.sandboxes.create(
template="tenant-base",
no_env=True,
labels={"tenant": user.id},
sleep={"mode": "auto", "idle_seconds": 120},
idempotency_key=f"tenant-{user.id}",
)
hb.sandboxes.firewall.set(box.id, default_outbound="deny",
outbound=[{"action": "allow", "hosts": ["pypi.org", "registry.npmjs.org"]}])
hb.budgets.create(scope=f"label:tenant={user.id}", limit_usd=20, action="sleep")
The idempotency key means a retry never creates a second VM.
key = hb.api_keys.create(name=f"tenant-{user.id}", preset="tenant",
sandboxes=[box.id], ttl_seconds=86400, monthly_budget_usd=20)
The tenant preset reaches only this VM. It cannot create VMs, list others or read billing. Keep your own key on your server.
For previews, prefer OIDC or your own signed session in front of an endpoint. A token URL is a bearer credential: anyone who has it can open it.
You do not have to manage idleness. Incoming requests wake a sleeping VM through its endpoint, with its dev server still running. There is no need for a separate "resume, restart the daemon" routine.
| Time away | State | Your cost |
|---|---|---|
| Up to 7 days | sleeping |
Nothing |
| Up to 14 days after stop | stopped |
Nothing |
| After that | archived, unless you delete it |
$0.012/GB-month |
No daily job is needed to protect a user's disk. Delete only on an explicit "delete my data" action, never on idleness. Archive is automatic, and you get a sandbox.archive_warning event first.
harebox usage --all --group-by label --json
This returns exact billed cost per tenant. Sleep time is shown separately. Listen to budget.threshold to warn your user before they hit a limit.
| Risk | Mitigation |
|---|---|
| A tenant abuses your account | Per-tenant budget, egress policy; abuse.limited event reaches you first |
| Thousands wake at once | Wake latency rises. Measure with your own traffic. |
| A tenant needs a nested VM | Sleep is off while it runs, so budget for that |
| Site outage | HareBox restarts affected sandboxes at another EU site from their last save. Everything stays in the EU. |
For 1,000 users at 15 hours a month on default, the list price is about $540 a month before any idle reclaim. If 20% of that time is reclaimed by sleep, it falls to about $432. Check your own idle share in harebox usage, since 20% is an assumption.

