Skip to content

HACKE-RC/Bandsox

Repository files navigation

BandSox

BandSox logo

Python library and CLI for managing Firecracker microVMs. Create, snapshot, and restore sandboxes from Docker images. Runs untrusted code or isolates workloads.

Features

  • Millisecond boot times via Firecracker
  • Create VMs from Docker images
  • Pause, resume, and snapshot VMs for instant restore
  • Web dashboard with login, API key management, and terminal sessions
  • CLI for all operations, including auth management
  • Python API for scripting and integration
  • TypeScript SDK for Node.js
  • Optional authentication: API keys for programmatic access, session cookies for the dashboard. Off by default.

Usage

Quick start

Create a VM and run Python code:

from bandsox.core import BandSox

bs = BandSox()
vm = bs.create_vm("python:3-alpine", enable_networking=False)

result = vm.exec_python_capture("print('Hello from VM!')")
print(result['stdout'])  # Hello from VM!

vm.stop()

Python API

from bandsox.core import BandSox

bs = BandSox()

# Create a VM from a Docker image (needs python preinstalled)
vm = bs.create_vm("python:3-alpine", name="test-vm")
print(f"VM started: {vm.vm_id}")

# Run a command
exit_code = vm.exec_command("echo Hello World > /root/hello.txt")

# Run Python code directly inside the VM
result = vm.exec_python_capture("print('Hello World')")
print(result['stdout'])  # Hello World

# Read a file
content = vm.get_file_contents("/root/hello.txt")
print(content)  # Hello World

vm.stop()

Run Claude Code

import os
from bandsox.core import BandSox

bs = BandSox()
vm = bs.create_vm(
    "ghcr.io/bandsox/claude-code:latest",
    env_vars={"ANTHROPIC_API_KEY": os.environ["ANTHROPIC_API_KEY"]},
    # Optional: wire MCP servers (resolved from built-in registry)
    mcp={"github": {"token": os.environ.get("GITHUB_TOKEN", "")}},
)

vm.exec_command(
    "claude --dangerously-skip-permissions -p 'Add a README section about performance'",
    timeout=300,
)
vm.stop()

docs/CLAUDE_CODE.md covers headless prompts, working with a cloned repo inside the VM, and the pause/snapshot/resume pattern for long-running Claude Code sessions. docs/MCP_REGISTRY.md lists the built-in MCP servers and how to add new ones.

Remote server usage

If the BandSox server is already running somewhere, point the Python client at it:

from bandsox.core import BandSox

# With authentication
bs = BandSox("http://localhost:8000", headers={"Authorization": "Bearer bsx_your_key_here"})
vm = bs.create_vm("python:3-alpine", enable_networking=False)

result = vm.exec_python_capture("print('Hello from the server')")
print(result["stdout"])

vm.stop()

Web dashboard

Start the server:

bandsox serve --host 0.0.0.0 --port 8000

Visit http://localhost:8000 to access the dashboard. Authentication is off by default -- see docs/AUTHENTICATION.md to enable it.

Authentication

Auth is off by default. Turn it on with bandsox auth init --storage /var/lib/sandbox. See docs/AUTHENTICATION.md for the full setup, CLI commands, SDK examples, and endpoint reference.

CLI

BandSox includes a CLI tool bandsox (or python -m bandsox.cli).

# Create a VM
bandsox create ubuntu:latest --name my-vm

# Open a terminal
bandsox terminal <vm_id>

# Start the server
bandsox serve --host 0.0.0.0 --port 8000

Prerequisites

  • Linux with KVM support (bare metal or nested virtualization)
  • Firecracker installed at /usr/bin/firecracker
  • Python 3.8+
  • sudo for TAP/NAT setup when networking is enabled (BandSox prompts as needed)
  • Vsock kernel module (virtio-vsock) in the guest kernel for fast file transfers (optional, falls back to serial)

Installation

From PyPI

# Using pip
pip install bandsox

# Using uv
uv pip install bandsox

Then initialize the required artifacts:

