> ## Documentation Index
> Fetch the complete documentation index at: https://docs.beta.b3os.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Sandbox settings

Every sandbox setting: size, lifetime, egress, the API grant, commands and port URLs, with defaults, values and examples, and what is fixed.

Set these when you create the sandbox, or on the call that uses them (a command, a fork, a port URL). A sandbox keeps its size for life; change the size by creating another. [Sandboxes](/sandboxes#create-a-sandbox) shows a create with the common ones.

| Setting | Default |
|---|---|
| [Template](#template): `template` | `base` |
| [CPUs](#cpus): `vcpu` | the template's `defaults.vcpu` (1 for `base`) |
| [Memory](#memory): `memory_mib` | the template's `defaults.memory_mib` (512 MiB for `base`) |
| [Disk](#disk): `disk_gib` | the template's (4 GiB for `base`) |
| [Lifetime](#lifetime): `timeout_s` | 300 s |
| [At the timeout](#at-the-timeout): `on_idle` | `stop` |
| [Forkable](#forkable): `forkable` | `false` |
| [Fork count](#fork-count): `count` | 1 |
| [Chrome reset on restore and fork](#chrome-reset-on-restore-and-fork): `clone_reset` | the node's: `full` on the beta node ([per field](#chrome-reset-on-restore-and-fork)) |
| [Egress](#egress): `egress.mode` | `public` |
| [API grant](#api-grant): `api.scopes` | none: code inside can call nothing ([per field](#api-grant)) |
| [Port URL lifetime](#port-url-lifetime): `ttl_s` | 600 s |
| [Command timeout](#command-timeout): `timeout_ms` | 30,000 ms; none in the background ([per field](#command-timeout)) |
| [Working directory](#working-directory): `cwd` | `/workspace` |
| [Run as](#run-as): `user` | `user` |
| [Background](#background): `background` | `false` |
| [Code language](#code-language): `language` | `python` |

## Size and template

### Template

What the sandbox starts with: its disk, its tools and its default size. `run_code` needs `code-interpreter`. Ignored when `snapshot` is set.

- **Field:** `template` on [create](/api/post-v1-sandboxes)
- **Default:** `base`
- **Values:** a template name (`base`, `code-interpreter`, `agent`) or a `tpl_` ID, from `GET /v1/sandboxes/templates`
- **Invalid value:** [`400 invalid_request`](/errors#invalid_request)
- **Guide:** [Templates](/sandboxes#templates)

```json
{"template": "code-interpreter"}
```

```bash
b3os sandbox create --template code-interpreter
```

### CPUs

Virtual CPUs. The template's default size comes from a pool of microVMs started ahead of time; any other size is restored on demand, which is slower, and the first create at a new size also builds a snapshot for it.

- **Field:** `vcpu` on [create](/api/post-v1-sandboxes)
- **Default:** the template's `defaults.vcpu` (1 for `base`)
- **Values:** 1 or more; at most your plan's `sandboxes.vcpu_max` (2 in the beta)
- **Invalid value:** [`400 invalid_request`](/errors#invalid_request), [`422 limit_exceeded`](/errors#limit_exceeded), [`429 rate_limited`](/errors#rate_limited)
- **Guide:** [Sizes](/sandboxes#sizes)

```json
{"template": "base", "vcpu": 2}
```

```bash
b3os sandbox create --vcpu 2
```

### Memory

Memory, rounded up to 128 MiB or the next multiple of 256 MiB: a request for 600 runs with 768. The sandbox's `memory_mib` says what it got, and memory bills at that size.

- **Field:** `memory_mib` on [create](/api/post-v1-sandboxes)
- **Default:** the template's `defaults.memory_mib` (512 MiB for `base`)
- **Values:** 128 MiB or more; at most your plan's `sandboxes.memory_max` (4,096 MiB in the beta)
- **Invalid value:** [`400 invalid_request`](/errors#invalid_request), [`422 limit_exceeded`](/errors#limit_exceeded)

```json
{"template": "base", "memory_mib": 2048}
```

```bash
b3os sandbox create --memory-mib 2048
```

### Disk

The sandbox's disk size.

- **Field:** `disk_gib` on [create](/api/post-v1-sandboxes)
- **Default:** the template's (4 GiB for `base`)
- **Values:** 1 GiB or more; at most the template's own disk, since disks do not grow in the beta
- **Invalid value:** [`400 invalid_request`](/errors#invalid_request), [`422 limit_exceeded`](/errors#limit_exceeded)

```json
{"template": "base", "disk_gib": 4}
```

```bash
b3os sandbox create --disk-gib 4
```

## Lifetime

### Lifetime

Seconds the sandbox runs from creation. A forgotten sandbox bills until then, so keep it short and extend it while you work: `POST …/timeout` on the sandbox sets a new lifetime from now, within the same bounds.

- **Field:** `timeout_s` on [create](/api/post-v1-sandboxes)
- **Default:** 300 s
- **Values:** 10 to 86,400 s; capped by your plan's `sandboxes.timeout_max` (3,600 s in the beta)
- **Invalid value:** [`400 invalid_request`](/errors#invalid_request), [`422 limit_exceeded`](/errors#limit_exceeded)
- **Guide:** [Lifecycle](/sandboxes#lifecycle)

```json
{"template": "base", "timeout_s": 900}
```

```bash
b3os sandbox create --timeout-s 900
```

### At the timeout

What happens at `expires_at`. `stop` destroys the sandbox. `pause` keeps it, so a resume after extending the timeout continues where it was; a paused sandbox is kept for an hour. It acts at `expires_at`, not when the sandbox is idle, so the SDKs and CLI 0.1.3 call it `on_timeout`.

- **Field:** `on_idle` on [create](/api/post-v1-sandboxes)
- **Default:** `stop`
- **Values:** `stop` or `pause`
- **Invalid value:** [`400 invalid_request`](/errors#invalid_request)
- **Guide:** [Pause and resume](/sandboxes/snapshots#pause-and-resume)

```json
{"template": "base", "on_idle": "pause"}
```

```bash
b3os sandbox create --on-timeout pause
```

### Forkable

Tracks the memory the sandbox changes, so it can be forked into up to 10 children. Forkable sandboxes come from a smaller pool, so set it only when you will fork.

- **Field:** `forkable` on [create](/api/post-v1-sandboxes)
- **Default:** `false`
- **Values:** `true` or `false`
- **Invalid value:** [`400 invalid_request`](/errors#invalid_request)
- **Guide:** [Fork](/sandboxes/snapshots#fork)

```json
{"template": "base", "forkable": true}
```

### Fork count

How many children one fork call makes, each starting where the source was.

- **Field:** `count` on [fork](/api/post-v1-sandboxes-sandbox-id-fork)
- **Default:** 1
- **Values:** 1 to 10
- **Invalid value:** [`400 invalid_request`](/errors#invalid_request)

```json
{"count": 4}
```

### Chrome reset on restore and fork

What happens to the `browser` template's Chrome in a sandbox restored from your snapshot (a create with `snapshot`) or forked. `full` replaces its renderers and network service when the sandbox starts, so `Math.random`, `crypto.getRandomValues` and WebSocket keys are fresh, and closes the tabs that were open at the snapshot. `none` keeps Chrome as the snapshot had it, its random state shared with the source. A create from a template ignores it, and it covers no other process. The `browser` template is not on the beta yet; where the node's image of it predates the reset, `full` is refused with `409 guest_outdated`.

- **Field:** `clone_reset` on [create](/api/post-v1-sandboxes) and [fork](/api/post-v1-sandboxes-sandbox-id-fork)
- **Default:** the node's: `full` on the beta node (create), the node's: `full` on the beta node, not the source's (fork)
- **Values:** `full` or `none`
- **Invalid value:** [`400 invalid_request`](/errors#invalid_request), [`422 option_not_allowed`](/errors#option_not_allowed)
- **Guide:** [Random state on restore and fork](/sandboxes/snapshots#random-state-on-restore-and-fork)

```json
{"count": 2, "clone_reset": "none"}
```

## Network and access

### Egress

Where the sandbox's traffic may go. `public` reaches any public address, `allowlist` only the hosts in `egress.allow`, and `deny` nothing. Private, loopback and metadata addresses are refused under every mode. A caller outside the sandbox can change it later; code inside cannot.

- **Field:** `egress.mode` on [create](/api/post-v1-sandboxes)
- **Default:** `public`
- **Values:** `public`, `allowlist` or `deny`
- **Invalid value:** [`400 invalid_request`](/errors#invalid_request)
- **Guide:** [Networking](/sandboxes#networking)

```json
{"template": "base", "egress": {"mode": "allowlist", "allow": ["github.com", "*.githubusercontent.com"]}}
```

### API grant

What code inside the sandbox may call on B3OS at `http://127.0.0.1:7700`, with no key: a subset of your own scopes, and an optional spend cap. With `infer:run` the environment also points the OpenAI and Anthropic SDKs at the node's models.

- **Field:** `api.scopes` and `api.spend_cap_usd` on [create](/api/post-v1-sandboxes)
- **Default:** none: code inside can call nothing (`api.scopes`), the creating key's own cap (`api.spend_cap_usd`)
- **Values:** scope names from [Scopes](/platform#scopes), within your own (`api.scopes`); 0 USD or more (`api.spend_cap_usd`)
- **Invalid value:** [`400 invalid_request`](/errors#invalid_request)
- **Guide:** [Agents in sandboxes](/sandboxes/agents)

```json
{"template": "base", "api": {"scopes": ["vision:run", "infer:run"]}}
```

```bash
b3os sandbox create --api-scope vision:run,infer:run
```

### Port URL lifetime

How long a URL minted for a private port works. Public ports ignore it; their URL's token lasts 7 days.

- **Field:** `ttl_s` on [port URL](/api/post-v1-sandboxes-sandbox-id-ports-port-url)
- **Default:** 600 s
- **Values:** 60 to 86,400 s
- **Invalid value:** [`400 invalid_request`](/errors#invalid_request)
- **Guide:** [Private ports](/sandboxes/ports#private-ports)

```json
{"ttl_s": 3600}
```

```bash
b3os sandbox port-url sbx_01example 8080 --ttl-s 3600
```

## Commands

### Command timeout

Kills the command after this long.

- **Field:** `timeout_ms` on [exec](/api/post-v1-sandboxes-sandbox-id-exec) and [run code](/api/post-v1-sandboxes-sandbox-id-run-code)
- **Default:** 30,000 ms; none in the background (exec), 30,000 ms (run code)
- **Values:** 1 to 3,600,000 ms; an exec waits at most 60,000 ms unless its output is streamed or it runs in the background (exec); 1 to 60,000 ms (run code)
- **Invalid value:** [`400 invalid_request`](/errors#invalid_request)

```json
{"cmd": "make test", "timeout_ms": 60000}
```

```bash
b3os sandbox exec sbx_01example --timeout-ms 60000 -- make test
```

### Working directory

Where the command runs.

- **Field:** `cwd` on [exec](/api/post-v1-sandboxes-sandbox-id-exec)
- **Default:** `/workspace`
- **Values:** an absolute path inside the sandbox
- **Invalid value:** [`400 invalid_request`](/errors#invalid_request)

```json
{"cmd": "ls", "cwd": "/tmp"}
```

```bash
b3os sandbox exec sbx_01example --cwd /tmp -- ls
```

### Run as

The user the command runs as. `root` can install system packages.

- **Field:** `user` on [exec](/api/post-v1-sandboxes-sandbox-id-exec)
- **Default:** `user`
- **Values:** `user` or `root`
- **Invalid value:** [`400 invalid_request`](/errors#invalid_request)

```json
{"cmd": "apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y -o Dpkg::Options::=--force-confold ffmpeg", "user": "root"}
```

```bash
b3os sandbox exec sbx_01example --root -- 'apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y -o Dpkg::Options::=--force-confold ffmpeg'
```

### Background

Returns at once with the process ID; read the output from the logs stream.

- **Field:** `background` on [exec](/api/post-v1-sandboxes-sandbox-id-exec)
- **Default:** `false`
- **Values:** `true` or `false`
- **Invalid value:** [`400 invalid_request`](/errors#invalid_request)

```json
{"cmd": "python3 -m http.server 8080", "background": true}
```

```bash
b3os sandbox exec sbx_01example --background -- python3 -m http.server 8080
```

### Code language

The kernel `run_code` sends the code to, in the `code-interpreter` template.

- **Field:** `language` on [run code](/api/post-v1-sandboxes-sandbox-id-run-code)
- **Default:** `python`
- **Values:** `python` or `javascript`
- **Invalid value:** [`400 invalid_request`](/errors#invalid_request)

```json
{"code": "1 + 1", "language": "javascript"}
```

## Fixed in the beta

These work one way in the beta, and no request field changes them.

### Paused sandboxes

**Kept 1 hour.** A sandbox paused by `on_idle: pause` is stopped an hour after it paused. Snapshots are kept 7 days.

### The model variable

**Set with infer:run.** A sandbox whose grant includes `infer:run` gets `B3OS_MODEL`, the node's default model, beside `OPENAI_BASE_URL` and `ANTHROPIC_BASE_URL` pointing at the node. A value you set in `env` wins. The node sets the model, and no request field changes it.

### Connections per sandbox

**512 open, 64 DNS lookups.** A sandbox may have 512 outbound connections open and 64 DNS queries in flight. More connections are refused; more queries are answered `SERVFAIL` at once.