sandboxTemplates
A sandbox template belongs to one tenant and fixes what its sandboxes run: a hosted pool, a flavor, an image, the pool's runtime, optional user data, TTL bounds and a warm pool. For each live template the `vps.sandboxes` reconciler keeps `warm.min` instances with `desiredState` `paused`, or `stopped` when the runtime cannot pause, creating at most 4 per template in one pass and deleting those beyond `warm.max`, newest first. Warm instances are owned by the template's author, placed and charged to quota when they are created, and a refill that fails is logged and tried again on a later pass. See [Sandboxes](/docs/guides/vps/sandboxes).
A sandbox template belongs to one tenant and fixes what its sandboxes run: a hosted pool, a flavor, an image, the pool's runtime, optional user data, TTL bounds and a warm pool. For each live template the vps.sandboxes reconciler keeps warm.min instances with desiredState paused, or stopped when the runtime cannot pause, creating at most 4 per template in one pass and deleting those beyond warm.max, newest first. Warm instances are owned by the template's author, placed and charged to quota when they are created, and a refill that fails is logged and tried again on a later pass. See Sandboxes.
All 5 methods are served by this release.
| Method | Kind | Authorization | Phase | Status |
|---|---|---|---|---|
create | mutation | compute:sandboxes:manage @ compute-tenant | v0.5 | registered |
list | read | compute:sandboxes:read @ compute-tenant + items | v0.5 | registered |
get | read | compute:sandboxes:read @ compute-sandbox-template | v0.5 | registered |
update | mutation | compute:sandboxes:manage @ compute-sandbox-template | v0.5 | registered |
delete | mutation | compute:sandboxes:manage @ compute-sandbox-template | v0.5 | registered |
create
POST /api/compute/sandboxTemplates/create
Checks the pool, flavor, image and runtime once and stores a template under a name unique in the tenant; returns the template.
-
Checks. The pool must be owned by or offered to the tenant and not archived (
NOT_FOUND), and be a hostedvps-hostpool: a provider pool isINVALID_INPUT. A missing or archived flavor and an image that does not resolve areNOT_FOUND;INVALID_CONFIGwhenvps()has noimages. The pool's runtime must boot the image's format and pass through the flavor's GPUs (INVALID_INPUT), andruntime, when given, must equal the pool's runtime (INVALID_INPUT). The template stores the pool's runtime. -
Lifetime.
defaultTtlSecondsdefaults to 3,600 andmaxTtlSecondsto 86,400 or the default TTL, whichever is larger; both lie between 60 seconds and 30 days, and a default above the maximum isINVALID_INPUT. -
Warm pool.
warm.minandwarm.maxare 0 to 64;maxdefaults tomin, and amaxbelowminisINVALID_INPUT. -
User data. At most 32 KiB. A URI must be a
secret://reference to a secret of the same tenant, otherwiseINVALID_INPUT. -
Volumes.
volumeslists up to 8 sandbox volumes (sandboxVolumes) that each sandbox of the template attaches:- each entry names a volume by
volumeIdor byname(one of them), with amountPathand an optionalreadOnly; - each volume must be the tenant's,
readyand in the template's pool (NOT_FOUND,INVALID_STATE,INVALID_INPUT), and named once; - a mount path is absolute, without
.or.., never over a system directory (/,/etc,/usr,/proc, …), and never inside another entry's (INVALID_INPUT); - a template with volumes keeps no warm pool (
warm.maxmust be 0), since a warm instance would hold the volumes; - every sandbox of the template reads the volume, and unless it is
readOnlywrites it, so each volume is also decided on the caller's own credential:compute:sandboxes:manageoncompute-sandbox-volumefor a read-write mount,compute:sandboxes:readfor a read-only one (ACCESS_DENIEDotherwise).
Its sandboxes run on the volumes' host only. A read-write attachment needs the volume to itself, so a second sandbox of a template that attaches a volume read-write is
CONFLICT(details.reason: 'volume-in-use') while the first lives. - each entry names a volume by
A live template with the same name is CONFLICT. The caller becomes the template's owner in the authorization projection. Publishes no event.
- Kind: mutation
- Authorization:
compute:sandboxes:manage@compute-tenant - Module:
vps - Phase: v0.5 (registered)
Input
| Field | Type | Required | Constraints |
|---|---|---|---|
tenantId | string | yes | at most 128 characters; matches ^[A-Za-z0-9._:-]{1,128}$ |
name | string | yes | at most 63 characters; matches ^[a-z0-9][a-z0-9._-]{0,62}$ |
poolId | string | yes | at most 57 characters; matches ^pool_[0-9a-hjkmnp-tv-z]{26,52}$ |
flavor | string | yes | at most 63 characters; matches ^[a-z0-9][a-z0-9._-]{0,62}$ |
imageId | string | yes | at most 200 characters; matches ^[A-Za-z0-9][A-Za-z0-9._@:/-]{0,199}$ |
runtime | string | at most 64 characters; matches ^[a-z][a-z0-9-]{0,63}$ | |
userData | string | at most 32768 characters | |
defaultTtlSeconds | integer | 60-2592000; default 3600 | |
maxTtlSeconds | integer | 60-2592000; default 86400 | |
warm | object | ||
warm.min | integer | yes | 0-64 |
warm.max | integer | 0-64 | |
env | map of string | at most 64 entries; keys match ^[A-Z_][A-Z0-9_]{0,63}$ | |
network | one of egress, private, none | ||
volumes | list of object | 0-8 items | |
volumes[].volumeId | string | at most 56 characters; matches ^vol_[0-9a-hjkmnp-tv-z]{26,52}$ | |
volumes[].name | string | at most 63 characters; matches ^[a-z0-9][a-z0-9._-]{0,62}$ | |
volumes[].mountPath | string | yes | at most 255 characters; matches ^/[A-Za-z0-9._\-/]{1,254}$ |
volumes[].readOnly | boolean | default false |
list
POST /api/compute/sandboxTemplates/list
Returns every live template of the tenant, ordered by name, in one answer.
Each template is checked for compute:sandboxes:read on compute-sandbox-template; those the caller may not read are left out. Deleted templates are never listed.
- Kind: read
- Authorization:
compute:sandboxes:read@compute-tenant+ items - Module:
vps - Phase: v0.5 (registered)
Input
| Field | Type | Required | Constraints |
|---|---|---|---|
tenantId | string | yes | at most 128 characters; matches ^[A-Za-z0-9._:-]{1,128}$ |
get
POST /api/compute/sandboxTemplates/get
Returns one live template of the tenant.
A deleted template, or one of another tenant, is NOT_FOUND.
- Kind: read
- Authorization:
compute:sandboxes:read@compute-sandbox-template - Module:
vps - Phase: v0.5 (registered)
Input
| Field | Type | Required | Constraints |
|---|---|---|---|
tenantId | string | yes | at most 128 characters; matches ^[A-Za-z0-9._:-]{1,128}$ |
templateId | string | yes | at most 57 characters; matches ^sbxt_[0-9a-hjkmnp-tv-z]{26,52}$ |
update
POST /api/compute/sandboxTemplates/update
Changes a template's flavor, image, user data, TTL bounds, warm pool or volumes; returns the template with its version raised.
The pool, name and runtime stay. A new flavor or imageId is checked against the pool as on create, and the pool must still run the template's runtime (INVALID_INPUT). Omitted fields keep their values, userData: null removes the user data, and warm replaces the warm pool, max again defaulting to min. A defaultTtlSeconds above maxTtlSeconds after the change is INVALID_INPUT. A deleted or missing template is NOT_FOUND. The secrets the template references are decided with the update; if another change added secret references while this one was decided, it is CONFLICT with details.reason: 'secrets-changed': retry, and the new references are decided too. The volumes are decided the same way, each on its own resource as on create: a new volumes list, and the current one when the update changes what the guest runs (flavor, image, user data, env or network). If a volume name now points at another volume, or a mount became writable, since the decision, it is CONFLICT with details.reason: 'volumes-changed': retry.
Sandboxes that exist keep their instances, and warm instances already created stay claimable with the shape they were created with; new sandboxes and warm refills use the new values. A lower warm.max makes the reconciler delete the excess. Publishes no event.
- Kind: mutation
- Authorization:
compute:sandboxes:manage@compute-sandbox-template - Module:
vps - Phase: v0.5 (registered)
Input
| Field | Type | Required | Constraints |
|---|---|---|---|
tenantId | string | yes | at most 128 characters; matches ^[A-Za-z0-9._:-]{1,128}$ |
templateId | string | yes | at most 57 characters; matches ^sbxt_[0-9a-hjkmnp-tv-z]{26,52}$ |
flavor | string | at most 63 characters; matches ^[a-z0-9][a-z0-9._-]{0,62}$ | |
imageId | string | at most 200 characters; matches ^[A-Za-z0-9][A-Za-z0-9._@:/-]{0,199}$ | |
userData | string,null | at most 32768 characters | |
defaultTtlSeconds | integer | 60-2592000 | |
maxTtlSeconds | integer | 60-2592000 | |
warm | object | ||
warm.min | integer | yes | 0-64 |
warm.max | integer | 0-64 | |
env | map of string | at most 64 entries; keys match ^[A-Z_][A-Z0-9_]{0,63}$ | |
network | one of egress, private, none | ||
volumes | list of object | 0-8 items | |
volumes[].volumeId | string | at most 56 characters; matches ^vol_[0-9a-hjkmnp-tv-z]{26,52}$ | |
volumes[].name | string | at most 63 characters; matches ^[a-z0-9][a-z0-9._-]{0,62}$ | |
volumes[].mountPath | string | yes | at most 255 characters; matches ^/[A-Za-z0-9._\-/]{1,254}$ |
volumes[].readOnly | boolean | default false |
delete
POST /api/compute/sandboxTemplates/delete
Deletes a template so that get, list, update and sandboxes.create no longer find it; returns deleted: true.
The template leaves the authorization projection and its name is free for a new template. Its sandboxes live on until they are deleted or expire, and the vps.sandboxes reconciler deletes all of its warm instances. A template already deleted is NOT_FOUND. Publishes no event.
- Kind: mutation
- Authorization:
compute:sandboxes:manage@compute-sandbox-template - Module:
vps - Phase: v0.5 (registered)
Input
| Field | Type | Required | Constraints |
|---|---|---|---|
tenantId | string | yes | at most 128 characters; matches ^[A-Za-z0-9._:-]{1,128}$ |
templateId | string | yes | at most 57 characters; matches ^sbxt_[0-9a-hjkmnp-tv-z]{26,52}$ |
Better Compute is created by Sean Filimon
Last updated
sandboxSnapshots
Sandbox snapshots are their own resource, so a snapshot kept with `keep: true` outlives the sandbox it came from. `sandboxes.snapshot` takes them and `sandboxes.create` restores from them with `fromSnapshot`. These methods list, read and delete them. Snapshots stay private to their tenant and are never promoted to shared images. See [Sandboxes](/docs/guides/vps/sandboxes).
sandboxVolumes
Sandbox volumes are persistent disks on one host that a tenant's sandboxes attach across runs, so an agent keeps its memory, caches and checkouts. A volume is placed when it is created: its size is booked as `diskGiB` on one host of the pool, charged to the tenant's quota, and the host keeps it as a sparse raw file. A sandbox template names volumes with a mount path. Sandboxes of that template then run on the volume's host only, attach it as an extra virtio disk, and mount it by serial (`/dev/disk/by-id/virtio-<serial>`) from their user data. The first mount formats it as ext4, and no later one ever does. A volume takes any number of read-only attachments or one read-write attachment, never both. Volumes are metered as `vps.volume.gib.hours` from creation until the disk is released. See [Sandboxes](/docs/guides/vps/sandboxes).