Self-hosted virtual computers for background coding agents.
Website · Docs · Quick start · Demo · Discussions
Bastion is an open-source orchestrator for running background coding agents on your own Linux infrastructure. Each agent runs in a separate Cloud Hypervisor VM with a reproducible dev environment.
Define an environment in JSON, prepare its dependencies once as an immutable disk layer, and create disposable VMs for parallel tasks. Bastion can run on a single KVM host or schedule environments across an optional multi-node cluster.
Bastion makes it easy to scale background coding agents into reproducible environments.
- VM-level isolation: each environment has its own guest kernel, root filesystem, processes, and network.
- Declarative setup: define CPU, memory, disk, agents, service tunnels, and lifecycle actions in schema-validated JSON.
- Layered environments: prepare a shared base once, install project dependencies in a template overlay, then create isolated copy-on-write environments from that layer.
- Direct access: connect through SSH, attach a local OpenCode TUI, or use
bastion muxto move between persistent sessions. - Conflict-free previews: expose dev servers on the guest VM through named tunnels for host side previews.
- Self-hosted control: start on one Linux machine, then add the cluster control plane when a single host is not enough.
The host needs:
- Linux on x86_64
- read/write access to
/dev/kvm /dev/vhost-vsockfor VM tunnel traffic- nested virtualization when the host is itself a VM
curl -fsSL https://bastion.computer/install.sh | bash
bastion system init --with-utilities
bastion system check
bastion base buildThe installer adds the bastion CLI, guest proxy, and systemd services for the host API and privileged VM daemon. Release archives are also available from GitHub Releases.
cat > template.json <<'JSON'
{
"resources": {
"vcpu": 2,
"memory": 2,
"volume": 20
},
"agents": {
"opencode": {}
},
"actions": {
"init": [
{
"run": "mkdir -p /workspace && printf 'hello from Bastion\\n' > /workspace/README.md"
}
]
}
}
JSON
bastion templates create --key hello --file ./template.jsonTemplate creation boots a temporary VM from the shared base, runs actions.init, and stores an immutable qcow2 overlay tied to that base.
bastion env create --template-key hello --key agent-1
bastion ssh --key agent-1 -- cat /workspace/README.md
bastion ssh --key agent-1With OpenCode installed locally, attach its TUI to the server inside the environment:
bastion opencode --key agent-1Or open Bastion's tmux-based environment picker:
bastion muxClean up when finished:
bastion env remove --key agent-1
bastion templates remove --key helloFor a complete parallel-agent walkthrough, see the Bastion issue tracker demo. It includes a Bun/TypeScript app, a reusable environment template, service previews, and five independent coding tasks.
flowchart LR
Client["CLI / API client"] --> API["Host API<br/>unprivileged · SQLite"]
API -->|Unix socket| Daemon["bastiond<br/>privileged VM operations"]
Daemon --> VM1["Cloud Hypervisor VM<br/>agent-1"]
Daemon --> VM2["Cloud Hypervisor VM<br/>agent-2"]
Daemon --> VMN["Cloud Hypervisor VM<br/>agent-n"]
The local control plane is split into two processes:
bastion start apistores metadata, serves the HTTP API onlocalhost:3148by default, and runs without root privileges.bastion start daemonperforms privileged Cloud Hypervisor operations behind a Unix socket.
bastion base build prepares one template-agnostic root disk with common guest components. When a template is created, Bastion boots a temporary VM with a qcow2 overlay backed by that base, runs the ordered actions.init steps, and saves the immutable overlay. Creating an environment adds a fresh writable overlay backed by the template, cold-boots it with new cloud-init state, runs optional actions.start steps, and exposes SSH, OpenCode, and configured service tunnels through the API.
For multiple hosts, the optional cluster API stores shared state in Postgres, stores the global base and template archives in S3-compatible object storage, synchronizes the base across nodes, schedules environments onto registered nodes, and proxies connections to the node that owns each environment.
This example prepares a Bun project once, refreshes it whenever an environment starts, and exposes its development server:
{
"resources": {
"vcpu": 4,
"memory": 8,
"volume": 40
},
"tunnels": {
"web": 3000
},
"agents": {
"opencode": {
"working_directory": "/workspace/project"
}
},
"actions": {
"init": [
{
"use": "setup_bun"
},
{
"run": "git clone https://github.com/your-org/your-repo.git project",
"working_directory": "/workspace"
},
{
"run": "bun install",
"working_directory": "/workspace/project"
}
],
"start": [
{
"run": "git pull --ff-only",
"working_directory": "/workspace/project"
},
{
"run": "nohup bun run dev >/tmp/dev-server.log 2>&1 &",
"working_directory": "/workspace/project"
}
]
}
}bastion templates create --key project --file ./template.json
bastion env create --template-key project --key issue-123 --tag repo:project
bastion proxy --env-key issue-123 --name webSee the template guide and public JSON schema for the complete format.
- VM hosts currently need Linux x86_64, KVM, and vhost-vsock. macOS Apple silicon is client-only.
bastiondruns as root because it manages VM lifecycle and networking operations. Template actions run as root inside the guest.- The host API binds to
localhost:3148by default. Anyone who can reach it can create, remove, and enter environments, so keep it private or place it behind your own authenticated network and TLS boundary. - OpenCode is the built-in agent integration today; SSH is available for other tools and workflows.
- The project is pre-1.0, and interfaces may still change.
Start with the introduction and quick start, then see the guides for system setup, the shared base, templates, environments, and clustering. The site also includes complete CLI and API references.
Questions, bug reports, design feedback, and use cases are welcome in GitHub Discussions or by email at hazim@bastion.computer.
Bastion is available under the MIT License.