quartermaster-code-runner
Secure sandboxed code execution service. Runs untrusted code in isolated Docker containers with support for Python, Node.js, Go, Rust, Deno, and Bun.
Features
- 6 Runtimes: Python, Node.js, Go, Rust, Deno, Bun
- Docker Isolation: Each execution runs in its own container with read-only filesystem
- Resource Limits: Configurable CPU, memory, and disk quotas per execution
- Network Control: Outbound network access toggled per request
- Timeout Enforcement: Hard container kill after configurable duration
- File Injection: Send multiple source files alongside the main code
- Prebuilt Images: Extend base runtimes with custom dependencies
- Auto Cleanup: Orphaned containers and old images cleaned up automatically
- API Key Auth: Optional authentication via
X-API-Keyheader or Bearer token - Health Checks: Built-in
/healthendpoint with Docker connectivity status - Standalone: No dependency on other Quartermaster packages
Supported Runtimes
| Runtime | Image Name | Sandbox |
|---|---|---|
| Python | python |
Alpine Linux |
| Node.js | node |
Alpine Linux |
| Go | go |
Alpine Linux |
| Rust | rust |
Alpine Linux |
| Deno | deno |
Alpine Linux |
| Bun | bun |
Alpine Linux |
Installation
As a Service (recommended)
pip install quartermaster-code-runner
uvicorn quartermaster_code_runner.app:app --host 0.0.0.0 --port 8000
Requires Docker to be running and accessible.
Docker Compose
services:
code-runner:
build: .
ports:
- "8000:8000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- LOG_LEVEL=info
- DEFAULT_TIMEOUT=30
- DEFAULT_MEMORY=256m
Quick Start
Execute Python Code
curl -X POST http://localhost:8000/run \
-H "Content-Type: application/json" \
-d '{
"code": "print(sum(range(1, 101)))",
"image": "python"
}'
Response:
{
"stdout": "5050\n",
"stderr": "",
"exit_code": 0,
"execution_time": 0.3421
}
Execute Node.js Code
curl -X POST http://localhost:8000/run \
-H "Content-Type: application/json" \
-d '{
"code": "console.log(Array.from({length: 5}, (_, i) => i * i))",
"image": "node"
}'
With Environment Variables and Resource Limits
curl -X POST http://localhost:8000/run \
-H "Content-Type: application/json" \
-d '{
"code": "import os; print(os.environ[\"API_KEY\"])",
"image": "python",
"timeout": 10,
"mem_limit": "128m",
"cpu_shares": 256,
"allow_network": false,
"environment": {
"API_KEY": "secret-123"
}
}'
With Additional Files
curl -X POST http://localhost:8000/run \
-H "Content-Type: application/json" \
-d '{
"code": "from helpers import greet; print(greet(\"world\"))",
"image": "python",
"files": {
"helpers.py": "def greet(name): return f\"Hello, {name}!\""
}
}'
Python Client Usage
from quartermaster_code_runner import CodeExecutionRequest
request = CodeExecutionRequest(
code="print('Hello from the sandbox')",
image="python",
timeout=10,
mem_limit="128m",
allow_network=False,
)
API Reference
POST /run
Execute code in a sandboxed Docker container.
Request body (CodeExecutionRequest):
| Field | Type | Default | Description |
|---|---|---|---|
code |
string |
required | Source code to execute |
image |
string |
"python" |
Runtime: python, node, go, rust, deno, bun |
files |
dict[str, str] |
null |
Additional files {filename: content} |
entrypoint |
string |
null |
Custom entrypoint command |
timeout |
int |
null (uses server default) |
Execution timeout in seconds |
mem_limit |
string |
null (uses server default) |
Memory limit, e.g. "256m" |
cpu_shares |
int |
null (uses server default) |
Docker CPU shares |
disk_limit |
string |
null (uses server default) |
Disk limit for tmpfs |
allow_network |
bool |
true |
Allow outbound network access |
environment |
dict[str, str] |
null |
Environment variables to inject |
prebuild_spec |
object |
null |
Prebuild spec: {base_image, setup_script} |
Response (CodeExecutionResponse):
| Field | Type | Description |
|---|---|---|
stdout |
string |
Standard output |
stderr |
string |
Standard error |
exit_code |
int |
Process exit code |
execution_time |
float |
Wall-clock time in seconds |
metadata |
dict |
Optional metadata from the container |
GET /health
Returns service health and Docker connectivity.
{
"status": "ok",
"docker_connected": true,
"auth_enabled": false
}
GET /runtimes
List available runtime images with metadata (alias for /images).
{
"images": [
{
"id": "code-runner-python",
"name": "Python",
"description": "Python runtime",
"default_entrypoint": "python main.py",
"file_extension": ".py",
"main_file": "main.py"
}
],
"default": "code-runner-python"
}
POST /prebuild
Build a prebuilt image extending a base runtime with custom dependencies.
curl -X POST http://localhost:8000/prebuild \
-H "Content-Type: application/json" \
-d '{
"tag": "my-scipy",
"base_image": "python",
"setup_script": "pip install scipy numpy"
}'
GET /prebuilds
List all prebuilt images. DELETE /prebuilds/{tag} removes one.
Security Model
Each execution is isolated with multiple layers:
- Container isolation -- separate Docker container per execution
- Read-only filesystem -- containers run with
read_only=True; writes go to tmpfs - Network control -- outbound access disabled when
allow_network=false - Resource limits -- CPU shares, memory limit, disk quota enforced by Docker
- Timeout enforcement -- containers killed after the configured timeout
- Input validation -- code size capped at 1 MB; reserved env vars blocked; path traversal rejected
Reserved environment variables (ENCODED_CODE, ENCODED_FILES, CUSTOM_ENTRYPOINT) cannot be overridden by callers.
Configuration
All settings load from environment variables with sensible defaults. Use a .env file or set them directly.
Environment Variables
| Variable | Default | Description |
|---|---|---|
HOST |
0.0.0.0 |
Bind address |
PORT |
8000 |
Bind port |
LOG_LEVEL |
info |
Log level (debug, info, warning, error) |
DEFAULT_TIMEOUT |
30 |
Default execution timeout (seconds) |
MAX_TIMEOUT |
300 |
Hard maximum timeout (seconds) |
DEFAULT_MEMORY |
256m |
Default memory limit |
MAX_MEMORY_MB |
2048 |
Maximum memory (MB) |
DEFAULT_CPU_SHARES |
512 |
Default Docker CPU shares |
MAX_CPU_CORES |
4.0 |
Maximum CPU cores |
DEFAULT_DISK |
512m |
Default tmpfs disk limit |
MAX_DISK_MB |
5000 |
Maximum disk (MB) |
DOCKER_SOCKET |
/var/run/docker.sock |
Docker socket path |
AUTH_TOKEN |
(none) | Bearer token for authentication |
CODE_RUNNER_API_KEYS |
(none) | Comma-separated API keys for X-API-Key header |
CLEANUP_INTERVAL_HOURS |
24 |
Hours between automatic prebuild cleanup |
CLEANUP_MAX_AGE_DAYS |
7 |
Max age (days) for prebuilt images before cleanup |
RUNTIME_DIR |
(auto) | Path to runtime Dockerfile directories |
When neither AUTH_TOKEN nor CODE_RUNNER_API_KEYS is set, authentication is disabled.
Error Types
from quartermaster_code_runner import (
CodeRunnerError, # Base exception
DockerError, # Docker communication failure
ExecutionError, # Code execution failure
InvalidLanguageError, # Unsupported runtime
ResourceExhaustedError, # Resource limit exceeded
RuntimeNotAvailableError, # Runtime image not found
TimeoutError, # Execution timeout
)
Contributing
Contributions welcome. See CONTRIBUTING.md for guidelines.
License
Apache License 2.0. See LICENSE for details.
Metadata
Release files for quartermaster-code-runner 0.9.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| quartermaster_code_runner-0.9.1.tar.gz | 81.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| quartermaster_code_runner-0.9.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 129.2 kB
Release files / quartermaster_code_runner-0.9.1.tar.gz
| Download URL | quartermaster_code_runner-0.9.1.tar.gz |
|---|---|
| Size | 81.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
102a910ffe06addcf3ea6295e67881ca217883df3422f4dea8d100d3807e88bf
|
|
BLAKE2b-256 checksum How to use checksums |
372d1083cbab9b71434a2c9cdddef71ac9c251eb06bf69f26c7e4ef25747b09f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.15
|
Release files / quartermaster_code_runner-0.9.1-py3-none-any.whl
| Download URL | quartermaster_code_runner-0.9.1-py3-none-any.whl |
|---|---|
| Size | 47.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b54963afda2542397ef1e00236080457c6546a67f66546730af5be3a96f56eae
|
|
BLAKE2b-256 checksum How to use checksums |
7406432a565e2f2b6c3145c1a65ad98c844d14e41524f494f32280342acf1f1d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.15
|