Cloud Lifecycle, Storage, and Networking

Cloud machines keep their filesystem across commands and stop/start cycles. Network access, published ports, and additional volumes are explicit parts of the machine configuration.

The command examples assume SMOL_CLOUD_TOKEN and SMOL_CLOUD_URL are set as shown in Cloud Quick Start.

Lifecycle

Create

POST /v1/machines creates a machine record. New machines begin stopped.

Start

POST /v1/machines/{id}/start starts a stopped machine. An exec request also starts a stopped machine automatically.

Starting and ready are separate conditions:

  • state: "started" means the VM process launched
  • ready: true means the guest agent is reachable and every published port is accepting connections

Poll the machine until ready is true before sending dependent work. Probe the application’s own health endpoint separately when accepting a connection is not enough to establish application health.

Stop

POST /v1/machines/{id}/stop stops compute while preserving the machine filesystem. Installed packages and files remain available after the next start.

Current public pricing states that stopped machines have no base, CPU, or memory charge. Stored disk continues to bill. Check the pricing page for current rates.

Delete

DELETE /v1/machines/{id} removes the machine. Export any required data first. Deleting the machine ends billing for its machine storage; separately managed volumes must be deleted separately.

Automatic cleanup

The create request can include:

  • autoStopSeconds: stop an idle machine after a period
  • ttlSeconds: limit the machine lifetime
  • ephemeral: request ephemeral lifecycle behavior

Confirm exact semantics in the generated OpenAPI and test cleanup behavior before relying on these fields for data retention.

Machine storage

The machine filesystem persists across exec and stop/start. It is appropriate for packages, caches, checked-out repositories, and other state tied to one machine.

Stopping is not a backup. Delete removes the machine, and infrastructure failures can still affect machine-local state. Keep important source data and outputs in an external system or a supported volume workflow.

Cloud volumes

Cloud volumes are managed by the Cloud API:

curl --fail-with-body -X POST "$SMOL_CLOUD_URL/v1/volumes" \
  -H "Authorization: Bearer $SMOL_CLOUD_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"project-data","sizeGb":10}'

Attach a volume when creating a machine:

{
  "source": {"type": "image", "reference": "alpine"},
  "mounts": [
    {
      "volume": "project-data",
      "mountPath": "/data",
      "readonly": false
    }
  ]
}

Cloud volumes are different from local bind mounts:

  • A local bind mount maps a host path into a local smolvm
  • A cloud volume is a cloud-managed resource attached by name
  • A cloud machine cannot mount an arbitrary path from your laptop

Current attachment constraints:

  • A volume is placed on one node. A machine with attached volumes is placed on that node.
  • All volumes attached to one machine must be on the same node; otherwise start fails with 422.
  • A volume can be attached to only one machine at a time; an attachment conflict returns 409.
  • Referencing a missing volume returns 400.
  • Deleting a machine detaches its volumes but does not delete them. Delete each volume separately when its data is no longer needed.

Cloud volumes are persistent storage attachments, not backups. Keep critical source data and outputs in an external backup or system of record.

Outbound networking

Set network.mode explicitly so behavior does not depend on a changing default.

Block all outbound traffic:

{"network": {"mode": "blocked"}}

Allow unrestricted outbound traffic:

{"network": {"mode": "open"}}

Allow only selected hosts and CIDR ranges:

{
  "network": {
    "mode": "allowCidrs",
    "hosts": ["api.example.com", "github.com"],
    "cidrs": ["203.0.113.0/24"]
  }
}

An allow list must include every registry, package host, API, and redirect target the workload needs. Prefer blocked or allowCidrs for untrusted workloads.

Ingress and published ports

Publish a guest port in the create request:

{
  "source": {"type": "image", "reference": "nginx"},
  "ports": [{"port": 80}],
  "public": false
}

Each cloud machine can publish up to four guest ports. A published port is a guest port declaration; use the returned URL or authenticated connect route to reach it.

With public: false, use the authenticated connect route where it is enabled:

curl --fail \
  "$SMOL_CLOUD_URL/v1/machines/$MACHINE_ID/connect/80/" \
  -H "Authorization: Bearer $SMOL_CLOUD_TOKEN"

The connect route also accepts WebSocket upgrades for clients that need a bidirectional connection.

Set public: true only when the service should be reachable without the caller’s API authorization. Public ingress exposes application traffic, so the application must provide any authentication and authorization it needs.

Verify port and ingress fields in the API Explorer for the deployment you use.

Forks and snapshots

Fork creates a copy-on-write child from a running forkable cloud machine. Snapshot operations may be unavailable in some environments. Neither feature provides general local-to-cloud live migration or a portable, cross-architecture restore format.

GPU

Hosted cloud machine resource requests currently expose CPU, memory, and disk fields. They do not expose GPU fields. Local smolvm GPU support does not imply hosted cloud GPU availability.