Skip to content
Runtime

How to run Ruby code in a sandbox

Install Ruby from Ubuntu in an isolated Linux microVM, or start from the official Ruby image, then run the file with ruby under a timeout.

On Runtime, you choose the Ruby: Ubuntu's 3.2 with one apt command, or Ruby 4.0 from the official Docker image, built once into a sandbox image. Each sandbox is a Firecracker microVM with its own kernel and sudo. The default image includes gcc and make for gems with C extensions. A 2 vCPU, 4 GiB sandbox costs $0.03125 an hour while it waits and $0.08 with both CPUs busy (pricing).

Which Ruby to use

Source Ruby version on 26 October 2026 How
Ubuntu 24.04 ruby package (main) 3.2.3 sudo apt-get install -y ruby
Ubuntu 24.04 ruby-full (universe) 3.2.3, with headers and docs sudo apt-get install -y ruby-full
Official ruby image on Docker Hub 4.0 (tags 4.0.9, 4.0-slim) A custom image built from it, below
rbenv with ruby-build, or mise Any release you build Ruby's recommended version managers

Ruby's own site lists 4.0.9 and 3.4.12 as the stable releases, gives sudo apt-get install ruby-full for Ubuntu, and notes that package managers may install older versions than the latest (Ruby).

Ruby is not in the default sandbox image, and the code interpreter does not support it. Run Ruby as a file or script with exec.

Install Ruby and run a file

TypeScriptimport { Sandbox } from "withruntime";const program = `words = ARGV.first.splitcounts = words.tally.sort_by { |_, n| -n }.first(3)puts counts.map { |w, n| "#{w}=#{n}" }.join(" ")`;await using sbx = await Sandbox.create({ timeoutSeconds: 900, onLeaseEnd: "stop" });await sbx.exec("sudo apt-get update -q && sudo apt-get install -y -q ruby", {  check: true,  timeoutMs: 600_000,});await sbx.network.set({ internet: false }); // the program runs offlineawait sbx.files.write("/workspace/top.rb", program);const run = await sbx.exec(["ruby", "top.rb", "a b a c b a"], { timeoutMs: 30_000 });console.log(run.exitCode, run.stdout); // 0 a=3 b=2 c=1
Pythonfrom withruntime import Sandboxprogram = """words = ARGV.first.splitcounts = words.tally.sort_by { |_, n| -n }.first(3)puts counts.map { |w, n| "#{w}=#{n}" }.join(" ")"""with Sandbox.create(timeout_seconds=900, on_lease_end="stop") as sbx:    sbx.exec("sudo apt-get update -q && sudo apt-get install -y -q ruby",             check=True, timeout_ms=600_000)    sbx.network.set(internet=False)  # the program runs offline    sbx.files.write("/workspace/top.rb", program)    run = sbx.exec(["ruby", "top.rb", "a b a c b a"], timeout_ms=30_000)    print(run.exit_code, run.stdout)  # 0 a=3 b=2 c=1
  • The text reaches the program unchanged, as ARGV.first. An array runs ruby with no shell, so quotes and semicolons in the text are plain characters.
  • Errors and backtraces go to stderr, and the exit code is non-zero.
  • A script that does not end returns timedOut: true after timeoutMs, with the output it printed up to that point.

Gems

Install gems while the network is on, then turn the network off before you run code you do not trust. You control the sandbox, so sudo gem install into the system Ruby works:

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ timeoutSeconds: 1200, onLeaseEnd: "stop" });await sbx.exec("sudo apt-get update -q && sudo apt-get install -y -q ruby-full", {  check: true,  timeoutMs: 600_000,});await sbx.exec("sudo gem install --no-document rainbow", { check: true, timeoutMs: 300_000 });await sbx.network.set({ internet: false });await sbx.files.write("/workspace/hi.rb", 'require "rainbow"\nputs Rainbow("ok").green');console.log((await sbx.exec(["ruby", "hi.rb"], { timeoutMs: 30_000 })).stdout);

ruby-full depends on ruby-dev, which provides the headers that gems with C extensions build against. The image's gcc compiles them.

A Rails or Bundler project

Upload the project, install the bundle, then run the tests with the network off:

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({  image: "ruby4",  diskMiB: 8192,  timeoutSeconds: 3600,  onLeaseEnd: "stop",});await sbx.files.upload("./my-app", "/workspace/app");await sbx.exec("bundle install", { cwd: "/workspace/app", check: true, timeoutMs: 900_000 });await sbx.network.set({ internet: false });const test = await sbx.exec(["bundle", "exec", "rake", "test"], {  cwd: "/workspace/app",  timeoutMs: 1_800_000,  onStdout: (text) => process.stdout.write(text),});console.log("exit", test.exitCode);

This uses the ruby4 image defined below. When timeoutMs is over 60 seconds, the output streams as it arrives, and the result still holds all of it.

Ruby in every sandbox

A custom image can start from any public image, so the official Ruby image gives every sandbox Ruby 4.0 with no install step. Or add Ubuntu's Ruby to the Runtime base image with a recipe:

TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.images.build({ name: "ruby4", image: "ruby:4.0-slim" });await runtime.images.build({ name: "ruby32", recipe: { apt: ["ruby-full"] } });await using sbx = await runtime.sandboxes.create({ image: "ruby4", network: { internet: false } });console.log((await sbx.exec(["ruby", "--version"])).stdout);
Pythonfrom withruntime import Runtimeruntime = Runtime()runtime.images.build(name="ruby4", image="ruby:4.0-slim")runtime.images.build(name="ruby32", recipe={"apt": ["ruby-full"]})with runtime.sandboxes.create(image="ruby4", network={"internet": False}) as sbx:    print(sbx.exec(["ruby", "--version"]).stdout)

The recipe image keeps the Runtime base image, so Python, Node.js and the usual tools are still available next to Ruby. Building is free. A stored image is charged by its size.

A new 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 ruby && ruby --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