bandsox init --rootfs-url ./bandsox-base.ext4

From source

  1. Clone the repo:

    git clone https://github.com/HACKE-RC/Bandsox.git
    cd bandsox
  2. Install:

    pip install -e .
  3. Initialize artifacts (kernel, CNI plugins, optional base rootfs):

    bandsox init --rootfs-url ./bandsox-base.ext4

    This downloads:

    • vmlinux (Firecracker kernel)
    • CNI plugins into cni/bin/
    • (Optional) a base rootfs .ext4 into storage/images/ when --rootfs-url is provided

    Default URLs are provided for kernel and CNI. For the rootfs, build one locally (instructions below) and point --rootfs-url to a local path or file:// URL. Use --skip-* flags to omit specific downloads or --force to re-download.

Architecture

BandSox has four main modules:

  • bandsox.core -- manages VMs, snapshots, and CID/port allocation.
  • bandsox.vm -- wraps the Firecracker process; handles config, networking, vsock bridge, and guest interaction.
  • bandsox/agent -- Go guest agent (bandsox-agent) baked into VM images; runs commands and file I/O over serial and vsock.
  • bandsox.server -- FastAPI backend for the web dashboard and REST API, with built-in authentication.
  • bandsox.auth -- optional authentication. When auth.json exists, enforces API key and session auth. Stores hashed keys and a signing secret. Sessions are HMAC-signed tokens (no server-side state). Rate-limits login attempts.

Storage layout

Default: /var/lib/bandsox (override with BANDSOX_STORAGE env var)

├── images/               # Rootfs ext4 images
├── snapshots/            # VM snapshots
├── sockets/              # Firecracker API sockets
├── metadata/             # VM metadata (including vsock_config)
├── auth.json             # API key hashes, admin password hash, session signing secret
├── cid_allocator.json    # CID allocation state
└── port_allocator.json   # Port allocation state

Docs and API reference

Building a local base rootfs

Build a minimal ext4 from a Docker image:

IMG=alpine:latest          # pick a base image with python if needed
OUT=bandsox-base.ext4
SIZE_MB=512                # increase for more disk
TMP=$(mktemp -d)

docker pull "$IMG"
CID=$(docker create "$IMG")
docker export "$CID" -o "$TMP/rootfs.tar"
docker rm "$CID"

dd if=/dev/zero of="$OUT" bs=1M count=$SIZE_MB
mkfs.ext4 -F "$OUT"
mkdir -p "$TMP/mnt"
sudo mount -o loop "$OUT" "$TMP/mnt"
sudo tar -xf "$TMP/rootfs.tar" -C "$TMP/mnt"

cat <<'EOF' | sudo tee "$TMP/mnt/init" >/dev/null
#!/bin/sh
export PATH=/usr/local/bin:/usr/bin:/bin:/sbin
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mkdir -p /dev/pts
mount -t devpts devpts /dev/pts
exec /usr/local/bin/bandsox-agent 2>&1
EOF
sudo chmod +x "$TMP/mnt/init"

# Build the Go agent if needed (requires Go toolchain)
(cd bandsox/agent && go build -ldflags='-s -w' -o agent .)
sudo mkdir -p "$TMP/mnt/usr/local/bin"
sudo cp bandsox/agent/agent "$TMP/mnt/usr/local/bin/bandsox-agent"
sudo chmod 755 "$TMP/mnt/usr/local/bin/bandsox-agent"

sudo umount "$TMP/mnt"
sudo e2fsck -fy "$OUT"
sudo resize2fs -M "$OUT"   # optional: shrink to minimum
rm -rf "$TMP"

Use it with bandsox init --rootfs-url ./bandsox-base.ext4.

You can also skip the base rootfs entirely -- BandSox builds per-image rootfs on demand from Docker images when you call bandsox create <image>.

License

Apache License 2.0

Note: This project wasn't supposed to be made public so it may have artifacts which make no sense. Please open issues so I can remove them.

About

Sanboxes for AI agents and humans

Topics

Resources

License

Contributing

Stars

74 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors