An open API service indexing awesome lists of open source software.

https://github.com/contember/edvabe

Local E2B-compatible sandbox runtime — a single Go binary that exposes an E2B-compatible API on localhost, backed by Docker containers
https://github.com/contember/edvabe

Last synced: about 5 hours ago
JSON representation

Local E2B-compatible sandbox runtime — a single Go binary that exposes an E2B-compatible API on localhost, backed by Docker containers

Awesome Lists containing this project

README

          

# edvabe

Local [E2B](https://e2b.dev)-compatible sandbox runtime. A single Go
binary that exposes a wire-compatible subset of the E2B cloud sandbox
API on a developer's laptop: point an unmodified E2B SDK at it via env
vars and sandboxes run in local Docker containers instead of E2B's
cloud.

## Features

- **Drop-in compatible** with unmodified E2B Python and TypeScript SDKs
- **Single binary** — no Redis, Postgres, Nomad, or Firecracker
- **Cross-platform** — Linux and macOS (x86_64 + arm64)
- **Sandbox lifecycle** — create, kill, pause, resume, snapshots
- **Custom templates** — programmatic `Template.build()` from the SDK
- **Code interpreter** — `@e2b/code-interpreter` SDK works out of the box
- **Full API surface** — teams, volumes, api-keys stubs so the SDK never crashes

## Quick start

### Option A: Go install

```sh
go install github.com/contember/edvabe/cmd/edvabe@latest

edvabe doctor # preflight check
edvabe build-image # first-time: build edvabe/base:latest (~60s)
edvabe serve # listens on :3000
```

### Option B: Docker (recommended for docker-compose setups)

```sh
docker run --rm \
-p 3000:3000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v edvabe-data:/data \
ghcr.io/contember/edvabe:main serve
```

### Docker Compose

```yaml
services:
edvabe:
image: ghcr.io/contember/edvabe:main
ports:
- "3000:3000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- edvabe-data:/data
environment:
EDVABE_STATE_DIR: /data
EDVABE_CACHE_DIR: /data/cache

volumes:
edvabe-data:
```

The Docker socket mount is required — edvabe creates sandbox containers
as siblings on the host Docker daemon.

## Point an SDK at it

Set these env vars in the process running your E2B SDK code:

```sh
export E2B_API_URL=http://localhost:3000
export E2B_DOMAIN=localhost:3000
export E2B_API_KEY=edvabe_local
export E2B_SANDBOX_URL=http://localhost:3000
```

When running inside docker-compose, replace `localhost:3000` with
`edvabe:3000` (the service name).

Then unmodified SDK code works:

```python
from e2b import Sandbox

sbx = Sandbox.create(timeout=60)
result = sbx.commands.run("echo hello from edvabe")
print(result.stdout) # "hello from edvabe\n"
sbx.kill()
```

### Code interpreter

```sh
edvabe build-image --template=code-interpreter # ~10 min first time
```

```python
from e2b_code_interpreter import Sandbox

sbx = Sandbox()
execution = sbx.run_code("1 + 1")
print(execution.results[0].text) # "2"
sbx.kill()
```

### Custom templates

The SDK's programmatic `Template.build()` works against edvabe — it
translates step arrays into Dockerfiles and builds them locally:

```typescript
import { Template, Sandbox } from 'e2b'

const tpl = Template()
.fromImage('oven/bun:slim')
.aptInstall(['curl', 'git'])
.runCmd('echo "built" > /etc/marker')

await Template.build(tpl, { alias: 'my-template' })
const sbx = await Sandbox.create('my-template')
```

## Commands

```sh
edvabe serve [--port 3000] # start server
edvabe doctor [--port 3000] # preflight checks
edvabe build-image [--template=base|code-interpreter|all] # build images
edvabe pull-base # pull upstream e2bdev/base
edvabe version # print version
```

## Environment variables

| Variable | Default | Description |
|---|---|---|
| `EDVABE_STATE_DIR` | `~/.local/share/edvabe` | Template store (templates.json) |
| `EDVABE_CACHE_DIR` | `~/.cache/edvabe/template-files` | File context cache |
| `EDVABE_BUILD_DIR` | `~/.cache/edvabe/builds` | Build scratch directory |
| `DOCKER_HOST` | auto-detected | Docker socket path |

## Test

```sh
make test # go test ./...
make test-e2e-python # Python SDK E2E (create, commands, files, pty, watch)
make test-e2e-ts # TypeScript SDK E2E
make test-e2e-code-interpreter-python # code interpreter Python E2E
make test-e2e-code-interpreter-ts # code interpreter TypeScript E2E
```

## Architecture

edvabe implements the E2B **control plane** in Go — sandbox CRUD,
template builds, pause/resume, and all the stub endpoints the SDK
expects. The **data plane** (filesystem, process, PTY, watchers) is
handled by upstream [envd](https://github.com/e2b-dev/infra/tree/main/packages/envd)
running inside each sandbox container. edvabe reverse-proxies SDK
requests to envd, giving byte-exact wire compatibility without
reimplementing the ~6000 LOC envd protocol.

```
SDK ──HTTP──> edvabe (:3000)

├─ control plane (Go)
│ sandboxes, templates, teams, volumes, ...

└─ reverse proxy ──> Docker container
│ │
│ ├─ envd (:49983)
│ │ files, process, PTY, watch
│ │
│ └─ code-interpreter (:49999)
│ Jupyter + FastAPI overlay

└─ routed by E2b-Sandbox-Id + E2b-Sandbox-Port headers
```

**Key design decisions:**

- **Templates are Docker images.** `Template.build()` translates SDK
step arrays into generated Dockerfiles and runs `docker build`.
- **envd is injected** into every user template via a `COPY --from`
stage — user images don't need to know about envd.
- **Pause = `docker pause`**, snapshot = `docker commit`. No live
memory snapshots. Documented trade-off for a local dev tool.
- **Runtime and Agent are pluggable interfaces** behind
`internal/runtime/` and `internal/agent/`. Docker is the v1 backend;
Firecracker/libkrun could slot in later.

See [docs/05-architecture.md](docs/05-architecture.md) for the full
design and [docs/03-api-surface.md](docs/03-api-surface.md) for the
wire protocol.

## License

[MIT](LICENSE) — Contember Limited