CI runners
Run untrusted PR CI inside ephemeral Firecracker microVMs — no sandbox-escape risk.
Use PandaStack as a GitHub Actions / GitLab CI runner backend. Each job gets a fresh microVM, runs, and dies — no risk of one PR's test suite affecting another's, no shared state, no escape vectors common to Docker-in-Docker.
Pattern: webhook → sandbox
from fastapi import FastAPI, Request
from pandastack import Sandbox
app = FastAPI()
@app.post("/ci/webhook")
async def webhook(req: Request):
payload = await req.json()
repo = payload["repository"]["clone_url"]
sha = payload["after"]
with Sandbox(template=pick_template(payload), cpu=4, memory_mb=8192) as sb:
sb.run(f"git clone --depth 1 --branch {sha} {repo} /workspace", timeout=120)
# Cache deps using a shared read-only volume
sb.attach_volume("vol_deps_cache", mount="/cache", readonly=True)
result = sb.stream(
"cd /workspace && make ci",
on_stdout=lambda c: upload_log(payload, "stdout", c),
on_stderr=lambda c: upload_log(payload, "stderr", c),
)
report_status(payload, "success" if result.exit_code == 0 else "failure")Pattern: matrix builds via fork
Build one "base" sandbox with dependencies installed, then fork for each matrix cell:
base = Sandbox(template="node-js")
base.run("git clone https://... /app && cd /app && npm ci", timeout=300)
snap = base.snapshot()
base.close()
# Now run 8 matrix cells in parallel, each starting from the snapshot
def matrix_cell(node_version: str):
sb = Sandbox.from_snapshot(snap.id)
try:
sb.run(f"cd /app && nvm use {node_version} && npm test")
finally:
sb.close()
with ThreadPoolExecutor(max_workers=8) as ex:
list(ex.map(matrix_cell, ["18", "20", "22"]))The snapshot is created once (npm ci happens once). Each matrix cell restores in ~250 ms.
Compared to GitHub Actions hosted runners
| GitHub Actions hosted | PandaStack | |
|---|---|---|
| Cold start | 30–60 s (provision VM) | 250 ms (snapshot restore) |
| Isolation | per-job VM | per-job microVM |
| Cost (1 vCPU·min) | $0.008 | ~$0.0008 (self-hosted) |
| Cache reuse | actions/cache (slow) | read-only volume mount (instant) |
| Custom hardware | Limited | Any KVM-capable host |