e2b-local is a local E2B-compatible gateway written in Go. It accepts requests from E2B SDKs and runs sandboxes on local infrastructure:
- Docker containers through the Docker Engine API
- OrbStack Linux VMs through the OrbStack CLI
- Apple Container through its native XPC services on macOS
The HTTP layer follows the E2B OpenAPI schema where practical, while runtime-specific work lives behind Docker, OrbStack, and Apple Container backend packages.
Copy the default config:
cp config.example.yaml config.yamlThe default runtime is Docker. Start the gateway:
go run ./cmd/e2b-local --config config.yamlCreate a volume through the CLI:
go run ./cmd/e2b-local volume create --config config.yaml test-volumeThe command reuses the configured runtime and returns the same JSON shape as POST /volumes, for example:
{"volumeID":"test-volume","name":"test-volume","token":"compat-volume-token-test-volume"}flowchart LR
SDK["E2B SDK callers"] -->|"E2B API requests<br/>E2B_API_URL"| Gateway["e2b-local gateway<br/>cmd/e2b-local"]
subgraph ControlPlane["Control plane"]
Gateway --> HTTP["Gin HTTP server<br/>internal/gateway"]
HTTP --> OpenAPI["Generated OpenAPI handlers<br/>internal/e2bapi"]
OpenAPI --> Callbacks["Gateway callbacks<br/>sandbox, template, volume, metrics"]
Callbacks --> Store["In-memory stores<br/>sandbox + management state"]
Callbacks --> Registry["Runtime registry<br/>RegisterSandboxRuntimeFactory"]
end
subgraph RuntimeBackends["Runtime backends"]
Registry --> Docker["Docker runtime<br/>internal/backends/docker"]
Registry --> OrbStack["OrbStack runtime<br/>internal/backends/orbstack"]
Registry --> AppleContainer["Apple Container runtime<br/>internal/backends/applecontainer"]
end
subgraph DockerRuntime["Docker"]
Docker --> Containers["Sandbox containers<br/>from local images"]
Docker --> DockerVolumes["Docker named volumes"]
end
subgraph OrbRuntime["OrbStack"]
OrbStack --> VMs["Cloned sandbox VMs"]
OrbStack --> HostVolumes["Host volume directories<br/>orbstack.volume_host_path"]
end
subgraph AppleRuntime["Apple Container"]
AppleContainer --> AppleContainers["VM-backed containers<br/>through container-apiserver XPC"]
AppleContainer --> AppleVolumes["Apple Container named volumes"]
end
EnvdBin["envd-bin<br/>linux amd64 / arm64"] --> Docker
EnvdBin --> OrbStack
EnvdBin --> AppleContainer
Containers --> ContainerEnvd["envd inside container"]
VMs --> VMEnvd["envd systemd service"]
ContainerEnvd -. "direct envdURL" .-> SDK
VMEnvd -. "direct envdURL" .-> SDK
The gateway handles E2B-compatible control-plane APIs such as sandbox lifecycle, templates, volumes, snapshots, metrics, and logs. After a sandbox is created, SDK calls for commands, filesystem, PTY, and streaming use the sandbox-specific envdURL returned by the runtime.
Point the E2B SDK at the local gateway instead of the hosted E2B API:
export E2B_API_URL="http://127.0.0.1:3000"
export E2B_API_KEY="local"
unset E2B_SANDBOX_URLE2B_API_KEY is kept for SDK compatibility. The local gateway does not require a real hosted E2B key.
Template IDs are local runtime IDs:
- Docker runtime exposes tagged local Docker images as templates. For example,
e2b-local/code-interpreter:latestis available ascode-interpreter. - OrbStack runtime exposes existing OrbStack machines, or configured template IDs, as templates.
- Apple Container runtime exposes configured template IDs mapped to locally pulled OCI images.
- Call
ListTemplatesfrom the SDK, orGET /templates, to see the exact IDs available on the current machine.
JavaScript or TypeScript callers:
import { Sandbox, Volume } from 'e2b'
const template = 'code-interpreter'
const sandbox = await Sandbox.create(template)
try {
const result = await sandbox.commands.run('echo "hello from e2b-local"')
console.log(result.stdout)
} finally {
await sandbox.kill()
}
const volume = await Volume.create('my-data')
const withVolume = await Sandbox.create(template, {
volumeMounts: {
'/mnt/data': volume,
},
})
await withVolume.kill()Go callers can use superduck-ai/e2b-go-sdk:
package main
import (
"context"
"fmt"
e2b "github.com/superduck-ai/e2b-go-sdk"
)
func main() {
ctx := context.Background()
template := "code-interpreter"
sandbox, err := e2b.Create(ctx, template, nil)
if err != nil {
panic(err)
}
defer sandbox.Kill(ctx, nil)
result, err := sandbox.Commands.Run(ctx, `echo "hello from e2b-local"`, nil)
if err != nil {
panic(err)
}
fmt.Println(result.(*e2b.CommandResult).Stdout)
volume, err := e2b.CreateVolume(ctx, "my-data", nil)
if err != nil {
panic(err)
}
defer e2b.DestroyVolume(ctx, volume.VolumeID, nil)
withVolume, err := e2b.Create(ctx, template, &e2b.SandboxOpts{
VolumeMounts: map[string]any{
"/mnt/data": volume,
},
})
if err != nil {
panic(err)
}
defer withVolume.Kill(ctx, nil)
}Runtime notes for callers:
- Docker volumes are Docker native named volumes. The returned
volumeIDis the Docker volume name. - OrbStack volumes are directories under
orbstack.volume_host_pathand are mounted into sandbox VMs on demand. - Apple Container volumes are Apple Container native named volumes and are mounted during sandbox creation.
- The SDK receives a direct
envdURLfor each sandbox, so commands, filesystem, PTY, and streaming calls talk directly to the sandbox runtime after creation.
Implemented capabilities include:
- Gin-based HTTP server and middleware.
- Config-driven local runtime selection.
- Generated request/response DTOs, client types, and server interfaces from the E2B OpenAPI schema.
- E2B sandbox lifecycle APIs: create, list, get, kill, pause, resume, connect, and logs.
- Template, build, volume, snapshot, and metrics resource endpoints.
- Docker runtime for creating, pausing, resuming, deleting, restoring, logging, and collecting stats from real containers.
- OrbStack runtime for cloning/starting/stopping/deleting VMs through OrbStack sockets, installing
envdas a systemd service, managing volume mounts, and creating snapshots without shelling out to the OrbStack CLI. - Apple Container runtime for creating, pausing, resuming, deleting, restoring, and mounting volumes through
container-apiserverXPC without shelling out for sandbox lifecycle operations.
cmd/e2b-local: CLI entrypoint for serving the gateway and helper commands.internal/gateway: core gateway package with config, routes, store, callbacks, and runtime interfaces.internal/backends/docker: Docker runtime implementation.internal/backends/orbstack: OrbStack VM runtime implementation.internal/backends/applecontainer: Apple Container XPC runtime implementation.internal/e2bapi: generated OpenAPI client/server/DTO code.envd-bin: checked-in Linuxenvdbinaries used by Docker, OrbStack, and Apple Container.scripts: local smoke-test and helper scripts.tests/sdk_integration: optional Go/JS SDK integration tests.
Backends register themselves through RegisterSandboxRuntimeFactory, so runtime logic stays outside the HTTP router.
- Go 1.24 or newer.
- Docker, OrbStack, or Apple Container, depending on the selected runtime.
- A compatible Linux
envdbinary fromenvd-bin.
The repository tracks:
envd-bin/envd-linux-amd64envd-bin/envd-linux-arm64
Docker inspects the selected image architecture and bind-mounts the matching envd binary into each sandbox container at /usr/local/bin/envd. OrbStack copies the configured binary into each sandbox VM and installs it as /usr/local/bin/envd before starting the systemd service. Apple Container copies the configured binary into each VM-backed container with XPC copyIn unless the selected template sets prebaked_envd_path, then starts envd as a container process.
See config.example.yaml for the full local config shape. Use config.docker.yaml for a Docker-focused example, config.orb.yaml for an OrbStack-focused example, and config.applecontainer.yaml for an Apple Container example.
A compact Docker config:
server:
addr: "127.0.0.1:3000"
runtime:
type: "docker"
docker:
container_name_prefix: "e2b-envd-"
health_timeout_seconds: 30Important fields:
runtime.typesupportsdocker,orbstack, andapplecontainer.docker.hostcan be omitted. The gateway usesDOCKER_HOST, then the current user's OrbStack socket when present, thenunix:///var/run/docker.sock.- Docker templates are discovered from tagged local Docker images. The gateway never pulls images; pull, build, and tag them locally before creating sandboxes.
docker.platformis optional. Empty means Docker chooses the image platform, then the gateway inspects the selected image.docker.envd_binaryis optional. Empty means the gateway picksenvd-bin/envd-linux-amd64orenvd-bin/envd-linux-arm64from the selected image architecture. When set, it can be relative to the config file.orbstack.envd_binarycan be relative to the config file. The gateway copies it into each VM before installing the service.orbstack.volume_host_pathstores local volume directories on macOS and supports~and config-relative paths.applecontainer.envd_binarycan be relative to the config file. The gateway copies it into Apple Container sandboxes unless the selected template setsprebaked_envd_path.applecontainer.templatesmaps local template IDs to Apple Container image references. The gateway does not pull images; pull them withcontainer image pullfirst.
To run a standalone envd container for manual debugging:
scripts/start-docker-envd.shDefaults:
- image:
e2b-local/code-interpreter:latest - standalone container platform:
linux/amd64 - envd binary: selected from
envd-binbased on the helper platform - container name:
e2b-envd - external URL:
http://127.0.0.1:49984
Useful overrides:
E2B_ENVD_HOST_PORT=49985 \
E2B_ENVD_CONTAINER=e2b-envd-2 \
scripts/start-docker-envd.shUse Docker runtime when you want the gateway to create one container per sandbox:
runtime:
type: "docker"In Docker runtime:
POST /sandboxescreates a container.DELETE /sandboxes/{sandboxID}removes the container.pauseandconnectmap to Docker pause/unpause.- envd listens on container port
49983; Docker publishes a separate localhost host port for each sandbox automatically. - Templates are resolved from local tagged Docker images, or from a full image reference passed as
templateID. The image must already exist locally. - The gateway stores non-sensitive runtime metadata in
e2b.local.*container labels and restores running/paused sandboxes after process restart. - The selected envd binary is mounted at
/usr/local/bin/envd. - Requested E2B volumes use Docker native named volumes.
- Sandbox responses return the direct runtime
envdURLassigned by Docker.
Example sandbox request:
{
"templateID": "code-interpreter",
"volumeMounts": [
{
"name": "my-data",
"path": "/mnt/data"
}
]
}Use OrbStack runtime when each sandbox should run inside a full Linux VM:
runtime:
type: "orbstack"
orbstack:
machine_name_prefix: "e2b-sandbox-"
envd_binary: "envd-bin/envd-linux-arm64"
envd_port: 49983
volume_host_path: "~/.e2b-local/volumes"In OrbStack runtime:
- Existing OrbStack machines whose names do not start with
machine_name_prefixare exposed as templates. - Sandbox creation clones the selected template machine.
- The gateway copies
envd_binaryinto the VM and installs/usr/local/bin/envd. - envd runs as a systemd service inside the VM.
- Sandbox envd URLs prefer the VM IP and fixed
envd_port. orbstack.isolated: trueprevents sandbox VMs from seeing the full macOS filesystem.- Volumes are exposed through OrbStack selective mounts and symlinked to the requested paths inside the VM.
- Snapshots are created by cloning the VM through OrbStack's socket RPC.
Use Apple Container runtime on Apple Silicon macOS when each sandbox should run as an Apple Container VM-backed container:
runtime:
type: "applecontainer"
applecontainer:
container_name_prefix: "e2b-sandbox-"
envd_binary: "envd-bin/envd-linux-arm64"
envd_port: 49983
templates:
debian-bookworm-slim:
image: "docker.io/library/debian:bookworm-slim"
# Set this when envd is already baked into the image.
# prebaked_envd_path: "/usr/local/bin/envd"System prerequisites:
export CGO_ENABLED=1
brew install container
brew services start container
container system status
container system kernel set --recommended
container image pull --platform linux/arm64 docker.io/library/debian:bookworm-slimNotes:
- The Apple Container backend requires macOS with cgo enabled because the native XPC bridge is compiled through cgo.
- Apple Container must report
status running; the backend talks tocom.apple.container.apiserverandcom.apple.container.core.container-core-imagesdirectly through XPC. - A default kernel is required. If
container runreportsdefault kernel not configured, runcontainer system kernel set --recommended. - Template images must already be pulled with Apple Container. Lifecycle-only smoke tests can use small images such as Alpine, but E2B SDK command execution needs an image with
/bin/bash;debian:bookworm-slimworks. - envd is copied from
applecontainer.envd_binaryunless the selected template setsprebaked_envd_path. - envd is exposed with an explicit published localhost port because Apple Container does not allocate
hostPort: 0; the runtime retries with a fresh port when Apple Container reports a port conflict. pausemaps to Apple Container stop, andresumebootstraps the existing container and reuses the persisted published port.- Volumes use Apple Container named volumes and are mounted with the requested
VolumeMountsduring sandbox creation.
Capability matrix:
| Capability | Apple Container backend |
|---|---|
| Create/pause/resume/delete/restore | Supported |
| Commands, filesystem, PTY, Git | Supported through direct envdURL |
| Volume create/list/get/delete | Supported with Apple Container named volumes |
| Volume mounts | Supported at sandbox creation |
| Snapshots | Not supported |
| Runtime network updates | Not supported |
Run regular tests:
go test ./...Optional JS SDK integration test:
go test -tags=js_sdk_integration -run TestJSSDKGatewaySmoke -count=1 -vOptional Go SDK integration tests:
go test -tags=go_sdk_integration -run 'TestGoSDKGatewayMVP|TestGoSDKGatewayFilesystemDirectEnvd|TestGoSDKGatewayVolumeLifecycle' -count=1 -vOptional Apple Container integration tests:
go test -tags=integration ./internal/backends/applecontainer/... -count=1 -v
go test -tags=go_sdk_integration ./tests/sdk_integration -run TestGoSDKGatewayAppleContainerDirectEnvd -count=1 -vMost SDK integration tests read config.yaml through LoadConfig("config.yaml") and skip when Docker, envd, Node, or SDK dependencies are unavailable. TestGoSDKGatewayAppleContainerDirectEnvd builds its own Apple Container config and skips unless container-apiserver, the configured envd binary, and the template image are available.
- �pplecontainer backend requires macOS 13+ and the container-apiserver binary; on other platforms use the docker or orbstack backend.
- SDK integration tests are skipped automatically when Docker or envd is unavailable (see config.yaml loading in the test suite).
- The gateway exposes an unauthenticated control endpoint on the local loopback interface; do not bind it to public addresses.