Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/opensandbox-group/OpenSandbox/llms.txt

Use this file to discover all available pages before exploring further.

OpenSandbox is built from four cooperating system components. Each component owns a distinct responsibility and communicates with the others over well-defined interfaces: the server manages lifecycle from the outside, execd handles execution from inside the sandbox, ingress routes external HTTP and WebSocket traffic to the right sandbox on Kubernetes, and egress enforces outbound network policy from within the sandbox’s own network namespace. Together they form a layered architecture that separates control, execution, routing, and security concerns cleanly.

Components at a Glance

ComponentLanguageRole
ServerPython (FastAPI)Lifecycle control plane — creates, monitors, and terminates sandboxes across Docker and Kubernetes
ExecdGo (Gin)In-sandbox execution daemon — HTTP APIs for shell, files, PTY, code, and metrics
IngressGoHTTP/WebSocket reverse proxy — routes Kubernetes traffic to sandbox instances via header or URI mode
EgressGoPer-sandbox FQDN egress sidecar — enforces allowlists, credential injection, and network policy

Component Interaction

┌─────────────┐     ┌─────────────┐
│   SDK/CLI   │────▶│   Ingress   │──────────────────┐
└─────────────┘     │  (K8s only) │                  │
                    └─────────────┘                  │

┌─────────────┐     ┌──────────────────────────────────────────┐
│   Server    │────▶│              Sandbox Pod / Container      │
│ (Control    │     │                                           │
│  Plane)     │     │  ┌──────────────────┐  ┌──────────────┐  │
│             │     │  │  execd :44772    │  │    Egress    │  │
│             │     │  │  • /command      │  │  :18080      │  │
│             │     │  │  • /session      │  │  • /policy   │  │
│             │     │  │  • /files        │  │  • DNS proxy │  │
│             │     │  │  • /code         │  │  • nftables  │  │
│             │     │  │  • /pty          │  │              │  │
│             │     │  │  • /metrics      │  │              │  │
│             │     │  └──────────────────┘  └──────────────┘  │
│             │     │                                           │
│             │     │  ┌──────────────────────────────────────┐ │
│             │     │  │    User Workload Container           │ │
│             │     │  │    (user image + entrypoint)         │ │
│             │     │  └──────────────────────────────────────┘ │
└─────────────┘     └──────────────────────────────────────────┘

Server

The server (server/) is the lifecycle control plane for the entire platform. It is a FastAPI application that authenticates incoming requests, validates configuration, persists server-managed metadata, and delegates all runtime work to either a Docker or Kubernetes service implementation.

Key responsibilities

  • API layer — HTTP request handling, input validation, and response formatting
  • Service layer — business logic for create, pause, resume, renew, and delete across runtimes
  • Middleware — API-key authentication via OPEN-SANDBOX-API-KEY header and request ID propagation
  • Runtime selection — routes lifecycle operations to DockerSandboxService or KubernetesSandboxService based on [runtime].type
  • Persistence — stores snapshot metadata and other server-managed records in SQLite (or a configured [store] backend)
  • Proxy and endpoint resolution — returns reachable sandbox endpoints; proxies HTTP and WebSocket traffic at /sandboxes/{id}/proxy/{port} when use_server_proxy=true

Key API endpoints

MethodPathDescription
GET/healthServer health check (unauthenticated)
POST/v1/sandboxesCreate a new sandbox
GET/v1/sandboxes/{id}Get sandbox state and metadata
POST/v1/sandboxes/{id}/pausePause a running sandbox
POST/v1/sandboxes/{id}/resumeResume a paused sandbox
POST/v1/sandboxes/{id}/renew-expirationExtend sandbox TTL
GET/v1/sandboxes/{id}/endpoints/{port}Resolve a sandbox service endpoint
DELETE/v1/sandboxes/{id}Delete a sandbox
GET/docsSwagger UI (unauthenticated)
GET/redocReDoc reference (unauthenticated)
See Server Deployment for the full installation and configuration guide.

Execd

execd (components/execd/) is a Go daemon built with the Gin framework. It runs inside every OpenSandbox sandbox and exposes the in-sandbox execution API. It is the bridge between the external SDK or CLI and the processes, files, and code running inside the sandbox container.

Key responsibilities

  • Shell commands — execute commands with Server-Sent Events streaming of stdout/stderr
  • Background commands — start commands, poll status, and fetch incremental logs
  • Persistent bash sessions — stateful shell sessions with input/output streaming
  • PTY sessions — interactive terminal over WebSocket (/pty)
  • File and directory operations — read, write, list, stat, delete files and directories
  • Code execution — Jupyter-backed code contexts for Python, Java, Node.js, Go, and TypeScript; translates kernel messages into OpenSandbox streaming events
  • Metrics — point-in-time CPU/memory snapshot (/metrics) and 1-second SSE stream (/metrics/watch); optional OTLP metrics export

Default port

execd listens on port 44772 inside the sandbox container. The Docker runtime maps this port to a random host port. In bridge mode, this single mapped port serves as the entry point for all sandbox services via the built-in reverse proxy (see Network Architecture).

Injection mechanism

The server stages the execd binary from the configured execd_image into the container filesystem and installs a bootstrap launcher script before the user entrypoint starts.

Execd CLI flags and environment variables

