MetorialDocs

Run your first machine

Create a sandbox machine, run a command in it, and clean up.

This guide takes you from nothing to a running machine you can run commands in. It takes about two minutes.

What you'll learn

  • How to pick an image and a region
  • How to create and start a machine
  • How to run commands and move files
  • How to delete a machine

Before you start

With the CLI

Pick a region

List the regions you can run machines in and note an identifier such as iad1:

metorial-admin sandbox regions list

Pick an image

Metorial manages a set of images for common stacks: Debian, Alpine, Node.js, Bun, Deno, Python, Go, Java, PHP, .NET, and images with browser automation preinstalled. Find one and copy its ID (sbi_...):

metorial-admin sandbox images list --owner global --search debian

Create the machine

Machines start right away unless you pass --start=false. Without a size, the machine gets the default size.

metorial-admin sandbox machines create \
  --region iad1 \
  --image-id sbi_your_image_id \
  --name first-machine

Save the machine ID from the output and check its status. It moves from starting to running within a few seconds.

MACHINE=sma_your_machine_id
metorial-admin sandbox machines get $MACHINE

Run a command

Anything after -- runs inside the machine. The CLI exits with the command's exit code.

metorial-admin sandbox machines shell $MACHINE -- uname -a

Leave out the command to open an interactive shell.

Move a file in and out

echo "hello from my laptop" | metorial-admin sandbox machines files upload $MACHINE - /tmp/hello.txt
metorial-admin sandbox machines files cat $MACHINE /tmp/hello.txt

Delete the machine

Deleting a machine also deletes its root disk. Attached disks are kept.

metorial-admin sandbox machines delete $MACHINE

With the SDK

The same flow in code. Machine operations return the machine object; shell() and files() open a live connection to the machine.

import { Metorial } from 'metorial';

let metorial = new Metorial({ apiKey: process.env.METORIAL_API_KEY! });

let machine = await metorial.sandbox.machines.create({
  region: 'iad1',
  imageId: 'sbi_your_image_id',
  name: 'first-machine'
});

while (machine.status != 'running') {
  if (machine.status == 'failed') throw new Error(machine.failure?.message);
  await new Promise(resolve => setTimeout(resolve, 1000));
  machine = await metorial.sandbox.machines.get(machine.id);
}

let shell = await metorial.sandbox.machines.shell(machine.id);
let result = await shell.command('uname -a');
console.log(result.exitCode, result.stdout);

let files = await metorial.sandbox.machines.files(machine.id);
await files.write('/tmp/hello.txt', 'hello from my app');
console.log(await files.readText('/tmp/hello.txt'));

shell.close();
files.close();
await metorial.sandbox.machines.delete(machine.id);

Note

In Python, resource calls such as create and get are synchronous. The live helpers shell(), files(), and connect() are async.

Next steps