Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ node_modules
/logs
.next
next-env.d.ts
.idea/
14 changes: 14 additions & 0 deletions examples/tpl-sbx-world-py/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# E2B API key (required)
E2B_API_KEY=your_api_key_here

# Private deployment configuration (optional)
# E2B_DOMAIN=your.domain.tld:port
# E2B_CUSTOM_IP= # If custom DNS mapping is needed
# NODE_TLS_REJECT_UNAUTHORIZED=0 # Disable TLS certificate verification

# Sandbox configuration (optional)
# SANDBOX_MINUTES=10
# SANDBOX_MODE=code # Sandbox mode: code (Code Interpreter) or base (Base Image)

# Image registry configuration (optional)
# E2B_IMAGE_REGISTRY=
254 changes: 254 additions & 0 deletions examples/tpl-sbx-world-py/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
# E2B Sandbox Template (Python)

This is a Python implementation of an E2B sandbox template that allows you to run code in a controlled environment.

## Prerequisites

Before you begin, make sure you have:

* An E2B account (sign up at [e2b.dev](https://e2b.dev))
* An E2B API key (available from the [E2B Console](https://e2b.dev/dashboard))
* Python 3.8+ and pip

## Configuration

1. Copy `.env.example` and fill in the values:

```bash
cp .env.example .env
# Edit the .env file to set E2B_API_KEY, E2B_DOMAIN, etc.
```

The script automatically loads the `.env` file via `python-dotenv`.

### Private Deployment

For private/self-hosted E2B deployments, configure the following environment variables:

```bash
# Authentication
E2B_API_KEY=your_api_key_here

# Domain (including port number)
E2B_DOMAIN=your.domain.tld:port

# Custom DNS resolution (optional)
# Use this if the domain needs to resolve to a specific IP address
E2B_CUSTOM_IP=192.168.123.84
```

You may export variables in the shell, but using a `.env` file is recommended.

**SSL Certificate Notes**:

* The script automatically detects private deployments (via the `E2B_DOMAIN` variable)
* SSL certificate verification is automatically disabled for private deployments
* If custom DNS resolution is needed, set the `E2B_CUSTOM_IP` variable
* For production environments, using valid SSL certificates is recommended

## Install Dependencies

```bash
pip install -r requirements.txt
```

## Build the Template

```bash
# 1. Build (requires alias)
python build_template.py --alias=<template_alias>

# 2. Specify mode (optional, default is 'code')
python build_template.py --alias=my-base-template --mode=base

# 3. Specify image registry (optional)
python build_template.py --alias=my-template --registry=hub.registry.com

# 4. Read configuration from environment variables (set them in the .env file)
# SANDBOX_MODE=base
# E2B_IMAGE_REGISTRY=hub.registry.com
python build_template.py --alias=my-template
```

## Use the Template in a Sandbox

After the template is built, you can use it inside an E2B sandbox:

```python
from e2b import Sandbox

# Create a new sandbox instance
sandbox = Sandbox.create('my-template')

# Sandbox is ready!
print('Sandbox created successfully')
```

## CLI Commands

### Create / Connect

```bash
# Create a new sandbox from an alias (alias required)
python operate_sandbox.py --alias=<template_alias>

# Connect to an existing sandbox
python operate_sandbox.py --connect --id=<sandboxID>

# Enter interactive shell (session persists until exit)
python operate_sandbox.py --connect --id=<sandboxID> --shell
python operate_sandbox.py --alias=<template_alias> --shell

# Upload a file and enter shell (file will appear in /home/user/)
python operate_sandbox.py --alias=<template_alias> --upload example_code.py --shell

# Upload multiple files and enter shell
python operate_sandbox.py --alias=<template_alias> --upload file1.py file2.py script.sh --shell

# Optional runtime duration (minutes)
python operate_sandbox.py --alias=<template_alias> --minutes=10
```

Notes:

* Both building and creating sandboxes require specifying an alias.
* You can optionally set TTL using `--minutes`; for shell mode, it’s optional.
* Using `--upload` uploads files to `/home/user/` immediately after sandbox creation.

### List / Info / Kill / Pause / Resume

```bash
# List sandboxes (ID, STATE, NAME, START AT, END AT)
python operate_sandbox.py --list

# Show sandbox details
python operate_sandbox.py --info --id=<sandboxID>

# Kill sandbox
python operate_sandbox.py --kill --id=<sandboxID>

# Pause sandbox
python operate_sandbox.py --pause --id=<sandboxID>

# Resume sandbox
python operate_sandbox.py --resume --id=<sandboxID>
```

### Code Execution

You can execute Python code, shell commands, or local Python files directly inside a sandbox:

```bash
# Execute Python code (create new sandbox)
python operate_sandbox.py --alias=<template_alias> --code='print("Hello from E2B!")'

# Execute Python code (connect to existing sandbox)
python operate_sandbox.py --connect --id=<sandboxID> --code='import sys; print(sys.version)'

# Execute a local Python file (recommended for multi-line code)
python operate_sandbox.py --alias=<template_alias> --file=your_script.py

# Execute a local Python file (connect to existing sandbox)
python operate_sandbox.py --connect --id=<sandboxID> --file=your_script.py

# Execute shell command (create new sandbox)
python operate_sandbox.py --alias=<template_alias> --command='ls -la'

# Execute shell command (connect to existing sandbox)
python operate_sandbox.py --connect --id=<sandboxID> --command='pwd && whoami'
```

Notes:

* `--code` runs Python code via `python3 -c`
* `--file` uploads and runs a local Python file from `/tmp/`
* `--command` runs a shell command
* Exit code, stdout, and stderr are displayed after execution
* The script exits using the executed program’s exit code

#### Multi-line Python Code Example

For complex multi-line code, use the `--file` parameter:

1. Create a Python file (e.g., `my_script.py`):

```python
import math

def fibonacci(n):
if n <= 1:
return n
a, b = 0, 1
for _ in range(n - 1):
a, b = b, a + b
return b

result = [fibonacci(i) for i in range(10)]
print(f"Fibonacci sequence: {result}")

radius = 5
area = math.pi * radius ** 2
print(f"Area of a circle with radius {radius}: {area:.2f}")
```

2. Run the file:

```bash
python operate_sandbox.py --alias=<template_alias> --file=my_script.py
```

### Template Management

```bash
# List templates (ID, ALIASES, STATUS, BUILDS, CREATED/UPDATED/LAST USED)
python operate_sandbox.py --list-templates

# Delete template by ID
python operate_sandbox.py --delete-template --id=<templateID>

# Delete template by alias (automatically resolves to ID)
python operate_sandbox.py --delete-template --alias=<alias>
```

## Template Structure

* `template.py` — Defines sandbox template configuration
* `build_template.py` — Builds the template
* `operate_sandbox.py` — CLI script for create/connect/shell/list/info/kill/pause/resume

## Purpose

This repository demonstrates how to work with sandboxes using the E2B Python SDK on private deployments or the official E2B platform. It focuses on:

* Building templates using user-provided aliases
* Creating and connecting to sandboxes
* Launching interactive shells
* Listing, inspecting, pausing, resuming, and killing sandboxes

For private deployments, ensure environment variables such as `E2B_DOMAIN` are set correctly.
For the official E2B SaaS, only `E2B_API_KEY` is required.

## Next Steps

1. Customize the template in `template.py`
2. Build the template using one of the methods above
3. Use the template in your E2B sandbox code
4. Check out the [E2B documentation](https://e2b.dev/docs) for advanced usage
5. For private deployments, ensure `E2B_DOMAIN` is configured and certificates are trusted

## Differences from the JavaScript Version

This Python implementation provides the same functionality as the JavaScript version:

* Template definition and building
* Sandbox creation and management
* Interactive shell support
* Full CLI operations

Main differences:

* Uses Python’s `argparse` instead of manual CLI parsing
* Uses `termios` and `tty` for terminal control
* Loads environment variables via `python-dotenv`
* Python-style naming conventions (snake_case)

100 changes: 100 additions & 0 deletions examples/tpl-sbx-world-py/build_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import os
import sys
from pathlib import Path
from dotenv import load_dotenv

# Load environment variables first
env_path = Path.cwd() / '.env'
load_dotenv(dotenv_path=env_path, override=True)

# For private deployments, apply necessary patches before importing e2b
if os.getenv('E2B_DOMAIN'):
import ssl
import socket
import httpcore._backends.sync

# Create SSL context function that doesn't verify certificates
def create_unverified_context(*args, **kwargs):
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
return context

# Globally replace SSL context creation
ssl._create_default_https_context = create_unverified_context
ssl._create_unverified_context = create_unverified_context
ssl.create_default_context = create_unverified_context

# DNS patch (optional, if you need to resolve domain to specific IP)
custom_ip = os.getenv('E2B_CUSTOM_IP')
if custom_ip:
original_gai = socket.getaddrinfo
def patched_getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
domain = os.getenv('E2B_DOMAIN', '').split(':')[0]
if isinstance(host, (str, bytes)) and domain in (host if isinstance(host, str) else host.decode()):
return [(socket.AF_INET, socket.SOCK_STREAM, 6, "", (custom_ip, port))]
return original_gai(host, port, family, type, proto, flags)
socket.getaddrinfo = patched_getaddrinfo

# TLS patch for httpcore
_original_start_tls = httpcore._backends.sync.SyncStream.start_tls
def patched_start_tls(self, ssl_context, server_hostname=None, timeout=None):
return _original_start_tls(self, create_unverified_context(), server_hostname, timeout)
httpcore._backends.sync.SyncStream.start_tls = patched_start_tls

import argparse
from e2b import Template, default_build_logger
from template import create_template

# Disable SSL warnings
if os.getenv('E2B_DOMAIN'):
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)


def get_args():
"""Parse command line arguments"""
parser = argparse.ArgumentParser(description='Build E2B template')
parser.add_argument('--alias', required=True, help='Template alias (required)')
parser.add_argument(
'--mode',
choices=['code', 'base'],
default=None,
help='Sandbox mode: code (Code Interpreter) or base (base image). Priority: CLI args > env SANDBOX_MODE > default "code"'
)
parser.add_argument(
'--registry',
default=None,
help='Image registry prefix. Priority: CLI args > env E2B_IMAGE_REGISTRY'
)
return parser.parse_args()


def main():
args = get_args()

# Parameter priority: CLI args > environment variables > default values
mode = args.mode or os.getenv('SANDBOX_MODE') or 'code'
registry = args.registry or os.getenv('E2B_IMAGE_REGISTRY') or None

# Create template
template = create_template(mode=mode, registry=registry)

# Build template
Template.build(
template,
alias=args.alias,
cpu_count=1,
memory_mb=1024,
on_build_logs=default_build_logger(),
)

print(f'✅ Template built successfully: alias={args.alias}, mode={mode}, registry={registry or "default"}')


if __name__ == '__main__':
try:
main()
except Exception as err:
print(f'Error: {err}', file=sys.stderr)
sys.exit(1)
Loading