Skip to content
Runtime

How to compile and run Rust code in a sandbox

Install Rust with rustup or Ubuntu's rustc and cargo in an isolated microVM, build the code there, and run it with the network off.

On Runtime, untrusted Rust is contained at two points: build time and run time. Cargo runs a package's build.rs just before it builds the package, so the build executes other people's code. That code belongs in the sandbox, as the binary does. Each Runtime sandbox is a Firecracker microVM with its own kernel, gcc and sudo. A 2 vCPU, 4 GiB sandbox costs $0.08 an hour with both CPUs compiling (pricing).

Which Rust to install

Source Package or command Version on 26 October 2026
Ubuntu 24.04 archive (main) sudo apt-get install -y rustc cargo 1.75.0
Ubuntu 24.04 archive (universe) sudo apt-get install -y rustc-1.91 1.91.1
rustup, the official installer the sh.rustup.rs script, below 1.99.1, the current stable release

The image has none of these. It has the C toolchain (gcc, g++, make) that crates with C code build against. Choose rustup if your code or its crates need a recent compiler.

Install with rustup and run a program

rustup installs rustc, cargo and rustup into ~/.cargo/bin (Rust); in a sandbox, home is /workspace. -y skips the prompts and --profile minimal leaves out the docs (rustup).

TypeScriptimport { Sandbox } from "withruntime";const program = `fn main() {    let words = ["sandbox", "microvm", "kernel"];    let longest = words.iter().max_by_key(|w| w.len()).unwrap();    println!("{longest}");}`;await using sbx = await Sandbox.create({ diskMiB: 8192, timeoutSeconds: 1200, onLeaseEnd: "stop" });await sbx.exec(  "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal",  { check: true, timeoutMs: 600_000 },);await sbx.network.set({ internet: false }); // compile and run offlineawait sbx.files.write("/workspace/job/main.rs", program);const cargoBin = "/workspace/.cargo/bin";const build = await sbx.exec([`${cargoBin}/rustc`, "-O", "main.rs", "-o", "main"], {  cwd: "/workspace/job",  timeoutMs: 300_000,});if (build.exitCode !== 0) console.error(build.stderr);const run = await sbx.exec(["./main"], { cwd: "/workspace/job", timeoutMs: 10_000 });console.log(run.stdout); // sandbox
Pythonfrom withruntime import Sandboxprogram = """fn main() {    let words = ["sandbox", "microvm", "kernel"];    let longest = words.iter().max_by_key(|w| w.len()).unwrap();    println!("{longest}");}"""with Sandbox.create(disk_mib=8192, timeout_seconds=1200, on_lease_end="stop") as sbx:    sbx.exec("curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal",             check=True, timeout_ms=600_000)    sbx.network.set(internet=False)  # compile and run offline    sbx.files.write("/workspace/job/main.rs", program)    cargo_bin = "/workspace/.cargo/bin"    build = sbx.exec([f"{cargo_bin}/rustc", "-O", "main.rs", "-o", "main"],                     cwd="/workspace/job", timeout_ms=300_000)    if build.exit_code != 0:        print(build.stderr)    run = sbx.exec(["./main"], cwd="/workspace/job", timeout_ms=10_000)    print(run.stdout)  # sandbox
  • Disk: the default 4 GiB sandbox had about 2.5 GiB free on 26 October 2026. A toolchain and a target folder use a lot of space, so request 8 GiB.
  • Time: set a timeoutMs on the install and on each build. The default is 60 seconds. The sandbox has no time limit unless timeoutSeconds sets one.
  • Errors: compiler errors go to stderr. Return them to the model that wrote the code, unchanged.

A Cargo project

Fetch the crates with the network on, then build and test offline, so neither build.rs nor the tests can make outside calls:

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({  image: "rust",  diskMiB: 8192,  timeoutSeconds: 3600,  onLeaseEnd: "stop",});await sbx.files.upload("./my-crate", "/workspace/crate");await sbx.exec("cargo fetch", { cwd: "/workspace/crate", check: true, timeoutMs: 600_000 });await sbx.network.set({ internet: false });const test = await sbx.exec(["cargo", "test", "--offline"], {  cwd: "/workspace/crate",  timeoutMs: 1_800_000,  onStdout: (text) => process.stdout.write(text),  onStderr: (text) => process.stderr.write(text),});console.log("exit", test.exitCode);
Pythonimport sysfrom withruntime import Sandboxwith Sandbox.create(image="rust", disk_mib=8192, timeout_seconds=3600, on_lease_end="stop") as sbx:    sbx.files.upload("./my-crate", "/workspace/crate")    sbx.exec("cargo fetch", cwd="/workspace/crate", check=True, timeout_ms=600_000)    sbx.network.set(internet=False)    test = sbx.exec(["cargo", "test", "--offline"], cwd="/workspace/crate", timeout_ms=1_800_000,                    on_stdout=sys.stdout.write, on_stderr=sys.stderr.write)    print("exit", test.exit_code)

This uses the rust image defined below. Both streams print as the build runs.

Rust in every sandbox

Install the toolchain once in a custom image so that no sandbox has to wait for it. rustup reads RUSTUP_HOME and CARGO_HOME to find its files, and both must be set whenever the toolchain runs (rustup). A recipe's env stays set in every sandbox made from the image. Recipe commands run as root, so the last command lets the sandbox user write to Cargo's cache.

TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.images.build({  name: "rust",  recipe: {    env: { RUSTUP_HOME: "/usr/local/rustup", CARGO_HOME: "/usr/local/cargo" },    commands: [      "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --no-modify-path",      "ln -sf /usr/local/cargo/bin/* /usr/local/bin/",      "chmod -R a+w /usr/local/rustup /usr/local/cargo",    ],  },});
Pythonfrom withruntime import Runtimeruntime = Runtime()runtime.images.build(name="rust", recipe={    "env": {"RUSTUP_HOME": "/usr/local/rustup", "CARGO_HOME": "/usr/local/cargo"},    "commands": [        "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --no-modify-path",        "ln -sf /usr/local/cargo/bin/* /usr/local/bin/",        "chmod -R a+w /usr/local/rustup /usr/local/cargo",    ],})

To use Ubuntu's compiler instead, the recipe is { apt: ["rustc", "cargo"] }. Building an image is free. A stored image is charged by its size.

Many builds at once

Each sandbox is its own machine with its own disk, so parallel builds never share a target folder or a lock on Cargo's cache. A paid account runs 100 sandboxes at the same time. Every account gets 100 free hours of a 1 GB machine in its first 30 days, with no card required:

Terminalnpx withruntime sandboxes run -- bash -c 'sudo apt-get update -q && sudo apt-get install -y -q rustc && rustc --version'

Sources

Facts on this page were checked on 26 October 2026.

100 free hoursin your first 30 days.

of a 1 GB machine

  • No credit card
  • Four sandboxes at once, 2 vCPU and 4 GiB each
  • Then prepaid credit from $10, no plan fee
Start free, no card
Start free, no card