Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions docs/migrating-from-v1.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ Seven questions. If every answer is "no", your migration is a configuration chan
None of these exist in v2.
</Step>
<Step title="Do you build images or fork from checkpoints?">
Image builds are unavailable. Fork is unavailable today and being worked on.
Image builds work, but only ahead of time — see [Templates](/sandboxes/templates).
Passing `image:` directly to a create is refused. Fork is unavailable today and being
worked on.
</Step>
</Steps>

Expand Down Expand Up @@ -86,7 +88,8 @@ A v1 template captures the whole disk. v2 can only replay the workspace half, an
silently would hand you your files while dropping every system change the template existed for.
So it refuses, loudly, at create.

Rebuild affected templates as workspace templates or checkpoints on v2.
Rebuild them on v2 — usually by re-running the same `Image` definition under the same name.
See [Templates](/sandboxes/templates).

### Sizes are fixed steps, and 16 GB is gone

Expand Down Expand Up @@ -134,7 +137,7 @@ that sandbox. See [Secrets](/sandboxes/secrets).
|---|---|
| `scale()`, `setAutoscale()` | memory is fixed at launch |
| Mounts (FUSE, NFS, overlay) | the guest cannot perform `mount` |
| Image builds (`image:`) | no build pipeline in v2 |
| Inline `image:` on create | build ahead of time instead — see [Templates](/sandboxes/templates) |
| Fork from a checkpoint | in progress |
| Checkpoint patches | not wired up |
| Live migration | not applicable |
Expand Down
17 changes: 15 additions & 2 deletions docs/reference/typescript-sdk/image.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@ Fluent, immutable builder for declarative sandbox images. Each method returns a

## `Image.base()`

Start from the default OpenSandbox environment (Ubuntu 22.04, Python, Node.js, build tools).
Start from the default OpenSandbox environment (Amazon Linux 2023, Python, Node.js, build
tools) on ARM64.

<Note>
Images are built ahead of time and started by name — see
[Templates](/sandboxes/templates). Passing an `Image` directly to `Sandbox.create()` is
refused, because a build takes minutes.
</Note>

```typescript
import { Image } from "@opencomputer/sdk";
Expand All @@ -28,9 +35,15 @@ const image = Image.base()
### `image.aptInstall(packages)`

<ParamField body="packages" type="string[]" required>
System packages to install via apt-get
System packages to install
</ParamField>

<Note>
The base is Amazon Linux 2023, so these are installed with `dnf`. Common Debian names are
translated (`build-essential` becomes `gcc gcc-c++ make`); a package that exists only on
Debian fails the build and the error names it.
</Note>

**Returns:** `Image`

---
Expand Down
124 changes: 79 additions & 45 deletions docs/sandboxes/templates.mdx
Original file line number Diff line number Diff line change
@@ -1,72 +1,106 @@
---
title: "Templates"
description: "Which templates carry over, and which do not"
description: "Same API as v1, with two differences worth knowing"
---

Templates work on v2, but **the templates you have today probably do not.** This is
the migration issue most likely to affect you, and it is worth checking before anything moves.
Templates work on v2, and **the contract is unchanged**. You define an environment once,
give it a name, and start sandboxes from that name:

## How a template is applied here
```typescript
import { Image, Snapshots, Sandbox } from "@opencomputer/sdk";

A template create claims a standard pooled sandbox and unpacks the template's **workspace
archive** on top of it. That keeps the fast pooled create and makes a template cost a tarball
rather than a separately published machine image.
const snapshots = new Snapshots();

```typescript
const sandbox = await Sandbox.create({ templateID: "my-template" });
await snapshots.create({
name: "video-tools",
image: Image.base()
.aptInstall(["ffmpeg"])
.pipInstall(["numpy"]),
});

await snapshots.waitUntilReady("video-tools");

const sandbox = await Sandbox.create({ template: "video-tools" });
```

## The catch: rootfs templates are refused
Same `Image` builder, same names, same `list` / `get` / `delete`. Your existing definitions
carry over as written — what changes is how they are built underneath, and two consequences of
that are visible to you.

## 1. Build ahead of time

A template is built into a machine image before any sandbox uses it, which takes minutes rather
than seconds. So the build is a separate step from the create, and you wait for it once:

```typescript
await snapshots.create({ name: "tools", image });
await snapshots.waitUntilReady("tools"); // minutes, once
await Sandbox.create({ template: "tools" }); // fast, every time after
```

