# How to give every hackathon team a cloud dev environment Create one named sandbox per team from a starter image, give teams SSH and a public demo link, cap the spend, and stop them all by label. **On Runtime a team's machine for a 48-hour hackathon costs about $2.04.** A 2 vCPU, 4 GiB sandbox is billed on the CPU the team's code uses, $0.025 per vCPU-hour, plus $0.0075 per GiB-hour of memory, so the hours a team spends arguing over the pitch cost $0.03125 each ([pricing](/docs/pricing), 25 September 2026). Every team gets its own Firecracker microVM, with `sudo`, Docker and the event's starter kit already installed. ## What organizers need from event machines A hackathon compresses a year of dev-environment problems into a weekend: laptops that cannot install the SDK, a sponsor API that needs a key, a demo that only runs on one person's machine. Cloud machines for every team solve that if they are: - **Identical at the start**, with the starter kit installed, so the first hour is spent building. - **Separate**, so one team's `rm -rf` or leaked key touches nobody else. - **Reachable for judging**, with a URL that works on the judges' phones. - **Bounded in cost**, per team and for the whole event. - **Easy to shut down**, all at once, when the event ends. ## Prepare the starter image Build the image once with what every team needs. Each build is a numbered version; pin the one you tested: ```ts check import { Runtime } from "withruntime"; const runtime = new Runtime(); const image = await runtime.images.build({ name: "hack-starter", recipe: { apt: ["postgresql-client", "redis-tools"], pip: ["fastapi", "uvicorn", "httpx"], npm: ["vite", "typescript"], commands: ["enable-docker --no-start"], }, }); console.log(`hack-starter@${image.version}`); ``` `enable-docker --no-start` puts Docker Engine and Compose in the image; the first `docker` command a team runs starts it. Store the sponsor's API key once as a Runtime secret for the sponsor's host, and every team's code can call the API while no team ever holds the key ([security](/docs/security#secrets-sandboxes-never-see)). ## One sandbox per team Name each sandbox after its team and label all of them with the event, so you can find one by name and every one by label: ```ts check import { Runtime } from "withruntime"; const runtime = new Runtime(); const teams = ["byte-club", "null-pointers", "404-found"]; for (const team of teams) { const sbx = await runtime.sandboxes.create({ name: `hack-${team}`, image: "hack-starter@1", vcpu: 2, memoryMiB: 4096, diskMiB: 16_384, funding: "paid", persistent: true, // keeps running while credit lasts; no lease to extend overnight maxTotalCostMicros: 10_000_000, // at most $10 for this team over the event labels: { event: "hack-2026-10", team }, }); console.log(team, sbx.id); } ``` ```python check from withruntime import Runtime runtime = Runtime() for team in ["byte-club", "null-pointers", "404-found"]: sbx = runtime.sandboxes.create( name=f"hack-{team}", image="hack-starter@1", vcpu=2, memory_mib=4096, disk_mib=16_384, funding="paid", persistent=True, max_total_cost_micros=10_000_000, # at most $10 for this team labels={"event": "hack-2026-10", "team": team}, ) print(team, sbx.id) ``` `persistent: true` renews the sandbox's lease on the server for as long as the account has credit, so a team's server keeps running through the night. `maxTotalCostMicros` is the ceiling on that one sandbox over its whole life. ## Let teams in Invite each participant to the event's account at [Members](https://withruntime.com/account/members) with the **Developer** role. They connect the CLI with one browser approval, then open their team's machine by name: ```bash no-run npx withruntime login runtime sandbox ssh hack-byte-club runtime sandbox ssh config --install # then VS Code's Remote - SSH to hack-byte-club.runtime runtime sandbox port-forward hack-byte-club 5173 ``` SSH, VS Code, JetBrains Gateway and port forwarding all go through Runtime's API with the participant's own connection, so the sandbox opens no port to the internet ([SSH and editors](/docs/editors)). Each connection is a key of its own: an owner or admin can set a daily spending limit on it, or revoke it, from [API keys](https://withruntime.com/account/keys), and every key made or limited is in the account's audit log ([teams](/docs/teams)). ## Demo links for judging When a team's app is ready, share its port as a public HTTPS address that works on any phone: ```ts check import { Sandbox } from "withruntime"; const sbx = await Sandbox.getOrCreate("hack-byte-club"); // the team's existing sandbox const preview = await sbx.previews.create(5173, { visibility: "public" }); console.log(preview.url); // under runtimehost.com, apart from Runtime's own site ``` WebSockets pass through, so a dev server's live reload works in the demo. `previews.delete(5173)` stops sharing after the judging. ## End the event List every sandbox with the event's label, turn persistence off so a stopped disk is not kept, and stop it. Copy out anything a team wants to keep first, with `files.download` or `git push`: ```ts check import { Runtime } from "withruntime"; const runtime = new Runtime(); const page = await runtime.sandboxes.list({ labels: { event: "hack-2026-10" } }); for await (const sbx of page) { await sbx.update({ persistent: false }); await sbx.stop(); console.log("stopped", sbx.info.name); } ``` A stopped persistent sandbox keeps its disk, billed as reserved disk, so `restart()` can bring it back. Turning persistence off first makes each one an ordinary sandbox again before it stops. ## What a hackathon needs | Need | How Runtime covers it | | ---------------------------------- | --------------------------------------------------------------------------- | | The same kit for every team | A versioned custom image, pinned as `hack-starter@1` | | A machine per team | A named sandbox, a Firecracker microVM with its own kernel | | Root for installs, not for billing | `sudo` in the guest; CPU, memory, network and cost enforced on the host | | Sponsor API keys | Runtime secrets: a placeholder in the sandbox, the value added by the proxy | | Editors and terminals | `runtime sandbox ssh`, VS Code, JetBrains, port forwarding | | Demos for judges | Public previews under `runtimehost.com` | | A budget per team | `maxTotalCostMicros` per sandbox; a daily limit per key | | Everything off at the end | `sandboxes.list({ labels })`, then stop | A paid account runs 100 sandboxes at once to start; for a larger event, write to support with the numbers you need ([pricing](/docs/pricing#how-many-at-once)). ## What it costs Take 30 teams, each with a 2 vCPU, 4 GiB sandbox running for the whole 48 hours, using half a vCPU on average: ``` CPU: 30 × 48 h × 0.5 vCPU × $0.025 = $18.00 Memory: 30 × 48 h × 4 GiB × $0.0075 = $43.20 Total: $61.20 ``` About $2.04 a team. Building the starter image is free; storing it costs $0.08 per GB per 30-day month on its whole file, and the free trial stores your first three images free. New accounts get 50 free sandbox hours with no card and run eight trial sandboxes at once, enough to rehearse the setup with a few test teams before the event. ## Start ```bash no-run npx withruntime sandbox run --trial --keep -- python3 --version ``` The first run prints a link to approve in your browser. Then build the image and create the teams' sandboxes as above. Related: [per-user dev environments](/use-cases/per-user-dev-environments), [preview agent-built apps](/use-cases/preview-agent-built-apps), [run Docker in a sandbox](/how-to/run-docker-in-a-sandbox), [pause and resume a sandbox](/how-to/pause-and-resume-a-sandbox). Facts on this page were checked on 25 September 2026.