Skip to content
Fuse
Esc
navigateopen⌘Jpreview

Snapshot a running VM

Checkpoints a running VM into a new snapshot. Creation is synchronous; the 201 body is the persisted record, already in state ready, with parent_snapshot_id pointing at the VM’s previous ready snapshot. mode defaults to manual.

live: false (the default, and the value of an omitted body) copies the rootfs and nothing else, so restoring cold-boots the guest. live: true additionally captures the guest’s memory and vCPU state inside a single pause window, so restoring resumes the guest where it stopped. It costs the environment’s full configured memory in bytes on every create, pauses the guest for the length of the capture, and produces an artifact pinned to the host that took it.

The response’s kind is what was actually written, not what was requested. A host running an agent too old to know about live snapshots answers live: true with a disk snapshot and the record says disk, so a caller that depends on the memory being present must read kind rather than assume the request was honoured.

Preconditions are reported as 4xx, not 5xx:

  • 404 not_found — unknown VM.
  • 409 conflict — the VM is not running (e.g. draining), the per-tenant snapshot quota (count or bytes) is exhausted, or the VM holds a GPU passthrough device. A vfio device cannot be checkpointed, so GPU environments can never be snapshotted; this is permanent and must not be retried. A GPU VM asking for live: true gets this same 409 and the same GPU-specific message, not the 501 below: the device is what cannot be checkpointed, so dropping live will not help.
  • 501 unimplemented — the provider has no snapshot support (e.g. the in-memory stub), or live: true was requested against a provider that supports disk snapshots but not live ones. The latter is not a conflict: nothing about the VM’s state is wrong and retrying it unchanged can never succeed, but the same call without live will, and the message says so. Only Firecracker hosts running an agent new enough to capture memory implement it.

Byte quotas were calibrated against rootfs-only snapshots, so a workload that switches to live: true reaches the 409 quota case far sooner than its snapshot count suggests.