Flag / Env varDefaultDescription
--port / —44772HTTP listen port
--jupyter-host / JUPYTER_HOST""Jupyter server URL for code execution
--jupyter-token / JUPYTER_TOKEN""Jupyter authentication token
--access-token / EXECD_ACCESS_TOKEN""Optional shared API token; enforced via X-EXECD-ACCESS-TOKEN header
--log-level6 (Info)0=Emergency … 7=Debug
--graceful-shutdown-timeout / EXECD_API_GRACE_SHUTDOWN1sSSE tail-drain wait before shutdown
EXECD_CLONE3_COMPATunsetSet 1/true for seccomp clone3 fallback in restricted sandbox environments
OTEL_EXPORTER_OTLP_METRICS_ENDPOINTunsetEnable OTLP metrics export

Health check

curl http://localhost:44772/ping

Ingress

ingress (components/ingress/) is a Kubernetes-oriented HTTP and WebSocket reverse proxy written in Go. It watches BatchSandbox and AgentSandbox custom resources across all namespaces and routes incoming traffic to the correct sandbox pod based on request headers or URI structure.

Key responsibilities

  • Sandbox discovery — watches CRs via informer cache; reads endpoints from the sandbox.opensandbox.io/endpoints annotation (BatchSandbox) or status.serviceFQDN (AgentSandbox)
  • Traffic routing — dispatches each request to the right sandbox pod and port
  • Protocol support — HTTP and WebSocket (forwards Upgrade, Connection, and X-Forwarded-* headers)
  • Health check — exposes GET /status.ok
  • Auto-renew integration — optionally publishes renew-intent events to Redis on each proxied request

Routing modes

Routes based on the OpenSandbox-Ingress-To header or the Host header.Format: <sandbox-id>-<port>
# Via custom header
curl -H "OpenSandbox-Ingress-To: my-sandbox-8080" \
  https://ingress.opensandbox.io/api/users

# Via Host header
curl -H "Host: my-sandbox-8080.example.com" \
  https://ingress.opensandbox.io/api/users
The last --separated segment is treated as the port; everything before it is the sandbox ID. The original request path is preserved and forwarded.

Error codes

ConditionHTTP status
Sandbox CR not found404
Sandbox not ready (insufficient replicas, missing endpoints)503
Kubernetes API error or other internal error502

Starting ingress

go run main.go \
  --provider-type batchsandbox \
  --mode header \
  --port 28888 \
  --log-level info

Egress

egress (components/egress/) is a per-sandbox FQDN egress control sidecar. It runs alongside the user workload container, sharing its network namespace, and enforces outbound network policy via DNS proxying and optional nftables rules.

Key responsibilities

  • DNS proxy (Layer 1) — intercepts all port-53 DNS traffic via iptables redirect; returns NXDOMAIN for denied domains; runs on 127.0.0.1:15353
  • Network filter (Layer 2) — in dns+nft mode, adds nftables rules for resolved IPs of allowed domains with TTL so that default-deny is enforced at the network layer
  • Allow/deny rules — FQDN patterns, wildcard domains (*.pypi.org), IP addresses, and CIDR ranges
  • Always-rules — platform-managed deny.always and allow.always files that cannot be overridden by user policy
  • Credential vault — injects bearer, basic, API-key, or custom header credentials into matching outbound HTTPS requests via transparent mitmproxy
  • Runtime policy API — HTTP endpoints for inspecting and patching policy at runtime

Egress HTTP API

MethodPathDescription
GET/policyGet current policy and enforcement mode
POST/policyReplace policy (empty body resets to deny-all)
PUT/policyAlias for POST /policy
PATCH/policyAppend/merge rules (JSON array of egress rule objects)
DELETE/policyRemove rules by target (JSON string array)
GET/healthzHealth check — 200 ok when ready
The egress HTTP API listens on port 18080 by default (configurable via OPENSANDBOX_EGRESS_HTTP_ADDR).

Enforcement modes

ModeDescription
dnsDNS filtering only. Denied domains get NXDOMAIN. IP-based connections are not blocked.
dns+nftDNS filtering plus nftables IP enforcement. Recommended for strict default-deny deployments.

Always-rules files

Static rule files baked into the egress image take precedence over all user-supplied policy and are hot-reloaded every minute.
FilePriorityDescription
/var/egress/rules/deny.alwaysHighestAlways denied; user policy cannot override
/var/egress/rules/allow.alwaysHighAlways allowed; overrides user deny rules
/var/egress/rules/log_skip.alwaysPatterns to suppress from denial logs

Privilege model

  • The egress sidecar requires CAP_NET_ADMIN to set up iptables/nft rules.
  • The user workload container runs without NET_ADMIN — on Kubernetes, this capability is explicitly dropped from the main sandbox container so only the sidecar can mutate network rules.
The egress sidecar conflicts with transparent service mesh sidecars (Istio/Envoy). When both are present in the same pod, iptables redirect order is undefined and can produce double interception or broken TLS. Exclude sandbox pods from automatic mesh injection when using the egress sidecar. See Network Architecture for details.

Quick policy example

# Replace policy: deny all, allow *.pypi.org
curl -X POST http://127.0.0.1:18080/policy \
  -d '{"defaultAction":"deny","egress":[{"action":"allow","target":"*.pypi.org"}]}'

# Append a new allow rule
curl -X PATCH http://127.0.0.1:18080/policy \
  -d '[{"action":"allow","target":"*.github.com"}]'

# Remove a specific target
curl -X DELETE http://127.0.0.1:18080/policy \
  -d '["*.pypi.org"]'

Build docs developers (and LLMs) love