---
title: Linux Sandboxes
description: Linux virtual machine sandboxes, their capabilities, use cases, and architecture.
sidebar:
label: Linux
---
Linux sandboxes are **Linux virtual machines (VMs)**. Each sandbox is a virtual machine, a microVM, that runs its own Linux kernel on shared physical hardware and has its own operating system, files, network connection, and fixed amount of processor, memory, and disk. The hardware enforces the boundary and isolation between sandboxes.
| **Term** | **Description** |
| -------------- | -------------------------------------------------------------------------------------------------------------- |
| **Sandbox** | An isolated Linux machine created on demand to run code. |
| **Host** | The physical server that runs many sandboxes at once. Daytona calls these servers runners. |
| **Guest** | The operating system running inside a sandbox, as opposed to the operating system of the host. |
| **Kernel** | The core of an operating system. It manages memory, processes, files, and devices. |
| **Hypervisor** | Software on the host that creates virtual machines and keeps them separated from each other and from the host. |
| **Image** | A packaged filesystem, such as `python:3.12-slim`, that defines what software a sandbox starts with. |
| **Snapshot** | A saved copy of a sandbox's memory and disk that new sandboxes resume from. |
| **Persistent** | A sandbox that keeps its disk across stop and start, and its memory across pause and resume. |
| **Spot** | A sandbox that runs on discounted capacity that Daytona can reclaim at any time. |
## Use cases
Sandboxes are used wherever code must run in a real environment, but you cannot trust the code or you cannot afford for it to affect anything else.
- **Code execution for AI agents**: an agent writes code, runs it in a sandbox, reads the output, and decides what to do next. The sandbox gives the agent a real shell and filesystem while keeping its actions away from your infrastructure.
- **Coding agents**: an agent clones a repository, installs dependencies, edits files, runs the test suite, and opens a pull request, all inside one sandbox.
- **Reinforcement learning (RL)**: training runs create very large numbers of identical environments, run one episode in each, score the result, and discard the environment. Fast creation from a shared snapshot keeps the cost of each environment low.
- **Evaluation and benchmarks**: each test case or model run gets a clean, identical machine, so results do not depend on leftover state from a previous run.
- **Code interpreters and data analysis**: a chat application runs user or model-generated Python against uploaded files and returns tables, charts, and results.
- **Untrusted user code**: online coding platforms, grading systems, and plugin hosts run code submitted by users without exposing other users or the service.
- **Computer-use agents**: an agent operates a graphical desktop, a browser, or desktop applications through screenshots and input events.
- **Development environments**: a developer gets a preconfigured machine from an image, connects over SSH or from an editor, and previews web applications through a URL.
## Create a Linux sandbox
Create a Linux sandbox from the dashboard or programmatically.
1. Go to [Daytona Sandboxes ↗](https://app.daytona.com/dashboard/sandboxes)
2. Click
3. Select
4. Click
```python
from daytona import Daytona
daytona = Daytona()
sandbox = daytona.v2.create()
```
The following example sets the remaining parameters:
```python
from daytona import Daytona
from daytona.v2 import PortMapping
daytona = Daytona()
sandbox = daytona.v2.create(
name="my-sandbox",
labels={"team": "research", "run": "42"},
cpu=2,
memory=4,
disk=20,
ports=[PortMapping(port=8080), PortMapping(port=5353, proto="udp")],
network_policy={"block_all": True, "allow_domains": ["pypi.org", "*.github.com"]},
env={"LOG_LEVEL": "debug"},
secrets=["GITHUB_TOKEN"],
spot=False,
region="us",
cpu_arch="amd64",
cpu_type="zen5",
lifecycle_policy={
"idle_expiry_seconds": 3600,
"on_idle_timeout": "delete",
"timeout_seconds": 604800,
"on_timeout": "delete",
},
idempotency_key="run-42-create",
wait_seconds=120,
)
```
| **Parameter** | **Type** | **Description** |
| ----------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `image` | str | Sets the registered image that the sandbox starts from, by name or `img_` ID. This is the first positional argument. If omitted, the sandbox boots the platform default image. |
| `name` | str | Sets the display name. If omitted, a name is generated. Within one [workload cell](/docs/v2/regions), a create with the same name and different arguments is refused until the first sandbox is deleted. |
| `labels` | Dict\[str, str\] | Attaches key-value metadata to the sandbox. |
| `cpu` | float | Sets the guaranteed CPU cores as a float. The value is raised to at least one core per 4 GiB of guaranteed memory. The default is 0.125. |
| `memory` | int | Sets the guaranteed memory in GiB. The default is 1 GiB. |
| `disk` | int | Sets the guaranteed writable disk in GiB. The default is 512 MiB. |
| `resources` | Resources | Sets CPU, memory, and disk in one object, in place of `cpu`, `memory`, and `disk`. It also carries `cpu_max`, the vCPU limit, which defaults to 16, and `memory_max`, the memory limit in GiB, which defaults to 32. |
| `ports` | Sequence\[PortMapping\] | Forwards inbound ports to the sandbox. Each mapping has a `port` and a `proto`, which defaults to `tcp`. |
| `env` | Dict\[str, str\] | Sets environment variables inside the sandbox. |
| `secrets` | Sequence\[str\] | Attaches project secrets by name. The sandbox sees each secret as an opaque placeholder. |
| `network_policy` | NetworkPolicyInput | Sets the outbound network policy with `block_all`, `allow_domains`, and `allow_cidrs`. You can change it after create. |
| `spot` | bool | Runs the sandbox on discounted capacity that can be reclaimed. The default is `False`. |
| `region` | str | Sets the region or global region slug. The default is the project default. |
| `cpu_arch` | str | Sets the CPU architecture, `amd64` or `arm64`. The default is `amd64`. |
| `cpu_type` | str | Sets the CPU hardware tier slug: `zen3`, `zen4`, `zen5`, `zen5c`, `arrowlake1`, `arrowlake2`, `graviton`, `graviton3`, and `graviton4`. The slug also sets the architecture. See [CPU types](#cpu-types). |
| `lifecycle_policy` | LifecyclePolicyConfig | Sets the lifecycle policy with `timeout_seconds` and `on_timeout`, and `idle_expiry_seconds` and `on_idle_timeout`. The action is `delete`. By default, there is no idle timeout, and the wall-clock timeout uses the project or platform default, if one is enabled. |
| `idempotency_key` | str | Makes a retried create in the same workload cell return the same sandbox. A create in another cell makes a separate sandbox. To keep creates in one region, set `region`. If `name` is set, the key is derived from it. Otherwise, each call generates a new key. |
| `wait_seconds` | int | Sets how many seconds create waits for the sandbox to start. The server holds the request for up to 3 seconds, and the SDK waits for the rest. `0` returns immediately. The default is 60. If the sandbox has not started in time, or fails, `create()` returns it without raising. Check `sandbox.state` before using it. |
```typescript
import { Daytona } from '@daytona/sdk'
const daytona = new Daytona()
const sandbox = await daytona.v2.create()
```
The following example sets the remaining parameters:
```typescript
import { Daytona } from '@daytona/sdk'
const daytona = new Daytona()
const sandbox = await daytona.v2.create({
name: 'my-sandbox',
labels: { team: 'research', run: '42' },
cpu: 2,
memory: 4,
disk: 20,
ports: [{ port: 8080 }, { port: 5353, proto: 'udp' }],
networkPolicy: { blockAll: true, allowDomains: ['pypi.org', '*.github.com'] },
env: { LOG_LEVEL: 'debug' },
secrets: ['GITHUB_TOKEN'],
spot: false,
region: 'us',
cpuArch: 'amd64',
cpuType: 'zen5',
lifecyclePolicy: {
idleExpirySeconds: 3600,
onIdleTimeout: 'delete',
timeoutSeconds: 604800,
onTimeout: 'delete',
},
idempotencyKey: 'run-42-create',
waitSeconds: 120,
})
```
| **Parameter** | **Type** | **Description** |
| ---------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `image` | string | Sets the registered image that the sandbox starts from, by name or `img_` ID. This is the first positional argument. If omitted, the sandbox boots the platform default image. |
| `name` | string | Sets the display name. If omitted, a name is generated. Within one [workload cell](/docs/v2/regions), a create with the same name and different arguments is refused until the first sandbox is deleted. |
| `labels` | Record\ | Attaches key-value metadata to the sandbox. |
| `cpu` | number | Sets the guaranteed CPU cores as a float. The value is raised to at least one core per 4 GiB of guaranteed memory. The default is 0.125. |
| `memory` | number | Sets the guaranteed memory in GiB. The default is 1 GiB. |
| `disk` | number | Sets the guaranteed writable disk in GiB. The default is 512 MiB. |
| `resources` | Resources | Sets CPU, memory, and disk in one object, in place of `cpu`, `memory`, and `disk`. It also carries `cpuMax`, the vCPU limit, which defaults to 16, and `memoryMax`, the memory limit in GiB, which defaults to 32. |
| `ports` | PortMapping\[\] | Forwards inbound ports to the sandbox. Each mapping has a `port` and a `proto`, which defaults to `tcp`. |
| `env` | Record\ | Sets environment variables inside the sandbox. |
| `secrets` | string\[\] | Attaches project secrets by name. The sandbox sees each secret as an opaque placeholder. |
| `networkPolicy` | NetworkPolicyInput | Sets the outbound network policy with `blockAll`, `allowDomains`, and `allowCidrs`. You can change it after create. |
| `spot` | boolean | Runs the sandbox on discounted capacity that can be reclaimed. The default is `false`. |
| `region` | string | Sets the region or global region slug. The default is the project default. |
| `cpuArch` | CpuArch | Sets the CPU architecture, `amd64` or `arm64`. The default is `amd64`. |
| `cpuType` | string | Sets the CPU hardware tier slug: `zen3`, `zen4`, `zen5`, `zen5c`, `arrowlake1`, `arrowlake2`, `graviton`, `graviton3`, and `graviton4`. The slug also sets the architecture. See [CPU types](#cpu-types). |
| `lifecyclePolicy` | LifecyclePolicyOptions | Sets the lifecycle policy with `timeoutSeconds` and `onTimeout`, and `idleExpirySeconds` and `onIdleTimeout`. The action is `delete`. By default, there is no idle timeout, and the wall-clock timeout uses the project or platform default, if one is enabled. |
| `idempotencyKey` | string | Makes a retried create in the same workload cell return the same sandbox. A create in another cell makes a separate sandbox. To keep creates in one region, set `region`. If `name` is set, the key is derived from it. Otherwise, each call generates a new key. |
| `waitSeconds` | number | Sets how many seconds create waits for the sandbox to start. The server holds the request for up to 3 seconds, and the SDK waits for the rest. `0` returns immediately. The default is 60. If the sandbox has not started in time, or fails, `create()` resolves with it without throwing. Check `sandbox.state` before using it. |
```bash
daytona sandbox create
```
The following example sets the remaining flags:
```bash
daytona sandbox create \
--name my-sandbox \
--label team=research --label run=42 \
--user root \
--cpu 2 --memory 4096 --disk 20480 \
--vcpus-max 8 --mem-max 16384 \
--port 8080 --port 5353/udp \
--block-all --allow-domain pypi.org --allow-domain '*.github.com' \
--env LOG_LEVEL=debug \
--secret GITHUB_TOKEN \
--region us \
--cpu-arch amd64 --cpu-type zen5 \
--idle-timeout 3600 --on-idle-timeout delete \
--timeout 604800 --on-timeout delete \
--idempotency-key run-42-create
```
| **Flag** | **Type** | **Description** |
| ------------------- | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--image` | string | Sets the registered image that the sandbox starts from, by name or `img_` ID. If omitted, the sandbox boots the platform default image. |
| `--name` | string | Sets the display name. If omitted, a name is generated. |
| `--label` | KEY=VALUE | Attaches a `KEY=VALUE` metadata label. Repeat the flag for more labels. |
| `--user` | string | Sets the default OS user inside the sandbox. The default is `root`. |
| `--cpu` | float | Sets the guaranteed CPU cores as a float. The value is raised to at least one core per 4 GiB of guaranteed memory. The default is 0.125. |
| `--vcpus` | int32 | Sets a whole vCPU count. It applies only if `--cpu` is absent. The default is 2. |
| `--memory` | int32 | Sets the guaranteed memory in MiB. The default is 1024. |
| `--disk` | int32 | Sets the guaranteed writable disk in MiB. The default is 512. |
| `--vcpus-max` | int32 | Sets the vCPU limit of the sandbox. The default is 16. |
| `--mem-max` | int32 | Sets the memory limit of the sandbox in MiB. The default is 32768. |
| `--disk-max` | int32 | Sets the writable disk limit of the sandbox in MiB. |
| `--port` | PORT\[/PROTO\] | Forwards an inbound port, with an optional protocol. Repeat the flag for more ports. |
| `--env` | KEY=VALUE | Sets an environment variable inside the sandbox. Repeat the flag for more variables. |
| `--secret` | string | Attaches a project secret by name. The sandbox sees it as an opaque placeholder. Repeat the flag for more secrets. |
| `--block-all` | bool | Denies all egress that is not explicitly allowed. You can change it after create. The default is `false`. |
| `--allow-domain` | string | Allows egress to a hostname or a `*.` wildcard domain. It implies `--block-all`. Repeat the flag for more domains. |
| `--allow-cidr` | string | Allows egress to an IPv4 address or CIDR block, on any port. It needs `--block-all` or `--allow-domain`. Repeat the flag for more addresses. |
| `--spot` | bool | Runs the sandbox on discounted capacity that can be reclaimed. The default is `false`. |
| `--region` | string | Sets the region or global region slug. The default is the project default. |
| `--cpu-arch` | string | Sets the CPU architecture, `amd64` or `arm64`. The default is `amd64`. |
| `--cpu-type` | string | Sets the CPU hardware tier slug: `zen3`, `zen4`, `zen5`, `zen5c`, `arrowlake1`, `arrowlake2`, `graviton`, `graviton3`, and `graviton4`. The slug also sets the architecture. See [CPU types](#cpu-types). |
| `--timeout` | int | Sets the wall-clock seconds until `--on-timeout` fires. The default is the organization or platform default, if one is enabled. |
| `--on-timeout` | string | Sets the action when `--timeout` elapses, `delete`. The default is `delete`. |
| `--idle-timeout` | int | Sets the idle seconds until `--on-idle-timeout` fires. Values below 60 are raised to 60. By default, there is no idle timeout. |
| `--on-idle-timeout` | string | Sets the action when `--idle-timeout` elapses, `delete`. It is required with `--idle-timeout`. |
| `--idempotency-key` | string | Makes a retried create return the same sandbox. |
| `--wait` | int | Sets how many seconds the server holds the create request for the sandbox to start, up to 3. The default is 3. The command then waits until the sandbox is running and prints it. The global `--no-wait` flag prints the create response immediately instead. |
| `--create-ttl` | int | Sets how many seconds the sandbox has to reach running before the server deletes it. `-1` sets the server maximum, 86400. The default is 3600. |
```bash
curl 'https://api.daytona.com/sandboxes' \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{}'
```
The following example sets the remaining fields:
```bash
curl 'https://api.daytona.com/sandboxes' \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{
"name": "my-sandbox",
"labels": { "team": "research", "run": "42" },
"user": "root",
"cpu": 2,
"memory_mib": 4096,
"disk_mib": 20480,
"vcpus_max": 8,
"memory_max_mib": 16384,
"ports": [{ "port": 8080 }, { "port": 5353, "proto": "udp" }],
"network_policy": { "block_all": true, "allow_domains": ["pypi.org", "*.github.com"] },
"env": { "LOG_LEVEL": "debug" },
"secrets": ["GITHUB_TOKEN"],
"spot": false,
"region": "us",
"cpu_arch": "amd64",
"cpu_type": "zen5",
"lifecycle_policy": {
"idle_expiry_seconds": 3600,
"on_idle_timeout": "delete",
"timeout_seconds": 604800,
"on_timeout": "delete"
},
"idempotency_key": "run-42-create"
}'
```
| **Field** | **Type** | **Description** |
| ----------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `image` | string | Sets the registered image that the sandbox starts from, by name or `img_` ID. If omitted, the sandbox boots the platform default image. |
| `name` | string | Sets the display name. If omitted, a name is generated. |
| `labels` | object | Attaches key-value metadata to the sandbox. |
| `user` | string | Sets the default OS user inside the sandbox. The default is `root`. |
| `cpu` | number | Sets the guaranteed CPU cores as a float. The value is raised to at least one core per 4 GiB of guaranteed memory. The default is 0.125. |
| `vcpus` | integer | Sets an integer CPU request. It applies only if `cpu` is absent. The default is 2. |
| `memory_mib` | integer | Sets the guaranteed memory in MiB. The default is 1024. |
| `disk_mib` | integer | Sets the guaranteed writable disk in MiB. The default is 512. |
| `vcpus_max` | integer | Sets the vCPU limit of the sandbox. The default is 16. |
| `memory_max_mib` | integer | Sets the memory limit of the sandbox in MiB. The default is 32768. |
| `ports` | array | Forwards inbound ports to the sandbox. Each entry has a `port` and a `proto`, which defaults to `tcp`. |
| `env` | object | Sets environment variables inside the sandbox. |
| `secrets` | array | Attaches project secrets by name. The sandbox sees each secret as an opaque placeholder. |
| `network_policy` | object | Sets the outbound network policy with `block_all`, `allow_domains`, and `allow_cidrs`. You can change it after create. |
| `spot` | boolean | Runs the sandbox on discounted capacity that can be reclaimed. The default is `false`. |
| `region` | string | Sets the region or global region slug. The default is the project default. |
| `cpu_arch` | string | Sets the CPU architecture, `amd64` or `arm64`. The default is `amd64`. |
| `cpu_type` | string | Sets the CPU hardware tier slug: `zen3`, `zen4`, `zen5`, `zen5c`, `arrowlake1`, `arrowlake2`, `graviton`, `graviton3`, and `graviton4`. The slug also sets the architecture. See [CPU types](#cpu-types). |
| `lifecycle_policy` | object | Sets the lifecycle policy with `timeout_seconds` and `on_timeout`, and `idle_expiry_seconds` and `on_idle_timeout`. The action is `delete`. By default, there is no idle timeout, and the wall-clock timeout uses the project or platform default, if one is enabled. |
| `idempotency_key` | string | Makes a retried create return the same sandbox. You can also send it as the `Idempotency-Key` header. |
| `create_timeout_seconds` | integer | Sets how many seconds the sandbox has to reach running before it is deleted. `-1` sets the maximum, 86400. The default is 3600. |
| `wait_seconds` | integer | Sets how many seconds the server holds the request for the sandbox to start. `0` returns immediately. The default is 3. |
The response has the following fields:
| **Field** | **Description** |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `status` | The status is often `pending`, because the server holds the request for at most 3 seconds by default. Poll `GET /sandboxes/{sandboxId}?wait=running` until the sandbox is running. |
| `access_token` | The access token is returned only once. An idempotent replay returns `null`. |
### Persistent
A persistent Linux sandbox keeps its disk on network storage instead of on its host, so it can shut down and boot again on another host in its region. A stopped sandbox keeps its filesystem, and its processes end. A paused sandbox also keeps its memory, and resumes with its processes where they left off. A stopped sandbox is archived after an interval: its disk moves to object storage, and the next start restores it first. See [lifecycle](#lifecycle) for stop, start, pause, resume, fork, and archive.
Persistent Linux sandboxes must be enabled for your organization. Contact [support@daytona.io](mailto:support@daytona.io).
```bash
curl 'https://api.daytona.com/sandboxes' \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{"persistent": true}'
```
| **Field** | **Type** | **Description** |
| ---------------- | ------------- | ------------------------------------------------------------------------ |
| `persistent` | `boolean` | Keeps the disk across stop and start. The default is `false`. |
- The [timers](#timeouts) can fire `stop`, `pause`, or `delete`. An omitted `on_timeout` defaults to `pause`.
### Spot
Linux sandboxes run on reserved capacity by default. A spot Linux sandbox runs on discounted capacity that Daytona can reclaim at any time to free resources for full-price sandboxes. Spot multiplies the CPU, memory, and disk price by 0.7. Apart from price and reclaim, a spot Linux sandbox supports the same images, resources, volumes, and lifecycle operations as any other Linux sandbox.
A reclaim is immediate, with no advance notice and no grace period. The sandbox moves to `deleting`, then `deleted`. Only data on a [volume](/docs/v2/volumes) or in other storage outside the sandbox remains.
```python
from daytona import Daytona
daytona = Daytona()
sandbox = daytona.v2.create("python-3.12", spot=True)
```
| **Parameter** | **Type** | **Description** |
| ------------- | -------- | --------------- |
| `spot` | `bool` | Places the sandbox on discounted, reclaimable capacity. The default is `False`. |
```typescript
import { Daytona } from '@daytona/sdk'
const daytona = new Daytona()
const sandbox = await daytona.v2.create('python-3.12', { spot: true })
```
| **Parameter** | **Type** | **Description** |
| ------------- | -------- | --------------- |
| `spot` | `boolean` | Places the sandbox on discounted, reclaimable capacity. The default is `false`. |
```bash
daytona sandbox create --image python-3.12 --spot
```
| **Flag** | **Type** | **Description** |
| -------- | -------- | --------------- |
| `--spot` | `bool` | Places the sandbox on discounted, reclaimable capacity. The default is `false`. |
```bash
curl 'https://api.daytona.com/sandboxes' \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{"image": "python-3.12", "spot": true}'
```
| **Field** | **Type** | **Description** |
| --------- | -------- | --------------- |
| `spot` | `boolean` | Places the sandbox on discounted, reclaimable capacity. The default is `false`. |
- Set `spot` when you create the sandbox. You cannot change it on an existing sandbox.
- See [preemption](/docs/v2/preemption) for the reclaim policy.
### CPU types
A CPU type is a processor model that a Linux sandbox can request when it is created. Each type belongs to one architecture, amd64 or arm64, and has a tier: its rank within that architecture, starting at 1 for the lowest. Requesting a CPU type also sets the sandbox's architecture.
The CPU type list contains every type that a create request accepts, whether or not a runner provides it. To see which types a region can serve, add the region. A type is available in a region when a running runner there provides it. When no runner provides the type itself, a runner with a higher tier of the same architecture can serve it as a fallback. Availability reflects the runners that are live at request time. [List regions](/docs/v2/regions#list-regions) gives the region slugs.
```bash
# List CPU types
daytona cpu-type list
# Check CPU type availability in a region
daytona cpu-type list --region us-west-1
```
| **Flag** | **Type** | **Description** |
| ---------- | -------- | ------------------------------------------------------------------------------------- |
| `--region` | string | Sets one region slug. Without it, the command lists CPU types without availability. With it, the table output adds an `AVAILABLE` column. The column shows `exact` if a runner in the region provides the type, `fallback` if a higher tier of the same architecture serves it, and `-` otherwise. |
- The table output has the columns `ID`, `NAME`, `ARCH`, and `TIER`.
```bash
# List CPU types
curl 'https://api.daytona.com/cpu-catalog' \
--header 'Authorization: Bearer YOUR_API_KEY'
# Check CPU type availability in a region
curl 'https://api.daytona.com/cpu-catalog?region=us-west-1' \
--header 'Authorization: Bearer YOUR_API_KEY'
```
| **Field** | **Type** | **Description** |
| ---------- | -------- | ---------------------------------------------------------------------------------------------------- |
| `region` | string | Sets a comma-separated list of region slugs, at most 64. The default is every region that the answering workload cell hosts. |
The response has the following fields:
| **Field** | **Description** |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cpu_types` | Lists every CPU type with `id`, `name`, `cpu_arch`, and `tier`, and whether the requested regions can serve it: `available`, `exact_regions`, and `fallback_regions`. |
| `arches` | Lists each CPU architecture and the requested regions where it is available. |
| `regions` | Lists the covered regions. In each region, `default_arch` and `default_type` are the values that a create request that sets neither uses. `default_type` is `null` when the region sets none. |
## Filesystem snapshot
A filesystem snapshot saves the filesystem of a running Linux sandbox as an [image](/docs/v2/images). The sandbox keeps running, and new sandboxes boot from the image with the captured files. Unlike a [memory snapshot](#memory-snapshot), a filesystem snapshot holds no processes or memory.
The capture runs in the background: the image starts as pending and becomes ready when the capture finishes. A named image is permanent until you delete it. An unnamed image is anonymous. Daytona deletes an anonymous image after its idle window passes without a sandbox create from it. The idle window is the server maximum of 7 days by default.
```python
from daytona import Daytona
daytona = Daytona()
sandbox = daytona.v2.create("python-3.12")
sandbox.process.run("pip install requests")
# Capture the filesystem; the sandbox keeps running
image = sandbox.snapshot_filesystem(name="my-env")
# Wait until the capture is ready, then boot new sandboxes from it
while image.status not in ("ready", "failed"):
image = daytona.v2.images.get(image.id, wait="ready")
if image.status == "failed":
raise RuntimeError(image.error)
clone = daytona.v2.create("my-env")
```
| **Parameter** | **Type** | **Description** |
| ------------- | -------- | --------------- |
| `name` | `str` | Sets the image name, which must be unique in the project. The default is `None`, which makes the image anonymous. |
| `idle` | `int` | Sets how many seconds an anonymous image can go without a sandbox create before deletion. It applies only to anonymous images. `-1` sets the maximum. The default is the server maximum. |
```typescript
import { Daytona } from '@daytona/sdk'
const daytona = new Daytona()
const sandbox = await daytona.v2.create('python-3.12')
await sandbox.process.run('pip install requests')
// Capture the filesystem; the sandbox keeps running
let image = await sandbox.snapshotFilesystem({ name: 'my-env' })
// Wait until the capture is ready, then boot new sandboxes from it
while (image.status !== 'ready' && image.status !== 'failed') {
image = await daytona.v2.images.get(image.id, { wait: 'ready' })
}
if (image.status === 'failed') throw new Error(image.error ?? 'image capture failed')
const clone = await daytona.v2.create('my-env')
```
| **Parameter** | **Type** | **Description** |
| ------------- | -------- | --------------- |
| `name` | `string` | Sets the image name, which must be unique in the project. The default is `undefined`, which makes the image anonymous. |
| `idle` | `number` | Sets how many seconds an anonymous image can go without a sandbox create before deletion. It applies only to anonymous images. `-1` sets the maximum. The default is the server maximum. |
```bash
# Capture the filesystem and wait until the image is ready
daytona image capture {sandboxId} --name my-env
# Boot a new sandbox from the captured filesystem
daytona sandbox create --image my-env
```
| **Flag** | **Type** | **Description** |
| -------- | -------- | --------------- |
| `--name` | `string` | Sets the image name, which must be unique in the project. Without a name, the image is anonymous. |
| `--idle` | `int` | Sets how many seconds an anonymous image can go without a sandbox create before deletion. It applies only to anonymous images. `-1` sets the maximum. The default is the server maximum. |
| `--timeout` | `string` | Sets how long the command waits for the image to be ready. The default is `10m`. |
| `--no-wait` | `boolean` | Returns once the capture is queued, without waiting for the image to be ready. |
```bash
# Capture the filesystem; the sandbox keeps running
curl 'https://api.daytona.com/sandboxes/{sandboxId}/images' \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{"name": "my-env"}'
# Block until the capture is ready
curl 'https://api.daytona.com/images/{imageId}?wait=ready' \
--header 'Authorization: Bearer YOUR_API_KEY'
# Boot a new sandbox from the captured filesystem
curl 'https://api.daytona.com/sandboxes' \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{"image": "my-env"}'
```
| **Field** | **Type** | **Description** |
| --------- | -------- | --------------- |
| `name` | `string` | Sets the image name, which must be unique in the project. Without a name, the image is anonymous. |
| `idle` | `integer` | Sets how many seconds an anonymous image can go without a sandbox create before deletion. It applies only to anonymous images. `-1` sets the maximum. The default is the server maximum. |
- `snapshot_filesystem` and `snapshotFilesystem` return the pending image and do not wait for the capture. `daytona image capture` waits unless you pass `--no-wait`.
- The API call requires the `write:images` permission.
- See [capture images](/docs/v2/images#capture-images) for promoting and deleting captured images.
## Memory snapshot
A memory snapshot saves the memory and disk of a running Linux sandbox under a name. A sandbox restored from the snapshot resumes the captured processes and memory instead of booting. The restored sandbox gets the CPU, memory, and disk of the source sandbox. Deleting the source sandbox does not delete its snapshots.
The capture runs in the background: the snapshot starts as pending and becomes ready when the capture finishes. A snapshot restores only in the region of its source sandbox, on the host that captured it, and the restore fails while that host is unavailable.
```python
from daytona import Daytona
daytona = Daytona()
sandbox = daytona.v2.create("python-3.12")
# Capture the memory and disk of the running sandbox
snapshot = sandbox.create_snapshot("my-snapshot")
# Wait until the capture is ready
while snapshot.status not in ("ready", "failed"):
snapshot = daytona.v2.snapshots.get(snapshot.id, wait="ready")
if snapshot.status == "failed":
raise RuntimeError(snapshot.error)
# Resume the captured processes and memory in a new sandbox
restored = daytona.v2.create_from_snapshot("my-snapshot")
```
| **Parameter** | **Type** | **Description** |
| ------------- | -------- | --------------- |
| `name` | `str` | Sets the snapshot name, 1 to 128 characters of letters, digits, `.`, `_`, and `-`. Snapshots and images in the project share one name space. A name in use fails with `409`. This parameter is required. |
| `snapshot` | `str` | Sets the snapshot that `create_from_snapshot()` restores from, by name or by ID, `snap_...`. This parameter is required. |
```typescript
import { Daytona } from '@daytona/sdk'
const daytona = new Daytona()
const sandbox = await daytona.v2.create('python-3.12')
// Capture the memory and disk of the running sandbox
let snapshot = await sandbox.createSnapshot('my-snapshot')
// Wait until the capture is ready
while (snapshot.status !== 'ready' && snapshot.status !== 'failed') {
snapshot = await daytona.v2.snapshots.get(snapshot.id, { wait: 'ready' })
}
if (snapshot.status === 'failed') throw new Error(snapshot.error ?? 'snapshot capture failed')
// Resume the captured processes and memory in a new sandbox
const restored = await daytona.v2.createFromSnapshot('my-snapshot')
```
| **Parameter** | **Type** | **Description** |
| ------------- | -------- | --------------- |
| `name` | `string` | Sets the snapshot name, 1 to 128 characters of letters, digits, `.`, `_`, and `-`. Snapshots and images in the project share one name space. A name in use fails with `409`. This parameter is required. |
| `snapshot` | `string` | Sets the snapshot that `createFromSnapshot()` restores from, by name or by ID, `snap_...`. This parameter is required. |
```bash
# Capture the memory and disk of the running sandbox and wait until it is ready
daytona snapshot create {sandboxId} --name my-snapshot
# Resume the captured processes and memory in a new sandbox
daytona sandbox create-from-snapshot my-snapshot
```
| **Flag** | **Type** | **Description** |
| -------- | -------- | --------------- |
| `--name` | `string` | Sets the snapshot name. This flag is required. |
| `--timeout` | `string` | Sets how long the command waits for the snapshot to be `ready`. The default is `10m`. |
| `--no-wait` | `boolean` | Returns once the capture is queued, without waiting for `ready`. |
```bash
# Capture the memory and disk of the running sandbox
curl 'https://api.daytona.com/sandboxes/{sandboxId}/snapshots' \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{"name": "my-snapshot"}'
# Block until the capture is ready
curl 'https://api.daytona.com/snapshots/{snapshotId}?wait=ready&timeout_ms=60000' \
--header 'Authorization: Bearer YOUR_API_KEY'
# Resume the captured processes and memory in a new sandbox
curl 'https://api.daytona.com/sandboxes/from-snapshot' \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{"snapshot": "my-snapshot"}'
```
| **Field** | **Type** | **Description** |
| --------- | -------- | --------------- |
| `name` | `string` | Sets the snapshot name, 1 to 128 characters of letters, digits, `.`, `_`, and `-`. Snapshots and images in the project share one name space. A name in use fails with `409`. This field is required. |
| `snapshot` | `string` | Sets the snapshot that `POST /sandboxes/from-snapshot` restores from, by name or by ID, `snap_...`. This field is required. |
- The source sandbox must be running and served from a warm template.
- The snapshot kind is `full`: memory and disk. Attached volumes are not included.
- A restored sandbox is never spot.
- See [snapshots](/docs/v2/snapshots) for the restore options and for listing and deleting snapshots.
## Filesystem persistence
Filesystem persistence keeps the contents of a sandbox's disk: files, installed packages, cloned repositories, and build artifacts. A sandbox with a preserved filesystem starts with its environment intact, with nothing to reinstall or rebuild.
A Linux sandbox keeps its filesystem until it is deleted. A [persistent](#persistent) Linux sandbox also keeps its filesystem across [stop and start](#stop--start), [pause and resume](#pause--resume), and [archive](#archive). [Filesystem snapshots](#filesystem-snapshot) keep the filesystem beyond the sandbox, and new sandboxes boot from them.
| **Sandbox** | **Filesystem persistence** |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Ephemeral** | The filesystem stays on the host while the sandbox exists. Deleting the sandbox or losing its host discards it. Use filesystem snapshots to capture the filesystem. |
| **Persistent** | The filesystem is kept on network storage through stop and start. Archive moves it to object storage, and starting an archived sandbox restores it. Use filesystem snapshots to capture the filesystem. |
```python
from daytona import Daytona
daytona = Daytona()
sandbox = daytona.v2.get("{sandboxId}")
# Write a file to the filesystem
sandbox.fs.write_text("setup.log", "done")
# Stop ends the processes and keeps the filesystem
sandbox.stop()
sandbox.wait(until="stopped")
# Start boots the sandbox from its filesystem
sandbox.start()
print(sandbox.fs.read_text("setup.log")) # done
```
```typescript
import { Daytona } from '@daytona/sdk'
const daytona = new Daytona()
const sandbox = await daytona.v2.get('{sandboxId}')
// Write a file to the filesystem
await sandbox.fs.writeText('setup.log', 'done')
// Stop ends the processes and keeps the filesystem
await sandbox.stop()
await sandbox.wait({ until: 'stopped' })
// Start boots the sandbox from its filesystem
await sandbox.start()
console.log(await sandbox.fs.readText('setup.log')) // done
```
## Memory persistence
Memory persistence keeps the runtime state of a sandbox: running processes, open connections, and everything loaded in RAM. A sandbox with preserved memory continues from the point it was frozen, with processes still running, instead of starting from a clean boot.
A Linux sandbox keeps its memory while it runs. A [persistent](#persistent) Linux sandbox also keeps its memory across [pause and resume](#pause--resume) and [forks](#fork). [Memory snapshots](#memory-snapshot) keep memory beyond the sandbox. Memory is cleared on every stop.
| **Sandbox** | **Memory persistence** |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Ephemeral** | Memory persists only while the sandbox is running. Use memory snapshots to capture memory and processes. |
| **Persistent** | Memory is kept through pause and resume: pausing saves the memory and processes, and resuming continues them from the point they were saved. Use forks or memory snapshots to capture memory. |
```python
from daytona import Daytona
daytona = Daytona()
sandbox = daytona.v2.get("{sandboxId}")
# Start a server that runs in the background
sandbox.process.start("python3 -m http.server 8000")
# Pause saves the memory and processes
sandbox.pause()
sandbox.wait(until="paused")
# Resume continues the server from the point where the sandbox paused
sandbox.resume()
```
```typescript
import { Daytona } from '@daytona/sdk'
const daytona = new Daytona()
const sandbox = await daytona.v2.get('{sandboxId}')
// Start a server that runs in the background
await sandbox.process.start('python3 -m http.server 8000')
// Pause saves the memory and processes
await sandbox.pause()
await sandbox.wait({ until: 'paused' })
// Resume continues the server from the point where the sandbox paused
await sandbox.resume()
```
## Lifecycle
Every Linux sandbox moves through a lifecycle. A Linux sandbox can have several different states. Each state reflects the status of your sandbox. A Linux sandbox transitions between states in response to user actions, or automatically when one of its [timeouts](#timeouts) elapses.
Every Linux sandbox supports wait for state, delete, timeouts, and lifecycle policy updates. A Linux sandbox keeps its filesystem and memory until it is deleted, or until its host fails: the sandbox then moves to error (lost in the CLI and API), and its local filesystem and memory are gone. A [persistent](#persistent) Linux sandbox also supports [stop / start](#stop--start), [pause / resume](#pause--resume), [fork](#fork), and [archive](#archive).
The following tables list the states of a Linux sandbox and the transitions between them. The SDKs report the states in the **State** column. The CLI and API report the more detailed status in the **API status** column.
| **State** | **API status** | **Description** |
| ---------------- | ------------------------------ | ------------------------------------------------------------------------------- |
| **`queued`** | **`queued`** | The create request is recorded and waits to be published for placement. |
| **`creating`** | **`pending`**, **`assigned`** | The create request is accepted, and the sandbox is queued for and placed on a host. |
| **`starting`** | **`booting`** | The microVM is booting and will be ready to use. |
| **`started`** | **`running`** | The sandbox is running and ready to accept requests. |
| **`pausing`** | **`pausing`** | A persistent sandbox is saving its memory and processes. |
| **`paused`** | **`paused`** | A persistent sandbox has saved its memory and processes, and its virtual machine is shut down. |
| **`stopping`** | **`stopping`** | A persistent sandbox is shutting down. |
| **`stopped`** | **`stopped`** | A persistent sandbox is shut down, and its disk is kept. |
| **`destroying`** | **`deleting`** | The sandbox is being deleted. |
| **`destroyed`** | **`deleted`** | The sandbox and its storage are removed. |
| **`error`** | **`failed`**, **`lost`** | The sandbox could not boot, hit an unrecoverable error, or its host was lost. |
| **`unknown`** | | The SDK does not recognize the status the API reports. |
A sandbox can transition between states in response to various actions. The following table lists the initial state, target state, and trigger for the transition.
| **Initial state** | **Target state** | **Trigger** |
| ----------------- | ---------------- | ---------------------------------------------------------------------------------- |
| **`queued`** | **`creating`** | The create request is published for placement. |
| **`creating`** | **`starting`** | The sandbox is placed on a host, the host prepares its image, and the microVM boots. |
| **`starting`** | **`started`** | The sandbox finishes booting and accepts requests. |
| **`started`** | **`stopping`** | A stop is requested on a persistent sandbox, or a timer fires the stop action. |
| **`stopping`** | **`stopped`** | The virtual machine shuts down, and the disk is kept. |
| **`started`** | **`pausing`** | A pause is requested on a persistent sandbox, or a timer fires the pause action. |
| **`pausing`** | **`paused`** | The memory and processes are saved, and the virtual machine shuts down. |
| **`stopped`**, **`paused`** | **`creating`** | A start or resume is requested, and the sandbox is placed on a host. |
| **`creating`** | **`started`** | A resumed sandbox continues from its saved memory. |
| any state | **`destroying`** | A delete is requested, a timeout elapses, or the platform reclaims a spot sandbox. |
| **`destroying`** | **`destroyed`** | The sandbox is removed and its resources are released. |
| any active state | **`error`** | The sandbox fails to boot, hits an unrecoverable error, or its host is lost. |
### Wait for state
Wait until a Linux sandbox reaches a target state. The wait stops early when the sandbox reaches a state from which the target is no longer reachable, such as error or destroyed. The SDKs use the states in the [sandbox states](#lifecycle) table, so the SDK started state corresponds to the running status in the CLI and API.
```python
# Block until the sandbox is started; returns the sandbox
sandbox.wait(until="started", timeout=60)
# Block until the sandbox is in one of the listed states
sandbox.wait_for_state(["started"], timeout=60)
```
| **Parameter** | **Type** | **Description** |
| ------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `until` | `str` | Sets the one state that `wait()` waits for. `wait_for_state()` takes a list and returns on any of its states. The default is `"started"`. |
| `timeout` | `float` | Sets the wait limit in seconds. `None` or `0` waits without a limit. When the timeout elapses, both methods raise `RequestTimeoutError`. The default is `60` for `wait()` and `None` for `wait_for_state()`. |
- `wait()` and `wait_for_state()` raise `SandboxTerminalStateError` when the sandbox reaches `destroying`, `destroyed`, or `error` before a target state.
- Pass `terminal_states` to `wait_for_state()` to change the set of terminal states.
```typescript
// Block until the sandbox is started; timeout is seconds, returns the sandbox
await sandbox.wait({ until: 'started', timeout: 60 })
// Block until the sandbox is in one of the listed states; timeout is milliseconds
await sandbox.waitForState(['started'], { timeout: 60_000 })
```
| **Parameter** | **Type** | **Description** |
| ------------- | -------- | -------------------------------------------------------------------------------------------------------------------------- |
| `until` | `SandboxWaitState \| SandboxWaitState[]` | Sets one state or a list of states. `wait()` returns on any of them. The default is `'started'`. |
| `timeout` | `number` | `wait()`: seconds, default `60`. `waitForState()`: milliseconds, default no limit. `0` waits without a limit in both. When the timeout elapses, both throw `RequestTimeoutError`. |
- `wait()` and `waitForState()` throw `SandboxTerminalStateError` when the sandbox reaches `destroying`, `destroyed`, or `error` before a target state.
- Pass `terminalStates` to `waitForState()` to change the set of terminal states.
```bash
# Block until the sandbox is running, or the timeout elapses
daytona sandbox wait {sandboxId} --for running --timeout 60s
```
| **Flag** | **Type** | **Description** |
| -------- | -------- | --------------- |
| `--for` | `string` | Sets the state to wait for. The default is `running`. |
| `--timeout` | `string` | Sets how long the command waits. The default is `10m`. |
```bash
# Long-poll until the sandbox is running, a terminal state, or the timeout elapses
curl 'https://api.daytona.com/sandboxes/{sandboxId}?wait=running&timeout_ms=60000' \
--header 'Authorization: Bearer YOUR_API_KEY'
# Long-poll until the sandbox is exactly deleted; wait_exact skips the transient deleting state
curl 'https://api.daytona.com/sandboxes/{sandboxId}?wait_exact=deleted&timeout_ms=60000' \
--header 'Authorization: Bearer YOUR_API_KEY'
```
| **Field** | **Type** | **Description** |
| ------------ | --------- | ----------------------------------------------------------------------------------------------------------- |
| `wait` | `string` | Blocks the response until the sandbox reaches this state or a terminal state. The wait also ends on `deleting`, `deleted`, `failed`, or `lost`. There is no default. |
| `wait_exact` | `string` | Blocks the response until the sandbox reaches exactly this state. Only `failed` and `lost` also end the wait. There is no default. |
| `timeout_ms` | `integer` | Sets the wait limit in milliseconds, at most `60000`. When the limit elapses, the response is `200` with the current sandbox. Check `status` in the response. The default is `30000`. |
### Stop / start
Stop a persistent Linux sandbox to shut down its virtual machine and keep its disk. Processes do not survive a stop. Start boots the sandbox from the same disk, and restores an archived disk first.
```python
from daytona import Daytona
daytona = Daytona()
sandbox = daytona.v2.get("{sandboxId}")
# Shut down the virtual machine and keep the disk
sandbox.stop()
sandbox.wait(until="stopped")
# Boot from the same disk and wait until the sandbox is started
sandbox.start(timeout=120)
# Stop a sandbox by ID, without fetching it first
daytona.v2.stop("{sandboxId}")
# Start a stopped sandbox by ID
daytona.v2.start("{sandboxId}", timeout=120)
```
- `stop()` returns once the stop is accepted. `wait(until="stopped")` waits until the sandbox is stopped.
- `start()` waits until the sandbox is started. `timeout` is in seconds, and the default is `60`.
- `start()` on a paused sandbox resumes it.
```typescript
import { Daytona } from '@daytona/sdk'
const daytona = new Daytona()
const sandbox = await daytona.v2.get('{sandboxId}')
// Shut down the virtual machine and keep the disk
await sandbox.stop()
await sandbox.wait({ until: 'stopped' })
// Boot from the same disk and wait until the sandbox is started
await sandbox.start({ timeout: 120_000 })
// Stop a sandbox by ID, without fetching it first
await daytona.v2.stop('{sandboxId}')
// Start a stopped sandbox by ID
await daytona.v2.start('{sandboxId}', { timeout: 120_000 })
```
- `stop()` returns once the stop is accepted. `wait({ until: 'stopped' })` waits until the sandbox is stopped.
- `start()` waits until the sandbox is started. `timeout` is in milliseconds, and the default is `60_000`.
- `start()` on a paused sandbox resumes it.
```bash
# Shut down the virtual machine and keep the disk
daytona sandbox stop {sandboxId}
# Boot from the same disk
daytona sandbox start {sandboxId}
```
- Each command waits until the sandbox is stopped or running. The global `--no-wait` flag returns once the operation is accepted.
```bash
# Shut down the virtual machine and keep the disk
curl 'https://api.daytona.com/sandboxes/{sandboxId}/stop' \
--request POST \
--header 'Authorization: Bearer YOUR_API_KEY'
# Boot from the same disk
curl 'https://api.daytona.com/sandboxes/{sandboxId}/start' \
--request POST \
--header 'Authorization: Bearer YOUR_API_KEY'
```
- Both requests return `202` once the operation is accepted.
- A stop returns `409` when the sandbox is not persistent.
- A start on a paused sandbox discards its saved memory and boots from the disk.
### Pause / resume
Pause a running persistent Linux sandbox to save its memory and processes and shut down its virtual machine. Resume continues the sandbox from the saved memory, with its processes running. A sandbox with attached volumes cannot be paused.
```python
from daytona import Daytona
daytona = Daytona()
sandbox = daytona.v2.get("{sandboxId}")
# Save the memory and processes, then shut down the virtual machine
sandbox.pause()
sandbox.wait(until="paused")
# Continue from the saved memory and wait until the sandbox is started
sandbox.resume(timeout=120)
# Pause a sandbox by ID, without fetching it first
daytona.v2.pause("{sandboxId}")
# Resume a paused sandbox by ID
daytona.v2.resume("{sandboxId}", timeout=120)
```
- `pause()` returns once the pause is accepted. `wait(until="paused")` waits until the sandbox is paused.
- `resume()` waits until the sandbox is started. `timeout` is in seconds, and the default is `60`.
```typescript
import { Daytona } from '@daytona/sdk'
const daytona = new Daytona()
const sandbox = await daytona.v2.get('{sandboxId}')
// Save the memory and processes, then shut down the virtual machine
await sandbox.pause()
await sandbox.wait({ until: 'paused' })
// Continue from the saved memory and wait until the sandbox is started
await sandbox.resume({ timeout: 120_000 })
// Pause a sandbox by ID, without fetching it first
await daytona.v2.pause('{sandboxId}')
// Resume a paused sandbox by ID
await daytona.v2.resume('{sandboxId}', { timeout: 120_000 })
```
- `pause()` returns once the pause is accepted. `wait({ until: 'paused' })` waits until the sandbox is paused.
- `resume()` waits until the sandbox is started. `timeout` is in milliseconds, and the default is `60_000`.
```bash
# Save the memory and processes, then shut down the virtual machine
daytona sandbox pause {sandboxId}
# Continue from the saved memory
daytona sandbox resume {sandboxId}
```
- Each command waits until the sandbox is paused or running. The global `--no-wait` flag returns once the operation is accepted.
```bash
# Save the memory and processes, then shut down the virtual machine
curl 'https://api.daytona.com/sandboxes/{sandboxId}/pause' \
--request POST \
--header 'Authorization: Bearer YOUR_API_KEY'
# Continue from the saved memory
curl 'https://api.daytona.com/sandboxes/{sandboxId}/resume' \
--request POST \
--header 'Authorization: Bearer YOUR_API_KEY'
```
- Both requests return `202` once the operation is accepted.
- A pause returns `409` when the sandbox is not persistent, has attached volumes, or is not running.
- A resume returns `503` when no host in the region can take the sandbox now. Retry the request.
### Fork
Fork a persistent Linux sandbox to copy it into a new, independent sandbox in the same region. By default, a fork copies the memory and the disk, and continues the running processes of the source. A disk-only fork clones the disk, and the new sandbox boots fresh. A fork of a stopped sandbox is always disk-only.
Only a fork of a running sandbox starts by itself. A memory fork of a paused sandbox stays paused, and a disk-only fork of a paused or stopped sandbox stays stopped. Resume or start these forks to run them.
```python
from daytona import Daytona
daytona = Daytona()
sandbox = daytona.v2.get("{sandboxId}")
# Copy the memory and disk, and wait until the fork settles
fork = sandbox.fork(name="my-sandbox-fork", timeout=120)
# Copy only the disk; the fork boots fresh
disk_fork = sandbox.fork(memory=False)
```
| **Parameter** | **Type** | **Description** |
| ------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------- |
| `name` | `str` | Sets the name of the fork. The default is the source name with `-fork` appended. |
| `memory` | `bool` | Copies the memory and running processes. `False` copies only the disk. The default is `True`. |
| `timeout` | `float` | Waits up to this many seconds for the fork to reach the state it settles in. `0` waits without a limit. By default, `fork()` returns once the fork is accepted. |
```typescript
import { Daytona } from '@daytona/sdk'
const daytona = new Daytona()
const sandbox = await daytona.v2.get('{sandboxId}')
// Copy the memory and disk, and wait until the fork settles
const fork = await sandbox.fork({ name: 'my-sandbox-fork', timeout: 120_000 })
// Copy only the disk; the fork boots fresh
const diskFork = await sandbox.fork({ memory: false })
```
| **Parameter** | **Type** | **Description** |
| ------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `name` | `string` | Sets the name of the fork. The default is the source name with `-fork` appended. |
| `memory` | `boolean` | Copies the memory and running processes. `false` copies only the disk. The default is `true`. |
| `timeout` | `number` | Waits up to this many milliseconds for the fork to reach the state it settles in. `0` waits without a limit. By default, `fork()` resolves once the fork is accepted. |
```bash
daytona sandbox fork {sandboxId} --name my-sandbox-fork
```
| **Flag** | **Type** | **Description** |
| ------------ | ------------ | ------------------------------------------------------------------------------------ |
| `--name` | `string` | Sets the name of the fork. The default is the source name with `-fork` appended. |
- The command copies the memory and the disk, and waits until the fork settles. The global `--no-wait` flag returns once the fork is accepted.
```bash
curl 'https://api.daytona.com/sandboxes/{sandboxId}/fork' \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{"name": "my-sandbox-fork", "memory": true}'
```
| **Field** | **Type** | **Description** |
| ------------ | ------------- | ----------------------------------------------------------------------------------------------------- |
| `name` | `string` | Sets the name of the fork. The default is the source name with `-fork` appended. |
| `memory` | `boolean` | Copies the memory and running processes. `false` copies only the disk. The default is `true`. |
- The request returns `202` with the fork ID and the status `pending`.
- The body is optional. Without it, the request makes a memory fork with the default name.
- A request returns `409` when the sandbox is not persistent or is in the middle of a transition.
### Archive
Archive a stopped persistent Linux sandbox to move its disk to object storage. A stopped sandbox is archived automatically when its archive interval elapses, and archive moves it at once. The next start restores the disk before the sandbox boots. Archiving is not available in every region, and a sandbox with attached volumes is not archived.
```python
from daytona import Daytona
daytona = Daytona()
sandbox = daytona.v2.get("{sandboxId}")
# Archive needs a stopped sandbox
sandbox.stop()
sandbox.wait(until="stopped")
# Move the disk to object storage now
sandbox.archive()
# Archive a stopped sandbox by ID, without fetching it first
daytona.v2.archive("{sandboxId}")
# Archive the sandbox 1 hour after it stops
sandbox.update_lifecycle_policy(archive_interval_seconds=3600)
```
| **Parameter** | **Type** | **Description** |
| ------------------------------ | --------- | ----------------------------------------------------------------------------------------------------------------------- |
| `archive_interval_seconds` | `int` | Sets how long a stopped sandbox waits before it is archived, from `60` to `2592000` (30 days). `0` sets the maximum. The default is `86400` (1 day). |
- `archive()` returns once the archive is accepted. `sandbox.archived` is `True` once the disk is in object storage.
- Archiving an archived sandbox does nothing.
```typescript
import { Daytona } from '@daytona/sdk'
const daytona = new Daytona()
const sandbox = await daytona.v2.get('{sandboxId}')
// Archive needs a stopped sandbox
await sandbox.stop()
await sandbox.wait({ until: 'stopped' })
// Move the disk to object storage now
await sandbox.archive()
// Archive a stopped sandbox by ID, without fetching it first
await daytona.v2.archive('{sandboxId}')
// Archive the sandbox 1 hour after it stops
await sandbox.updateLifecyclePolicy({ archiveIntervalSeconds: 3600 })
```
| **Parameter** | **Type** | **Description** |
| ---------------------------- | ------------ | ----------------------------------------------------------------------------------------------------------------------- |
| `archiveIntervalSeconds` | `number` | Sets how long a stopped sandbox waits before it is archived, from `60` to `2592000` (30 days). `0` sets the maximum. The default is `86400` (1 day). |
- `archive()` returns once the archive is accepted. `sandbox.archived` is `true` once the disk is in object storage.
- Archiving an archived sandbox does nothing.
```bash
# Move the disk of a stopped sandbox to object storage now
curl 'https://api.daytona.com/sandboxes/{sandboxId}/archive' \
--request POST \
--header 'Authorization: Bearer YOUR_API_KEY'
# Archive the sandbox 1 hour after it stops
curl 'https://api.daytona.com/sandboxes/{sandboxId}/lifecycle-policy' \
--request PATCH \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{ "archive_interval_seconds": 3600 }'
```
| **Field** | **Type** | **Description** |
| ------------------------------ | ------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `archive_interval_seconds` | `integer` | Sets how long a stopped sandbox waits before it is archived, from `60` to `2592000` (30 days). `0` sets the maximum. The default is `86400` (1 day). |
- An archive returns `202` once it is accepted, and `200` when the sandbox is already archived.
- An archive returns `409` when archiving is not available in the region, the sandbox is not a stopped persistent Linux sandbox without volumes, or it is already being archived.
### Delete
Delete a Linux sandbox to tear down its virtual machine. Deletion works in any state, and the call returns once teardown starts. The sandbox moves from deleting to deleted when the teardown finishes. Deleting a sandbox discards its filesystem and memory. Images and snapshots captured from the sandbox remain.
To keep files from a sandbox, take a [filesystem snapshot](#filesystem-snapshot) or write the files to a [volume](/docs/v2/volumes) or other storage outside the sandbox.
```python
from daytona import Daytona
daytona = Daytona()
sandbox = daytona.v2.create()
sandbox.delete()
# Delete by sandbox ID, without fetching the sandbox first
daytona.v2.delete("{sandboxId}")
```
```typescript
import { Daytona } from '@daytona/sdk'
const daytona = new Daytona()
const sandbox = await daytona.v2.create()
await sandbox.delete()
// Delete by sandbox ID, without fetching the sandbox first
await daytona.v2.delete('{sandboxId}')
```
```bash
daytona sandbox delete {sandboxId}
```
```bash
curl 'https://api.daytona.com/sandboxes/{sandboxId}' \
--request DELETE \
--header 'Authorization: Bearer YOUR_API_KEY'
```
- The request requires the `delete:sandboxes` permission.
### Timeouts
Daytona deletes a Linux sandbox automatically when one of its two timers elapses, or stops or pauses a [persistent](#persistent) one. Each timer pairs an interval in seconds with the action it fires. Set both timers at create in the lifecycle policy, and change them later through [update lifecycle policy](#update-lifecycle-policy).
| **Timer** | **Purpose** | **Fires after** | **Default** |
| --------------------------------- | --------------------------------------------------- | ------------------------------------------------------------ | --------------------------- |
| [**Timeout**](#timeout) | Cap how long a sandbox lives | The interval has passed since the sandbox was created, active or not | Project or platform default |
| [**Idle timeout**](#idle-timeout) | Delete a sandbox that is not in use | The sandbox has had no activity for the interval | Project default, or off |
The action for both timers is delete. A persistent sandbox can also stop or pause. Auto-delete is not a separate setting. It is the idle timeout with the delete action.
#### Timeout
The timeout is a wall-clock budget. It starts when the sandbox is created. Activity does not extend it. A delete timeout fires in any state. Once set, the timeout cannot be cleared.
When the timeout is omitted at create, Daytona applies the project's [lifecycle defaults](/docs/v2/projects#lifecycle-defaults). Without a project default, Daytona applies the platform default timeout of 300 seconds, if the platform default is enabled. An explicit timeout must not exceed the organization maximum, 86,400 seconds (24 hours) unless the organization sets a different maximum.
When the action is omitted, it defaults to delete, or to pause for a persistent sandbox.
```python
from daytona import Daytona
daytona = Daytona()
sandbox = daytona.v2.create(
# Delete the sandbox 2 hours after it is created
lifecycle_policy={"timeout_seconds": 7200, "on_timeout": "delete"},
)
```
```typescript
import { Daytona } from '@daytona/sdk'
const daytona = new Daytona()
const sandbox = await daytona.v2.create({
// Delete the sandbox 2 hours after it is created
lifecyclePolicy: { timeoutSeconds: 7200, onTimeout: 'delete' },
})
```
```bash
# Delete the sandbox 2 hours after it is created
daytona sandbox create --timeout 7200 --on-timeout delete
```
```bash
# Delete the sandbox 2 hours after it is created
curl 'https://api.daytona.com/sandboxes' \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{
"lifecycle_policy": { "timeout_seconds": 7200, "on_timeout": "delete" }
}'
```
#### Idle timeout
The idle timeout fires after the sandbox has had no activity for the interval. Activity is any request through the toolbox API, preview URLs, VNC, and SSH, a toolbox command that is still running, and any lifecycle operation on the sandbox. The idle timeout is off by default unless the project sets one, has a minimum of 60 seconds, and requires an action. The action fires within about 2 minutes after the interval elapses.
##### Auto-delete
Delete a Linux sandbox after a period of inactivity.
```python
from daytona import Daytona
daytona = Daytona()
sandbox = daytona.v2.create(
lifecycle_policy={"idle_expiry_seconds": 3600, "on_idle_timeout": "delete"},
)
```
```typescript
import { Daytona } from '@daytona/sdk'
const daytona = new Daytona()
const sandbox = await daytona.v2.create({
lifecyclePolicy: { idleExpirySeconds: 3600, onIdleTimeout: 'delete' },
})
```
```bash
daytona sandbox create --idle-timeout 3600 --on-idle-timeout delete
```
```bash
curl 'https://api.daytona.com/sandboxes' \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{
"lifecycle_policy": { "idle_expiry_seconds": 3600, "on_idle_timeout": "delete" }
}'
```
##### Reset the idle timer
Reset the idle timer of a Linux sandbox to keep it alive while it does work that Daytona does not count as activity. The reset counts as activity, so the idle countdown restarts from now. The timeout is not affected.
The reset succeeds in any state, whether or not an idle timeout is set. It never moves the timer backwards: when newer activity arrives at the same time, the newer activity wins.
```python
from daytona import Daytona
daytona = Daytona()
sandbox = daytona.v2.create(
lifecycle_policy={"idle_expiry_seconds": 3600, "on_idle_timeout": "delete"},
)
lifecycle = sandbox.reset_idle_timer()
print(lifecycle.idle_timeout_at)
```
- `reset_idle_timer()` updates `sandbox.lifecycle_policy`.
- `idle_timeout_at` is `None` when no idle timeout is set.
- When the idle timeout action is `delete`, the API key also needs the `delete:sandboxes` permission.
```typescript
import { Daytona } from '@daytona/sdk'
const daytona = new Daytona()
const sandbox = await daytona.v2.create({
lifecyclePolicy: { idleExpirySeconds: 3600, onIdleTimeout: 'delete' },
})
const lifecycle = await sandbox.resetIdleTimer()
console.log(lifecycle.idleTimeoutAt)
```
- `resetIdleTimer()` updates `sandbox.lifecyclePolicy`.
- `idleTimeoutAt` is `undefined` when no idle timeout is set.
- When the idle timeout action is `delete`, the API key also needs the `delete:sandboxes` permission.
```bash
curl 'https://api.daytona.com/sandboxes/{sandboxId}/reset-idle-timer' \
--request POST \
--header 'Authorization: Bearer YOUR_API_KEY'
```
The response has the sandbox `id` and its `lifecycle_policy` with the following fields:
| **Field** | **Description** |
| ----------------- | ---------------------------------------- |
| `idle_timeout_at` | The reset moves this value forward. |
| `timeout_at` | The reset leaves this value unchanged. |
- The request requires the `write:sandboxes` permission.
- When the idle timeout action is `delete`, the request also requires the `delete:sandboxes` permission.
### Update lifecycle policy
Update the timeouts of an existing Linux sandbox. Omitted fields keep their current values. The new actions must be valid for the sandbox, as listed in [timeouts](#timeouts).
```python
from daytona import Daytona
from daytona.v2 import DISABLED
daytona = Daytona()
sandbox = daytona.v2.create()
# Delete the sandbox after 30 minutes without activity; omitted fields keep their current value
lifecycle = sandbox.update_lifecycle_policy(idle_expiry_seconds=1800, on_idle_timeout="delete")
print(lifecycle.idle_expiry_seconds, lifecycle.on_idle_timeout)
# Re-anchor the timeout to 1 hour from now
lifecycle = sandbox.update_lifecycle_policy(timeout_seconds=3600)
print(lifecycle.timeout_at)
# Clear the idle timeout
lifecycle = sandbox.update_lifecycle_policy(idle_expiry_seconds=DISABLED)
```
```typescript
import { Daytona } from '@daytona/sdk'
import { DISABLED } from '@daytona/sdk/v2'
const daytona = new Daytona()
const sandbox = await daytona.v2.create()
// Delete the sandbox after 30 minutes without activity; omitted fields keep their current value
let lifecycle = await sandbox.updateLifecyclePolicy({ idleExpirySeconds: 1800, onIdleTimeout: 'delete' })
console.log(lifecycle.idleExpirySeconds, lifecycle.onIdleTimeout)
// Re-anchor the timeout to 1 hour from now
lifecycle = await sandbox.updateLifecyclePolicy({ timeoutSeconds: 3600 })
console.log(lifecycle.timeoutAt)
// Clear the idle timeout
lifecycle = await sandbox.updateLifecyclePolicy({ idleExpirySeconds: DISABLED })
```
```bash
# Delete the sandbox after 30 minutes without activity
daytona sandbox update {sandboxId} --idle-timeout 1800 --on-idle-timeout delete
# Re-anchor the timeout to 1 hour from now
daytona sandbox update {sandboxId} --timeout 3600
# Clear the idle timeout
daytona sandbox update {sandboxId} --idle-timeout=-1
```
```bash
# Delete the sandbox after 30 minutes without activity
curl 'https://api.daytona.com/sandboxes/{sandboxId}/lifecycle-policy' \
--request PATCH \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{ "idle_expiry_seconds": 1800, "on_idle_timeout": "delete" }'
# Re-anchor the timeout to 1 hour from now
curl 'https://api.daytona.com/sandboxes/{sandboxId}/lifecycle-policy' \
--request PATCH \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{ "timeout_seconds": 3600 }'
# Clear the idle timeout
curl 'https://api.daytona.com/sandboxes/{sandboxId}/lifecycle-policy' \
--request PATCH \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{ "idle_expiry_seconds": -1 }'
```
| **Field** | **Type** | **Description** |
| ------------------- | --------- | ----------------------------------------------------------------------------------------------------------------- |
| `timeout_seconds` | `integer` | Sets the seconds until the timeout, counted from now. If omitted, the value is unchanged. |
| `idle_expiry_seconds` | `integer` | Sets the seconds without activity before the idle action. `-1` clears the idle timeout and its action. If omitted, the value is unchanged. |
| `on_timeout` | `string` | Sets the timeout action, `delete`. If omitted, the value is unchanged. |
| `on_idle_timeout` | `string` | Sets the idle action, `delete`. It is required when you set an idle timeout on a sandbox that has none. If omitted, the value is unchanged. |
- Setting either action to `delete` requires the `delete:sandboxes` permission in addition to `write:sandboxes`.
- Changing a timer whose action is `delete` requires the `delete:sandboxes` permission in addition to `write:sandboxes`.