LogoFreestyle

Specs and Snapshots

Use specs and snapshots to create similar VMs quickly.

What is a VmSpec?

A VmSpec is a declarative configuration that defines how to set up a VM. Specs can include:

  • Files - Add files to the filesystem
  • Git repositories - Clone repos into the VM
  • Systemd services - Define background services and startup tasks
  • Users and groups - Create system users with specific permissions
  • Environment variables - Set environment configuration

Specs can be used directly to create a VM, or used as snapshot layers to enable caching.

Quick Start

import { freestyle, VmSpec } from "freestyle-sandboxes";

const spec = new VmSpec({
    // Add files to the VM
    additionalFiles: {
        "/tmp/hello-world.txt": {
            content: "Hello World!"
        }
    },
    // Clone a git repository
    gitRepos: [{
        repo: "https://github.com/owner/repo",
        path: "/app"
    }],
    // Define systemd services
    systemd: {
        services: [{
            name: "my-app",
            mode: "service",
            exec: ["npm start"],
            workdir: "/app"
        }]
    }
});

// Create a VM directly from the spec
const { vm } = await freestyle.vms.create({ spec });

What is a snapshot?

A snapshot is an immutable saved state of a VM, including its memory, disk, and CPU registers. Once created, snapshots are replicated across our network for fast VM creation anywhere. You can create snapshots in two ways:

1. Snapshot an existing VM

Call snapshot() on any VM (running, suspended, or stopped). Running/suspended VMs create "live" snapshots that resume instantly.

import { freestyle } from "freestyle-sandboxes";

const { vm } = await freestyle.vms.create();

// Set up the VM
await vm.exec("apt-get update && apt-get install -y nginx");
await vm.fs.writeTextFile("/etc/nginx/sites-available/default", nginxConfig);

// Create a reusable snapshot
const { snapshotId } = await vm.snapshot();

Tip: If you just need copies of the current VM for parallel work, use vm.fork() instead. It's faster for one-time duplication but doesn't create a reusable snapshot.

2. Create a snapshot declaratively with VmSpec

Use VmSpec to define your VM configuration, then pass it as a snapshot layer to cache it. Calling with the same snapshot spec returns the cached snapshot instantly.

const spec = new VmSpec({
    gitRepos: [{
        repo: "owner/my-app",
        path: "/app"
    }],
    additionalFiles: {
        "/app/.env": {
            content: "NODE_ENV=production"
        }
    },
    systemd: {
        services: [{
            name: "install-deps",
            mode: "oneshot",
            exec: ["npm install"],
            workdir: "/app",
            wantedBy: ["multi-user.target"]
        }]
    }
});

// First call builds and caches
const { vm } = await freestyle.vms.create({ snapshot: spec });

// Second call returns cached snapshot immediately
const { vm: vm2 } = await freestyle.vms.create({ snapshot: spec });

Using snapshots and specs

From a snapshot ID

const { vm } = await freestyle.vms.create({
    snapshotId,
});

Directly from a spec (no caching)

Pass the spec directly to freestyle.vms.create() to apply configuration without caching.

const { vm } = await freestyle.vms.create({
    spec,
});

Retrieving VMs with typed helpers

When you add integrations via with, the returned vm includes typed helper properties (for example vm.js, vm.python). To get those helpers back later, pass the same spec to vms.get() or vms.ref().

import { freestyle, VmSpec } from "freestyle-sandboxes";
import { VmNodeJs } from "@freestyle-sh/with-nodejs";

const spec = new VmSpec({
    with: {
        js: new VmNodeJs(),
    },
});

const { vmId, vm } = await freestyle.vms.create({ spec });
await vm.js.runCode("console.log('hello')");

// Later: retrieve by id with helpers restored
const { vm: loaded } = await freestyle.vms.get({ vmId, spec });
await loaded.js.runCode("console.log('hello again')");

// Or create a local reference without an API call
const ref = freestyle.vms.ref({ vmId, spec });
await ref.js.runCode("console.log('hello from ref')");

Layering additional configuration

Apply extra configuration on top of a snapshot by passing additional options to freestyle.vms.create(). These settings are not cached.

const { vm } = await freestyle.vms.create({
    snapshot: spec, // or snapshotId
    additionalFiles: {
        "/tmp/goodbye-world.txt": {
            content: "Goodbye World!"
        }
    },
    env: {
        API_KEY: "secret-key"
    }
});

Building layered specs

Create reusable base specs and extend them for specific use cases. Snapshot layers are cached; outer layers are applied on top.

Base spec with a snapshot

const layer1 = new VmSpec({
    additionalFiles: {
        "/opt/layer-1.txt": {
            content: "layer 1 data"
        }
    },
});

const layer2 = new VmSpec({
    snapshot: layer1,
    additionalFiles: {
        "/opt/layer-2.txt": {
            content: "layer 2 data"
        }
    },
});

On this page

Freestyle AI

Documentation assistant

Experimental: AI responses may not always be accurate—please verify important details with the official documentation.

How can I help?

Ask me about Freestyle while you browse the docs.