Skip to content

bas3line/sandbox

Repository files navigation

███████╗ █████╗ ███╗   ██╗██████╗ ██████╗  ██████╗ ██╗  ██╗
██╔════╝██╔══██╗████╗  ██║██╔══██╗██╔══██╗██╔═══██╗╚██╗██╔╝
███████╗███████║██╔██╗ ██║██║  ██║██████╔╝██║   ██║ ╚███╔╝
╚════██║██╔══██║██║╚██╗██║██║  ██║██╔══██╗██║   ██║ ██╔██╗
███████║██║  ██║██║ ╚████║██████╔╝██████╔╝╚██████╔╝██╔╝ ██╗
╚══════╝╚═╝  ╚═╝╚═╝  ╚═══╝╚═════╝ ╚═════╝  ╚═════╝ ╚═╝  ╚═╝

Burn the code. Keep the host.

A self-hosted Rust control plane for disposable coding environments and AI agents.

Architecture · Security · Setup guides · Server setup · Client setup · Custom domains · CLI · MCP

Bas3line Sandbox: a safe playground for coding agents

One-command workstation setup

Install sandbox, sandboxd, sandbox-mcp, the Sandbox skill across supported agents, and register the MCP server with detected Codex, Claude Code, and Gemini CLIs:

curl -fsSL https://tools.yshubham.com/sandbox/setup.sh | sh

The full setup uses npx to install the skill across supported coding agents. For binaries only:

curl -fsSL https://tools.yshubham.com/sandbox/install.sh | sh
sandbox --help

The initial registry build publishes macOS ARM64 and Linux x86-64. The release workflow covers macOS x86-64 and Linux ARM64 as additional builders become available. Release binaries bundle libpq and vendored OpenSSL so sandboxd does not depend on a machine-specific PostgreSQL client path.

Then point the client at your self-hosted controller:

sandbox config set-server https://sandbox.example.com
export SANDBOX_TOKEN='read-from-your-secret-store'
sandbox doctor

The CLI saves only the non-secret controller URL. SANDBOX_URL or --server can override it for one environment or command.

See server setup, client setup, custom public domains, MCP setup, and the registry-hosted sandbox-platform skill.

Hosted documentation is available as a human portal, a raw agent index, and an llms.txt discovery file.

The MCP guide includes native setup for Codex, Claude Code, Gemini CLI, OpenCode, VS Code/Copilot, and Goose, plus drop-in templates for Cursor, Claude Desktop, Windsurf, Cline, Roo Code, Gemini Code Assist, and generic MCP clients. Agents without native MCP support use the same sandbox CLI and installed skill.

Why I am open-sourcing this

Sandbox started as private infrastructure I built to give coding agents fast, disposable machines without handing them the host. I kept running into the same problem: every team building with agents eventually needs remote execution, lifecycle management, resource limits, and a clean way to destroy everything afterward.

I am open-sourcing it so other engineers can use the foundation, adapt it to their own infrastructure, and help push self-hosted agent sandboxes forward. It is opinionated, practical, and still evolving—but it is real software, built to be run, forked, broken, improved, and shared.

Sandbox gives every human, CI job, and coding agent a typed remote execution boundary. One daemon, sandboxd, runs as a controller, worker, or both. The tiny sandbox CLI and sandbox-mcp bridge use the same authenticated API. PostgreSQL provides durable state; NATS is optional; Redis is deliberately not required. The default control plane stays lean.

sandbox create --tenant platform --image ubuntu:24.04 \
  --cpu-millis 2000 --memory-mib 4096 --ttl 3600 \
  --network restricted --untrusted-repo --generated-code

sandbox exec 019f... -- cargo test --workspace
sandbox http 3000
sandbox tunnel create 019f... --port 3000
sandbox agent run codex --tenant platform
sandbox delete 019f...

sandbox http PORT shares a service running on your current machine at a temporary https://local-….tunnel.yshubham.com URL through the hosted Sandbox relay. No third-party quick-tunnel domain or helper binary is involved. HTTP and WebSocket traffic—including Vite HMR—is carried over one outbound WebSocket and rewritten to the loopback origin, so development servers never need to allow a random public Host. Keep the command running and press Ctrl-C to revoke the exact-host route. Self-hosters can set SANDBOX_HTTP_RELAY; services inside a managed sandbox continue to use sandbox tunnel create SANDBOX_ID --port PORT.

What is already real

Capability Status
Controller/worker scheduling, leases, heartbeats, TTL cleanup Implemented
AEGIS risk scoring and placement Implemented and unit tested
Hardened Docker worker Implemented; intended for dedicated single-tenant worker hosts
External runtime protocol for Firecracker, Kata, gVisor, or private VMMs Implemented adapter contract; bring a driver
PostgreSQL through Diesel + in-memory development store Implemented
NATS lifecycle events + zero-service in-memory bus Implemented
CLI lifecycle, agent profiles, JSON output, bounded exec Implemented
MCP 2025-11-25 stdio server with structured tool results Implemented
Wildcard HTTP/WebSocket tunnels with per-sandbox edge networks Implemented; custom HTTPS domains, direct edge, and Cloudflare ingress documented
Local HTTP/WebSocket sharing on the deployment wildcard Implemented; ephemeral exact-host routes, bounded sessions/bodies, automatic revocation
Codex, Claude Code, OpenCode, Pi image builder Implemented with pinned versions
Aider and Goose profiles Implemented using their official images
OIDC/SAML, tenant RBAC, secret broker, interactive PTY, raw TCP tunnels Design boundary; not implemented in v0.1

