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 it once as a snapshot, 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.Prepared snapshots: install dependencies during template creation, then replicate isolated copy-on-write environments from that prepared state.Direct access: connect through SSH, attach a local OpenCode TUI, or usebastion mux
to 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-vsock
for VM tunnel traffic- nested virtualization when the host is itself a VM
curl -fsSL https://bastion.computer/install.sh | bash
bastion system check
bastion system init --with-utilities
The 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.json
Template creation boots a temporary VM, runs actions.init
, and stores an immutable prepared root disk and VM snapshot.
bastion env create --template-key hello --key agent-1
bastion ssh --key agent-1 -- cat /workspace/README.md
bastion ssh --key agent-1
With OpenCode installed locally, attach its TUI to the server inside the environment:
bastion opencode --key agent-1
Or open Bastion's tmux-based environment picker:
bastion mux
Clean up when finished:
bastion env remove --key agent-1
bastion templates remove --key hello
For 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 api
stores metadata, serves the HTTP API onlocalhost:3148
by default, and runs without root privileges.bastion start daemon
performs privileged Cloud Hypervisor operations behind a Unix socket.
When a template is created, Bastion boots a temporary VM, runs the ordered actions.init
steps, s it, and saves its prepared disk and VM snapshot. Creating an environment restores that snapshot, adds a small qcow2 writable overlay, 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 prepared template archives in S3-compatible object storage, 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 web
See 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.
bastiond
runs as root because it manages VM lifecycle and networking operations. Template actions run as root inside the guest.- The host API binds to
localhost:3148
by 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, 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.