<Warning>
A template that carries a **rootfs image** cannot be used on v2. The create fails with
*"template … carries a rootfs image, which v2 cannot restore."*
Passing `image:` directly to `Sandbox.create()` is refused on v2. A create that waited for a
build would time out, so the error names the two-step path instead of returning a sandbox
without your packages.
</Warning>

Templates built on v1 capture the **whole disk** — every system-level change,
not just your workspace. This runtime can only replay the workspace half, and doing that
silently would hand you your files while dropping every system change the template existed for:
a template that looks like it worked and hasn't.
## 2. Sandboxes from a template cold-start

So it refuses instead. That is the right failure, but it means:
Standard sandboxes come from a warm pool. A sandbox built on your template does not, because the
pool holds standard sandboxes — so expect a few seconds rather than milliseconds on create.

**Any template that installed system packages, changed system configuration, or was built
before your org moved will need rebuilding on the new runtime.**
Everything the template installed is already baked in, so this is paid at create, not on your
first command.

## What to do
## What your definitions run on

<Steps>
<Step title="List your templates and try each one">
A refused template fails loudly at create with the message above. That is the fastest audit
— you do not need to inspect anything.
</Step>
<Step title="Rebuild the ones that fail">
Start a sandbox on the new runtime, install what the template provided, and capture it as a
[checkpoint](/sandboxes/checkpoints) or a new template. What can be captured is the
filesystem, so anything you can install with files and packages carries over.
</Step>
<Step title="Move system-level setup into the image, or into your startup">
If the template depended on changes outside the workspace, they need to live somewhere else
— either in a published image (talk to us) or as a step your sandbox runs on boot.
</Step>
</Steps>
The environment underneath is Amazon Linux 2023 on ARM64, so two things in an existing
definition can need attention:

<CardGroup cols={2}>
<Card title="Package names" icon="box">
`aptInstall` works and common Debian names are translated — `build-essential` becomes
`gcc gcc-c++ make`. A package that exists only on Debian fails the build, and the error
names it.
</Card>
<Card title="Architecture" icon="microchip">
A step that downloads an x86-64 binary fails. Use your package manager, or fetch the
`aarch64` build.
</Card>
</CardGroup>

## Image builds are not available
Each org holds up to **10** templates at a time; delete one to make room. Two identical
definitions share one build, so rebuilding an unchanged template returns immediately.

## Templates built on v1

<Warning>
Declarative image manifests (`image:` on create) and the image build pipeline are **not
supported** on v2. They depend on a build fleet it does not have.
A template that carries a **rootfs image** cannot be used on v2. The create fails with
*"template … carries a rootfs image, which v2 cannot restore."*
</Warning>

If you build images today, that workflow needs an alternative before you migrate:
v1 templates capture the whole disk. Replaying only part of that would hand you your files while
dropping every system change the template existed for — a template that looks like it worked and
hasn't — so it refuses instead.

Rebuilding is the fix, and usually means re-running the `Image` definition you already have.

<Steps>
<Step title="Try each template">
One that cannot be used fails loudly at create with the message above. That is the fastest
audit — nothing to inspect.
</Step>
<Step title="Rebuild it">
Create it again by name with the same definition, wait for the build, and point your creates
at it.
</Step>
</Steps>

<CardGroup cols={2}>
<Card title="Workspace templates" icon="layer-group">
Prepare a workspace once and start sandboxes from it — as long as it does not need a
rootfs.
<Card title="Checkpoints" icon="camera" href="/sandboxes/checkpoints">
Save a running sandbox and restore it later.
</Card>
<Card title="Checkpoints" icon="camera">
Install into a sandbox, checkpoint it, and restore that checkpoint when you need the
environment again.
<Card title="Migrating from v1" icon="arrow-right" href="/migrating-from-v1">
Every behaviour that differs between v1 and v2.
</Card>
</CardGroup>
7 changes: 7 additions & 0 deletions sdks/typescript/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,5 +100,12 @@ export {
type TagKeyInfo,
} from "./usage.js";
// Node.js-only modules (use crypto, fs, path) — import via "@opencomputer/sdk/node".
// The Image builder and the Snapshots client are exported as VALUES, not only
// as types. Both were type-only, so `import { Image } from "@opencomputer/sdk"`
// — which the Image reference documents — failed at runtime with "does not
// provide an export named 'Image'", and there was no supported way to define a
// template through the SDK at all.
export { Image } from "./image.js";
export type { ImageManifest, ImageStep } from "./image.js";
export { Snapshots } from "./snapshot.js";
export type { SnapshotInfo, CreateSnapshotOpts, WaitForReadyOpts } from "./snapshot.js";