01Documentation
Template
A template is the reusable blueprint for a sandbox. It defines the image, default resources, environment, metadata, and default network policy. Every sandbox is claimed from a template.
Warm capacity is shared across templates. A template supplies a default memory size, with CPU derived by platform policy, but does not reserve a private idle pool. See Unified Warm Pool.
Creating, updating, and deleting team-owned templates requires team admin
permissions. developer and builder roles can read templates.
Template Types#
| Type | Description | Visibility |
|---|---|---|
| Builtin | Platform-provided templates | Public to all teams |
| Custom | Templates created and owned by a team | Private to that team |
A platform system identity manages builtin templates. Team identities cannot write public template state. When a team-owned template has the same ID as a builtin, get and claim prefer the team's template. Template IDs are scoped to the team or public namespace within a region.
Choose A Creation Method#
| Need | Prefer |
|---|---|
| Reproducible image build or a different base image | Create a template from an image |
| Reusable template ID from an initialized sandbox | Create a template from a sandbox |
| Reuse initialized RootFS state without a new template | Create a RootFS snapshot and claim with snapshot_id |
A template created from a sandbox retains an immutable regional block-COW RootFS generation. It does not republish the writable workspace as an OCI layer. The source template's digest-pinned base image and platform remain the runtime identity for the retained generation.
A RootFS snapshot is often better when the existing image, resource defaults, and network policy already fit. Snapshots do not appear in the template list; they can initialize new sandboxes claimed from a compatible template.
See Snapshot And Restore for snapshot, restore, fork, and rebase behavior.
Create From An Image#
/api/v1/templates
yaml# template.yaml spec: mainContainer: image: docker.io/library/python@sha256:<64-hex-digest> resources: memory: 4Gi ephemeralStorage: 8Gi envVars: PYTHONUNBUFFERED: "1" network: mode: block-all
bashs0 template create --id my-python-env --spec-file template.yaml
Replace <64-hex-digest> with the image's actual immutable digest before
submitting the file.
The request shape is:
json{ "template_id": "my-python-env", "spec": { "mainContainer": { "image": "docker.io/library/python@sha256:<64-hex-digest>", "resources": { "memory": "4Gi", "ephemeralStorage": "8Gi" } }, "envVars": {"PYTHONUNBUFFERED": "1"}, "network": {"mode": "block-all"} } }
Image-based template creation returns 201 Created after validating the
canonical digest-pinned source. Manager then idempotently discovers every
required runtime platform and imports the exact image, procd identity, and
initial RootFS capacity and immutable device geometry into the regional block store. A claim returns data-plane-not-ready
until that durable import reaches ready. Template IDs are canonical within
their scope and cannot be renamed.
The public template API accepts memory but not CPU. CPU is derived by platform
policy. Scheduling class and warm-capacity configuration are platform-level
inputs rather than template fields. Image tags are mutable and are rejected;
use a normalized OCI reference ending in @sha256: and 64 lowercase hex
characters.
Create From A Sandbox#
/api/v1/templates/from-sandbox
This operation accepts a running or paused source and returns 202 Accepted.
It is asynchronous because Sandbox0 must capture and retain an immutable RootFS
generation.
| Field | Required | Description |
|---|---|---|
template_id | Yes | New team-owned template ID. |
sandbox_id | Yes | Source sandbox owned by the same team. |
spec_overrides | No | Only description, displayName, and tags may be overridden. |
bashcurl -fsS -X POST "$SANDBOX0_API_URL/api/v1/templates/from-sandbox" \ -H "Authorization: Bearer $SANDBOX0_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: python-workspace-v1" \ -d '{ "template_id": "python-workspace", "sandbox_id": "SOURCE_SANDBOX_ID", "spec_overrides": { "displayName": "Python workspace", "tags": ["python", "initialized"] } }'
The new template inherits safe runtime inputs from the source template. It does not copy sandbox identity, processes, memory, sessions, claim-time environment or network overrides, or services. The retained RootFS still contains ordinary files written by the source, including any credentials or configuration saved there. The operation does not scrub those files.
For a running source, ctld briefly barriers the exact active writer and
publishes a committed RootFS checkpoint. Concurrent writes can continue after
the short barrier. Request acceptance is not the capture point:
status.creation.capturedAt records the committed capture time.
Keep the source available while the status stage is capturing. Poll the
returned Location until status.creation.state becomes ready or failed:
bashs0 template get python-workspace
Creation states are:
| State | Stage | Meaning |
|---|---|---|
creating | capturing | Exact source writer is being validated and captured. |
creating | publishing | The immutable block-COW generation is being bound to the template. |
ready | publishing | The regional template source is committed and claimable. |
failed | Current stage | Creation failed closed; inspect reason and message. |
ready does not mean the RootFS is already attached on every node. A claim
still needs a compatible carrier, node capacity, and RootFS attachment.
Use the same Idempotency-Key and body to retry after an uncertain client
response. Reusing a key with a different body returns a conflict.
Get And List#
/api/v1/templates/{id}
/api/v1/templates
bashs0 template get my-python-env s0 template list
Lists include builtin templates and team-owned templates visible to the current identity. Internal RootFS attestation, build lease, and idempotency state are not exposed in the public representation.
Update#
/api/v1/templates/{id}
Updates replace the template spec. They affect future claims and do not rewrite already-running sandbox generations.
bashs0 template update my-python-env --spec-file template.yaml
A template still being created, or one whose asynchronous creation failed,
cannot be updated and returns 409 Conflict. CPU and scheduling fields remain
platform-controlled on update.
For a template created from a sandbox, keeping the same image retains its
captured RootFS source. Changing mainContainer.image clears that source and
queues its cleanup; future claims initialize from the new image import rather
than the captured workspace. A resource change alone does not resize an
already captured RootFS generation.
Delete#
/api/v1/templates/{id}
bashs0 template delete my-python-env
Deletion removes the logical template and durably queues cleanup of an internal RootFS generation, when present. Existing sandboxes keep their own lifecycle and RootFS state. New claims fail when no template with that ID is visible. Deleting a private template that shadows a builtin exposes the builtin again, so subsequent claims with that ID use the builtin.