This repository is an engineering foundation, not a magic claim that Docker equals a hardened multi-tenant VM. Read the security model before exposing it to hostile tenants.

AEGIS: the custom isolation algorithm

AEGIS—Adaptive Execution Guard and Isolation Scheduler—does two jobs in one deterministic pass:

  1. Scores workload risk from data sensitivity, network access, repository trust, generated-code execution, secret use, host mounts, exposure, privilege, and lifetime.
  2. Chooses the minimum isolation tier, hard-filters unsafe nodes, then ranks survivors using dominant-resource headroom, fragmentation, host pressure, image warmth, region locality, and bin-packing efficiency.

A high-risk request cannot downgrade itself to a container. If no compatible microVM worker exists, the request fails with no_capacity; it never silently weakens isolation. See docs/aegis.md.

The shape

flowchart LR
    A["Humans / Codex / Claude / OpenCode / CI"] --> C["sandbox CLI"]
    A --> M["sandbox-mcp"]
    C --> P["sandboxd controller"]
    M --> P
    P --> G["Auth + policy + AEGIS"]
    G --> D[("PostgreSQL")]
    G -. events .-> N["NATS (optional)"]
    G --> W1["sandboxd worker: Docker"]
    G --> W2["sandboxd worker: external driver"]
    W1 --> X["Hardened containers"]
    W1 --> T["Private tunnel networks + HTTP edge"]
    W2 --> V["Firecracker / Kata / gVisor / private VMM"]
Loading

sandboxd is one deployable executable. Split controller and worker processes for production blast-radius control; use --role all only for development or a dedicated single-node installation.

Five-minute developer launch

Requirements: Docker with Compose and two random tokens of at least 32 characters.

export SANDBOX_API_TOKEN="$(openssl rand -hex 32)"
export SANDBOX_NODE_TOKEN="$(openssl rand -hex 32)"
docker compose -f deploy/compose/compose.yaml up --build

In another terminal:

export SANDBOX_URL=http://127.0.0.1:8080
export SANDBOX_TOKEN="$SANDBOX_API_TOKEN"
cargo run --package sandbox-cli -- doctor
cargo run --package sandbox-cli -- create --tenant dev --image ubuntu:24.04 --ttl 900

The Compose stack intentionally sets the microVM threshold above the score range so it can run on a normal Docker laptop. That is a developer convenience, not the production policy. Production keeps the default threshold of 55 and supplies compatible workers.

To publish sandbox services, configure wildcard DNS and enable an edge profile. Direct Traefik, Caddy, proxied Cloudflare with Origin CA and Full (strict), an outbound-only Cloudflare Tunnel overlay, and a clearly marked HTTP compatibility mode are documented in docs/tunnels.md. Follow the custom-domain setup for the complete path. The outbound Cloudflare option keeps the origin off public ingress; real deployment domains, connector tokens, addresses, and certificate material belong in the environment or secret store, never the repository.

Coding agents

Pinned image builders are included for:

./scripts/build-agent-image.sh codex
./scripts/build-agent-image.sh claude
./scripts/build-agent-image.sh opencode
./scripts/build-agent-image.sh pi
sandbox agent list

Agent credentials do not belong in command arguments, labels, or plaintext API fields. Connect the external runtime driver to Vault, AWS Secrets Manager, GCP Secret Manager, or your existing workload-identity broker. See docs/agents.md.

Repository map

cmd/
  sandbox/       # operator + agent CLI
  sandboxd/      # controller/worker/all-in-one daemon
  sandbox-mcp/   # stdio MCP bridge
crates/
  core/          # domain model, API contracts, configuration
  aegis/         # risk and placement algorithm
  storage/       # Diesel/PostgreSQL + memory store
  runtime/       # Docker + external runtime adapters
  events/        # memory + NATS event bus
  client/        # typed HTTP client
config/          # reviewed configuration examples
deploy/          # Compose and systemd packaging
docs/            # architecture, security, API, operations
images/agents/   # reproducible coding-agent image inputs
scripts/         # release installer and image tooling
skills/          # Codex-compatible Sandbox skill

Non-negotiable design rules

  • Policy is enforced by the server and runtime, never by an agent prompt.
  • Commands cross the API as argv, not interpolated shell text.
  • Privileged sandboxes are rejected by the public API.
  • Output, request bodies, runtime duration, PIDs, CPU, RAM, and TTL are bounded.
  • Tokens are separated for operators and workers and compared in constant time.
  • Docker socket workers belong on dedicated hosts. Strong multi-tenancy uses a VMM-grade external driver.
  • Every release archive gets a SHA-256 checksum and signed SLSA provenance; the installer fails closed on checksum mismatch.

Build

cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
cargo build --profile dist --workspace

After deploying to a test controller, exercise the complete CLI lifecycle and public tunnel path:

SANDBOX_URL=https://sandbox.example.com \
SANDBOX_TOKEN='read-from-your-secret-store' \
./scripts/smoke-test-cli.sh

Rust is pinned to 1.97.1. Direct dependencies were resolved to current stable releases on 2026-07-19 and are locked in Cargo.lock.

License

Apache-2.0. Fork it, harden it for your infrastructure, write a runtime driver, and make every untrusted build somebody else's kernel problem.

About

A self-hosted Rust control plane for disposable coding environments and AI agents

Resources

License

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages