Skip to content

Latest commit

 

History

History
835 lines (661 loc) · 22.5 KB

File metadata and controls

835 lines (661 loc) · 22.5 KB
title FAQ
description Frequently asked questions and troubleshooting guide for BoxLite.
icon circle-question

Frequently asked questions and common issues with BoxLite.

General Questions

BoxLite is a local-first micro-VM sandbox for AI agents — think "SQLite for sandboxing." It's a library you embed directly in your application, no daemon or cloud account required. Unlike ephemeral sandboxes that destroy state after each execution, BoxLite Boxes are stateful workspaces — install packages, create files, build up environment state, then come back later and pick up where you left off. | Feature | BoxLite | Docker | |---------|---------|--------| | **Isolation** | Hardware VM (KVM/Hypervisor.framework) | Container (namespaces/cgroups) | | **Daemon** | No daemon required | Requires Docker daemon | | **Root** | No root required | Typically needs root/sudo | | **Architecture** | Local-first library | Client-server architecture | | **Default state** | Stateful by default — full filesystem persists across stop/restart | Ephemeral by default — needs explicit volumes to persist data | | **Use Case** | AI agent sandboxes, secure code execution | Application deployment, CI/CD | | **Startup** | ~1-2 seconds | ~100-500ms | | **Isolation Level** | Separate kernel, hardware isolation | Shared kernel |
**When to use BoxLite:**
- AI agents that need full execution freedom
- Untrusted code execution
- Hardware-level isolation required
- Embedded in applications (no daemon)

**When to use Docker:**
- Application deployment
- Development environments
- CI/CD pipelines
- Established Docker workflows
**No.** BoxLite doesn't require root privileges.
**macOS:** Hypervisor.framework is available to all users (no special permissions).

**Linux:** Only requires access to `/dev/kvm`, which can be granted through group membership:

```bash
sudo usermod -aG kvm $USER
# Logout and login for changes to take effect
```
**Yes**, through WSL2 (Windows Subsystem for Linux).
**Requirements:**
- Windows 10 version 2004+ or Windows 11
- WSL2 with a Linux distribution (Ubuntu recommended)
- KVM support enabled in WSL2

**Setup:**
```bash
# Inside WSL2, add your user to the kvm group
sudo usermod -aG kvm $USER

# Apply the new group membership (pick one):
newgrp kvm
# OR restart WSL from Windows PowerShell:
# wsl.exe --shutdown

# Verify KVM access
python3 -c "open('/dev/kvm','rb').close(); print('kvm ok')"
```

**Common Issue:** If you see "Timeout waiting for guest ready (30s)" errors, your shell cannot open `/dev/kvm`. This happens when:
- `/dev/kvm` is owned by `root:kvm` with mode `660`
- Your user is not in the `kvm` group

Run `sudo usermod -aG kvm $USER` and restart WSL with `wsl.exe --shutdown`.

<Note>
  Native Windows (without WSL2) is not supported. BoxLite requires KVM (Linux) or Hypervisor.framework (macOS).
</Note>
**Python 3.10 or later.**
Check your version:
```bash
python --version  # Should be 3.10+
```

Upgrade if needed:
```bash
# macOS (Homebrew)
brew install python@3.11

# Ubuntu/Debian
sudo apt install python3.11

# Or use pyenv
pyenv install 3.11.0
```
**Yes.** BoxLite is stable and used in production.
**Production considerations:**
- Stable API
- Hardware-level isolation
- Resource limits enforced
- Error handling robust
- Monitor resource usage
- Test at expected scale
- Configure appropriate limits

See the [AI Agent Integration](/guides/ai-agent-integration) guide for production configuration, concurrency, and security patterns.
Apache License 2.0. Free for commercial and non-commercial use.

Technical Questions

**macOS:** Hypervisor.framework (built into macOS 12+)
**Linux:** KVM (Kernel-based Virtual Machine)

**How it works:**
- BoxLite uses libkrun as the hypervisor abstraction
- libkrun provides a unified API over Hypervisor.framework (macOS) and KVM (Linux)
- Each box runs as a separate microVM with its own kernel
**Minimum:** 128 MiB (configured via `memory_mib`)
**Default:** 2048 MiB

**Range:** 128 MiB to 64 GiB (65536 MiB)

**Overhead:**
- VM overhead: ~50-100 MB per box
- Guest kernel: ~20-40 MB
- Container: Depends on image

**Example:**
```python
# Lightweight box
boxlite.BoxOptions(memory_mib=128)  # Minimum for Alpine

# Standard box (default)
boxlite.BoxOptions(memory_mib=2048)  # Default

# Heavy box
boxlite.BoxOptions(memory_mib=4096)  # For complex workloads
```
**Typical:** 1-2 seconds
**Factors:**
- Image size (cached vs first pull)
- Disk I/O speed
- Available resources

**First run:** 5-30 seconds (includes image pull)

**Subsequent runs:** 1-2 seconds (image cached)

**Optimization:**
- Pre-pull images: `runtime.create(boxlite.BoxOptions(image="..."))`
- Reuse boxes instead of creating new ones
- Use smaller base images (`alpine:latest` vs `ubuntu:latest`)
**Yes**, using persistent disks.
**Ephemeral (default):**
```python
boxlite.BoxOptions()  # Data lost when box is removed
```

**Persistent:**
```python
boxlite.BoxOptions(
    disk_size_gb=10  # 10 GB persistent QCOW2 disk
)

# Data survives stop/restart
await box.stop()
# ... later ...
box = runtime.get(box_id)  # Disk intact
```

**Also:**
- Use volume mounts for host-box data sharing
- Read-write volumes persist changes to host filesystem
**1. Enable debug logging:** ```bash RUST_LOG=debug python script.py ```
**2. Check box status:**
```python
info = box.info()
print(f"State: {info.state}")
```

**3. Inspect filesystem:**
```bash
# Check disk space
df -h ~/.boxlite

# Check box data
ls -la ~/.boxlite/boxes/

# Check image cache
ls -la ~/.boxlite/images/
```

**4. Check hypervisor:**
```bash
# Linux
ls -l /dev/kvm
lsmod | grep kvm

# macOS
sw_vers  # Should be 12+
uname -m  # Should be arm64
```

See the [macOS Sandbox Debugging](/guides/macos-sandbox-debugging) guide for comprehensive troubleshooting.

Networking

**Yes.** All boxes have full internet access by default.
**Outbound connections:**
- HTTP/HTTPS requests
- DNS resolution
- Any protocol (TCP/UDP)

**Example:**
```python
async with boxlite.SimpleBox(image="alpine:latest") as box:
    # Test internet access
    result = await box.exec("wget", "-O-", "https://api.github.com/zen")
    print(result.stdout)
```
Use the `ports` parameter for port forwarding:
```python
boxlite.BoxOptions(
    ports=[
        (8080, 80, "tcp"),      # Host 8080 -> Guest 80
        (5432, 5432, "tcp"),    # PostgreSQL
        (53, 53, "udp"),        # DNS (UDP)
    ]
)
```

**Access from host:**
```bash
curl http://localhost:8080
```

See the [Architecture: Networking & Storage](/architecture/networking-storage) page for details.
**Not directly.** Boxes are isolated from each other.
**Alternatives:**

1. **Share data via volumes:**
   ```python
   volumes=[("/host/shared", "/mnt/shared", False)]  # False = read-write
   ```

2. **Use host network:**
   Box A exposes a port, and Box B connects to `host.docker.internal:port` (or localhost on Linux).

3. **External service:**
   Both boxes connect to Redis/database on host or network.

Performance

**Common causes:**
1. **Insufficient resources:**
   ```python
   # Increase limits
   boxlite.BoxOptions(
       cpus=4,          # More CPUs
       memory_mib=4096, # More memory
   )
   ```

2. **Disk I/O:**
   - Use ephemeral storage (faster than QCOW2)
   - Check host disk speed: `dd if=/dev/zero of=test bs=1M count=1024`

3. **Too many boxes:**
   ```python
   metrics = await runtime.metrics()
   print(f"Running boxes: {metrics.running}")
   # Reduce concurrency or increase host resources
   ```

4. **Image size:**
   - Use smaller images: `alpine:latest` (5 MB) vs `ubuntu:latest` (77 MB)
   - Check image size: `docker images`
**It depends on host resources.**
**Resource calculation:**
```text
Total Memory = (boxes * memory_mib) + overhead
Total CPUs = boxes * cpus (can oversubscribe)

Example:
100 boxes * 512 MiB = 51.2 GB memory needed
100 boxes * 1 CPU = 100 CPUs (oversubscribed, shares-based)
```

**Best practices:**
- Start small (10 boxes) and scale up
- Monitor metrics: `runtime.metrics().active_boxes`
- Use resource pooling (reuse boxes)
- Test at expected load

**Example:**
```python
import asyncio

async def run_100_boxes():
    tasks = []
    for i in range(100):
        task = run_box(i)
        tasks.append(task)

    results = await asyncio.gather(*tasks)
```
**No hard limit**, but practical constraints apply:
**Memory:**
- Range: 128 MiB to 64 GiB (65536 MiB)
- Limited by host RAM

**Disk:**
- Range: 1 GB to 1 TB
- Limited by host storage

**CPUs:**
- Range: 1 to host CPU count
- Can oversubscribe (shares-based)

**Tested configurations:**
- 64 GiB memory
- 1 TB disk
- 16 CPUs

Troubleshooting

**Causes:** 1. Network connectivity issues 2. Invalid image name/tag 3. Private image requires authentication 4. Registry not reachable
**Solutions:**
```bash
# Test with Docker first
docker pull <image>

# Check network
ping registry-1.docker.io

# For private images, authenticate
docker login

# Check image name format
# Correct: "python:3.11-slim"
# Wrong: "python/3.11-slim"

# Clear cache if corrupted
rm -rf ~/.boxlite/images/*
```

**Debug:**
```bash
RUST_LOG=debug python script.py
# Look for image-related errors in output
```
**Debug checklist:**
1. **Check disk space:**
   ```bash
   df -h ~/.boxlite
   # Should have at least 1 GB free
   ```

2. **Verify hypervisor:**
   ```bash
   # Linux
   ls -l /dev/kvm
   lsmod | grep kvm

   # macOS
   sw_vers | grep ProductVersion  # Should be 12+
   uname -m  # Should be arm64
   ```

3. **Check image:**
   ```bash
   docker pull <image>
   # Should succeed
   ```

4. **Enable debug logging:**
   ```bash
   RUST_LOG=debug python script.py
   ```

5. **Check permissions:**
   ```bash
   # Linux: Ensure user in kvm group
   groups | grep kvm

   # If not, add and relogin
   sudo usermod -aG kvm $USER
   ```
This is a known issue specific to Ubuntu 24.04. Ubuntu 25.04+ ships the required AppArmor profile by default.
**Symptom:** Box creation fails with "Timeout waiting for guest ready (30s)" or "VM subprocess exited before guest became ready" on Ubuntu 24.04. Works with `sudo` or on Ubuntu 25.04+.

**Root Cause:** Ubuntu 24.04 restricts unprivileged user namespaces via AppArmor (`kernel.apparmor_restrict_unprivileged_userns=1`) but does not ship the `bwrap-userns-restrict` profile that Ubuntu 25.04+ includes. bwrap (bubblewrap) needs user namespaces for sandbox isolation.

**Diagnosis:**
```bash
# Check for AppArmor denials
dmesg | grep apparmor
# Look for: apparmor="DENIED" ... comm="bwrap" capability=8

# Check if bwrap profile exists
aa-status | grep bwrap
# Should show "bwrap-userns-restrict" if profile is installed
```

**Fix (Option A -- targeted, recommended):**

Install the bwrap AppArmor profile that Ubuntu 25.04+ ships. Create the file `/etc/apparmor.d/bwrap-userns-restrict` with the following content, then reload:

```bash
sudo tee /etc/apparmor.d/bwrap-userns-restrict << 'PROFILE'
abi <abi/4.0>,

include <tunables/global>

profile bwrap /usr/bin/bwrap flags=(attach_disconnected,mediate_deleted) {
  allow capability,
  allow file rwlkm /{**,},
  allow network,
  allow unix,
  allow ptrace,
  allow signal,
  allow mqueue,
  allow io_uring,
  allow userns,
  allow mount,
  allow umount,
  allow pivot_root,
  allow dbus,
  allow pix /** -> &bwrap//&unpriv_bwrap,
  include if exists <local/bwrap-userns-restrict>
}

profile unpriv_bwrap flags=(attach_disconnected,mediate_deleted) {
  allow file rwlkm /{**,},
  allow network,
  allow unix,
  allow ptrace,
  allow signal,
  allow mqueue,
  allow io_uring,
  allow userns,
  allow mount,
  allow umount,
  allow pivot_root,
  allow dbus,
  allow pix /** -> &unpriv_bwrap,
  audit deny capability,
  include if exists <local/unpriv_bwrap>
}
PROFILE

sudo apparmor_parser -r /etc/apparmor.d/bwrap-userns-restrict
```

**Fix (Option B -- quick, less secure):**

Disable the restriction globally:

```bash
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0

# To persist across reboots:
echo "kernel.apparmor_restrict_unprivileged_userns=0" | \
  sudo tee /etc/sysctl.d/99-boxlite-userns.conf
```

**Fix (Option C -- disable jailer):**

If you don't need sandbox isolation (e.g., development environment), disable the jailer:

```python
from boxlite.boxlite import SecurityOptions

boxlite.BoxOptions(
    security=SecurityOptions(jailer_enabled=False),
    # ... other options
)
```
**Causes:** 1. Command is waiting for input 2. Long-running operation 3. Deadlock or infinite loop
**Solutions:**
```python
import asyncio

# Add timeout
async def execute_with_timeout():
    execution = await box.exec("command")

    try:
        result = await asyncio.wait_for(
            execution.wait(),
            timeout=30  # 30 second timeout
        )
        return result
    except asyncio.TimeoutError:
        await execution.kill()
        print("Command timed out")
```

**Check if command needs input:**
```python
# Provide stdin if needed
execution = await box.exec("command")
stdin = execution.stdin()
await stdin.send_input(b"input\n")
```
**Debug steps:**
1. **Check port is not in use:**
   ```bash
   lsof -i :8080
   # Should be empty, or show boxlite process
   ```

2. **Verify configuration:**
   ```python
   # Correct
   ports=[(8080, 80, "tcp")]

   # Wrong (swapped)
   # ports=[(80, 8080, "tcp")]  # Don't do this
   ```

3. **Test from inside box:**
   ```python
   # Start server in box
   await box.exec("python", "-m", "http.server", "80", background=True)

   # Test from host
   import requests
   response = requests.get("http://localhost:8080")
   ```

4. **Check gvproxy:**
   ```bash
   ps aux | grep gvproxy
   # Should show gvproxy process

   ls ~/.boxlite/gvproxy/
   # Should contain gvproxy binary
   ```
**Common scenarios:**
**1. ~/.boxlite directory:**
```bash
chmod 755 ~/.boxlite
chown -R $USER ~/.boxlite
```

**2. /dev/kvm (Linux):**
```bash
# Check permissions
ls -l /dev/kvm
# Should be: crw-rw---- 1 root kvm

# Add user to kvm group
sudo usermod -aG kvm $USER
# Logout and login required

# Or temporarily (not recommended)
sudo chmod 666 /dev/kvm
```

**3. Volume mounts:**
```bash
# Ensure host path is accessible
chmod 755 /host/path
```
**Cause:** Box exceeded memory limit.
**Solutions:**

1. **Increase memory limit:**
   ```python
   boxlite.BoxOptions(
       memory_mib=2048,  # Increase from 512 to 2048
   )
   ```

2. **Check actual usage:**
   ```python
   # metrics() is available on the low-level Box object (via runtime.create())
   metrics = await box.metrics()
   print(f"Memory: {metrics.mem / (1024**2):.2f} MB")
   ```

3. **Optimize code:**
   - Reduce memory footprint of executed code
   - Process data in chunks instead of loading all at once
   - Clear variables when no longer needed
**Cause:** KVM module not loaded or not accessible.
**Solutions:**

1. **Load KVM module:**
   ```bash
   sudo modprobe kvm kvm_intel  # For Intel CPUs
   sudo modprobe kvm kvm_amd    # For AMD CPUs

   # Verify
   lsmod | grep kvm
   ```

2. **Check CPU support:**
   ```bash
   grep -E 'vmx|svm' /proc/cpuinfo
   # Should show vmx (Intel) or svm (AMD)
   ```

3. **Enable in BIOS:**
   - Reboot and enter BIOS/UEFI
   - Enable "Intel VT-x" or "AMD-V"
   - Save and reboot

4. **Add user to kvm group:**
   ```bash
   sudo usermod -aG kvm $USER
   # Logout and login
   ```
**Cause:** Running on unsupported macOS version or architecture.
**Solutions:**

1. **Check macOS version:**
   ```bash
   sw_vers
   # ProductVersion should be 12.0 or higher
   ```

2. **Check architecture:**
   ```bash
   uname -m
   # Should output: arm64 (Apple Silicon)
   ```

3. **Upgrade if needed:**
   - BoxLite requires macOS 12+ (Monterey or later)
   - Apple Silicon (M1, M2, M3, M4) only
   - Intel Macs are **not supported**

<Note>
  If you have an Intel Mac, consider using a Linux VM, deploying to cloud (AWS, GCP, Azure), or using a cloud-based sandboxing service.
</Note>

Getting Help

**Documentation:** - [Getting Started](/getting-started/index) -- Quick onboarding - [How-to Guides](/guides/index) -- Practical guides - [SDK Reference](/reference/index) -- API and configuration reference - [Architecture](/architecture/index) -- How BoxLite works
**Community:**
- [Discord](https://go.boxlite.ai/discord) -- Chat with the team and community
- [GitHub Issues](https://github.com/boxlite-ai/boxlite/issues) -- Bug reports and feature requests
- [GitHub Discussions](https://github.com/boxlite-ai/boxlite/discussions) -- Questions and community support

**Before posting:**
1. Check this FAQ
2. Search existing issues/discussions
3. Enable debug logging: `RUST_LOG=debug`
4. Include BoxLite version, platform, and minimal reproduction
**1. Search existing issues:** [GitHub Issues](https://github.com/boxlite-ai/boxlite/issues)
**2. Gather information:**
- BoxLite version: `python -c "import boxlite; print(boxlite.__version__)"`
- Platform: `uname -a`
- Python version: `python --version`
- Error message and stack trace

**3. Minimal reproduction:**
```python
import asyncio
import boxlite

async def reproduce():
    # Minimal code that reproduces the issue
    async with boxlite.SimpleBox(image="python:slim") as box:
        result = await box.exec("command")

asyncio.run(reproduce())
```

**4. Debug logs:**
```bash
RUST_LOG=debug python reproduce.py 2>&1 | tee debug.log
```

**5. Create issue:**
- Use bug report template
- Include all gathered information
- Attach debug logs if relevant
- Be specific and clear
1. **Check roadmap:** Review [GitHub Issues](https://github.com/boxlite-ai/boxlite/issues) with the `enhancement` label 2. **Search for similar requests:** May already be planned or discussed 3. **Create feature request:** Use the feature request template, describe your use case, provide examples of desired API/behavior, and explain benefits to other users 4. **Participate in discussion:** Respond to questions, refine the proposal based on feedback, and consider implementing it yourself **Quick start:** ```bash git clone https://github.com/boxlite-ai/boxlite.git cd boxlite git submodule update --init --recursive make setup make dev:python ```
**Areas to contribute:**
- Bug fixes
- Documentation improvements
- New examples
- SDK improvements (Python, Node.js, C)
- Performance optimizations