POST/v1/environments/{vmId}/snapshots
Authorization
AuthorizationBearer token · headerrequired
`Authorization: Bearer <token>` — either the static master token (`ORCH_AUTH_TOKEN`) or a revocable API key issued via /v1/api-keys (API keys require Postgres; without a database only the master token is accepted). Master-only surfaces (exec, attach, API key management) refuse API keys with 403. **Authentication can be disabled entirely.** When neither `ORCH_AUTH_TOKEN` nor an API key store (`DATABASE_URL`) is configured — the default local-development posture — the bearer middleware becomes a pass-through: every operation this document marks as secured is reachable with no credentials, requests carry no principal, and master-only surfaces therefore admit everyone. Never run that configuration on a reachable network; set `ORCH_REQUIRE_AUTH=true` to make the orchestrator refuse to start without a master token.
or
fuse_sessionAPI key · cookierequired
HttpOnly session cookie set by POST /login for browser callers. Consulted only when no Authorization header is present.
Path parameters
vmIdstringrequired
VM identifier assigned by the orchestrator.
Request body
application/json
commentstring
Free-form note attached to the snapshot.
modestring
Defaults to "manual" when omitted. Values outside this set are not rejected by the server.
Allowed:manualauto
retention_secondsinteger<int64>
Seconds from now until the snapshot is eligible for garbage collection. Omitted or 0 falls back to the server's default retention if configured; otherwise the snapshot is kept until deleted.
metadataobject
layer_keystring
Labels this snapshot as the artifact of one cacheable setup step, so a later build can find it by recipe instead of by id. Set by `fuse build`; every other caller omits it. A layer is still an ordinary build-mode snapshot; the key is the only thing that distinguishes it.
liveboolean
Capture the guest's memory and vCPU state alongside the rootfs, so restoring resumes the guest instead of cold-booting it. Omitted or false takes a disk-only snapshot, which is the default everywhere. A live snapshot costs the environment's full configured memory in bytes on top of the rootfs, on every create, and pauses the guest for the length of the capture. The resulting artifact is pinned to the host that took it: a memory image depends on that host's CPU model and Firecracker version. Fork reads only a snapshot's rootfs, so forking a live snapshot silently yields a cold-booting environment. Asking for it on a provider without live-snapshot support is a 501, not a 409. Check the response's `kind` rather than assuming this flag was honoured.
default: false
export_refstring
export_statusstring
Defaults to "pending" when omitted. Values outside this set are not rejected by the server.
Allowed:pendingreadyerror
Responses
201Snapshot created (already in state `ready`).
idstringrequired
vm_idstringrequired
task_idstring
tenant_idstring
parent_snapshot_idstring
modestring
Normally "manual" or "auto". Not an enum: the server stores the caller-supplied `mode` verbatim (only an empty value is defaulted to "manual"), so an arbitrary string can appear here. Treat unknown values as opaque rather than rejecting the response.
statestring
Allowed:creatingreadyrestoringdeletingerror
commentstring
layer_keystring
Derived cache key of the setup step this artifact materializes. Absent on any snapshot that is not a build layer.
archstring
Architecture of the host that built the artifact, not of whoever asked for it. An ext4 rootfs does not travel across architectures, so this is what says whether these bytes are bootable for you.
Allowed:amd64arm64
digeststring
Hex sha256 of the artifact rootfs, for verifying a transfer of these exact bytes. It is not an identity two artifacts can share: rebuilding the same recipe produces different bytes, so nothing is looked up by digest. Absent when the host agent does not hash.
kindstring
What this artifact actually contains. "disk" is the rootfs and nothing else, so restoring it cold-boots the guest; "live" additionally carries the vCPU state and the whole guest memory, so restoring it resumes the guest where it stopped. This is what the host agent reports it wrote, never what the caller requested: a `live: true` create served by an agent that could only take a disk snapshot reads back as "disk". Branch on this rather than on your own request. Always present, on every read path. Records written before live snapshots existed read back as "disk".
default: "disk"
Allowed:disklive
size_bytesinteger<int64>
created_atstring<date-time>required
updated_atstring<date-time>
retention_untilstring<date-time> | null
When the snapshot becomes eligible for garbage collection; null/absent when it is kept until deleted.
last_errorstring
export_refstring
exportsSnapshotExport[]
Show properties
Array of SnapshotExport
destinationstringrequired
statusstring
Normally "pending", "ready", or "error". Not an enum: the create handler stores the caller-supplied `export_status` verbatim (only an empty value is defaulted to "pending"), so an arbitrary string can appear here. Treat unknown values as opaque rather than rejecting the response.
requested_atstring<date-time>
updated_atstring<date-time>
last_errorstring
400Malformed request.
errorobjectrequired
Show properties
codestringrequired
Stable machine-readable code. `route_not_found` (404) means the URL matches no route this server exposes — usually a wrong host, port, or path prefix — as opposed to `not_found`, where the route exists but the resource does not. `forbidden` is emitted only by CIDR-allowlist rejections; master-only refusals (exec, attach, API key management) return 403 with code `unauthorized`.
Allowed:not_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplemented
messagestringrequired
Human-readable description.
detailsobject
Optional stable, non-sensitive metadata (e.g. ids, counts). Omitted when empty.
404Resource does not exist. Note the distinct code `route_not_found`, returned when the URL matches no registered route at all (wrong host, port, or path prefix) rather than a known route with a missing resource.
errorobjectrequired
Show properties
codestringrequired
Stable machine-readable code. `route_not_found` (404) means the URL matches no route this server exposes — usually a wrong host, port, or path prefix — as opposed to `not_found`, where the route exists but the resource does not. `forbidden` is emitted only by CIDR-allowlist rejections; master-only refusals (exec, attach, API key management) return 403 with code `unauthorized`.
Allowed:not_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplemented
messagestringrequired
Human-readable description.
detailsobject
Optional stable, non-sensitive metadata (e.g. ids, counts). Omitted when empty.
409The VM is not running, the per-tenant snapshot quota (count or bytes) is exhausted, or the VM holds a GPU passthrough device. The GPU case is reported here for `live: true` as well as for a plain disk snapshot.
errorobjectrequired
Show properties
codestringrequired
Stable machine-readable code. `route_not_found` (404) means the URL matches no route this server exposes — usually a wrong host, port, or path prefix — as opposed to `not_found`, where the route exists but the resource does not. `forbidden` is emitted only by CIDR-allowlist rejections; master-only refusals (exec, attach, API key management) return 403 with code `unauthorized`.
Allowed:not_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplemented
messagestringrequired
Human-readable description.
detailsobject
Optional stable, non-sensitive metadata (e.g. ids, counts). Omitted when empty.
500Unexpected server error.
errorobjectrequired
Show properties
codestringrequired
Stable machine-readable code. `route_not_found` (404) means the URL matches no route this server exposes — usually a wrong host, port, or path prefix — as opposed to `not_found`, where the route exists but the resource does not. `forbidden` is emitted only by CIDR-allowlist rejections; master-only refusals (exec, attach, API key management) return 403 with code `unauthorized`.
Allowed:not_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplemented
messagestringrequired
Human-readable description.
detailsobject
Optional stable, non-sensitive metadata (e.g. ids, counts). Omitted when empty.
501The provider has no snapshot support at all, or `live: true` was asked of a provider that can take disk snapshots but not live ones. In the second case the message says to retry without `live` for a disk snapshot.
errorobjectrequired
Show properties
codestringrequired
Stable machine-readable code. `route_not_found` (404) means the URL matches no route this server exposes — usually a wrong host, port, or path prefix — as opposed to `not_found`, where the route exists but the resource does not. `forbidden` is emitted only by CIDR-allowlist rejections; master-only refusals (exec, attach, API key management) return 403 with code `unauthorized`.
Allowed:not_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplemented
messagestringrequired
Human-readable description.
detailsobject
Optional stable, non-sensitive metadata (e.g. ids, counts). Omitted when empty.
Request
curl -X POST "http://localhost:8080/v1/environments/string/snapshots" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "comment": "string",
  "mode": "manual",
  "retention_seconds": 0,
  "metadata": {},
  "layer_key": "string",
  "live": false,
  "export_ref": "string",
  "export_status": "pending"
}'
Response
{
  "id": "string",
  "vm_id": "string",
  "task_id": "string",
  "tenant_id": "string",
  "parent_snapshot_id": "string",
  "mode": "manual",
  "state": "creating",
  "comment": "string",
  "layer_key": "string",
  "arch": "amd64",
  "digest": "string",
  "kind": "disk",
  "size_bytes": 0,
  "created_at": "2024-01-01T00:00:00Z",
  "updated_at": "2024-01-01T00:00:00Z",
  "retention_until": "2024-01-01T00:00:00Z",
  "last_error": "string",
  "export_ref": "string",
  "exports": [
    {
      "destination": "string",
      "status": "pending",
      "requested_at": "2024-01-01T00:00:00Z",
      "updated_at": "2024-01-01T00:00:00Z",
      "last_error": "string"
    }
  ]
}