Heyo Web Services
Agents, their sandboxes, and their tools all need a home. So does everything you build with them. Heyo Web Services is the open source stack for running workloads on your own hardware — agents, sandboxes, MCP, and apps in microVM pools, with auth, CI, active security monitoring, and observability around them. And you drive all of it from your agent.
Everything above the VM, as binaries you run
HWS is shaped like the platforms agents already know — deployments, replicas, routes, secrets, namespaces, tokens — but every piece is a single binary on hosts you control, configured by environment variables. The source is on GitHub.
MicroVM images
Firecracker or KVM images built from a Dockerfile, kept in a content-addressed artifact store.
app-lb
Load balancer, autoscaler, TLS, and control plane in one process.
SIEM
Built-in security monitoring on every request, with block rules on the data plane.
ci
GitHub-Actions-shaped workflows, one fresh microVM per job, on your runner hosts.
app-obs
Logs and metrics for every deployment, with no shipper in the guest.
Auth
Google, app-token, or JWT/OIDC sign-in in front of any deployment, plus write-only secrets.
heyo-mcp
Tools for sandboxes, deployments, logs, CI, and artifacts — for your coding agent.
heyctl
A kubectl-style CLI and a Rust client library for the whole fleet.
pg-fc
Postgres with one microVM per database. Idle databases stop and wake on the next connect.
Dockerfile in, microVM out
Every workload is a Firecracker or KVM microVM (or an Incus container) whose image you build from the Dockerfile you already have, with heyvm. HWS adds everything above the VM.
Images live in art, a content-addressed blob store built for ext4. A blob’s only name is the sha256 of its bytes, so a tag is something you move and a digest is something you roll back to.
Sparse by default
Zero runs become holes on disk: a 20 GiB image with ~600 MiB of real data takes ~600 MiB, and the digest still matches the original file.
More than images
Site bundles, Dockerfile build inputs, workspace snapshots, and release binaries go in the same store.
Build anywhere, pull everywhere
Build once, push, and let each app-lb host pull. Re-pulling unchanged bytes skips the transfer.
# Build a bootable rootfs from your Dockerfile heyvm mvm build --local-only -f Dockerfile -n web-v2 # Push it to your artifact store heyctl artifact push --image web-v2 # Point a deployment at the store and roll the pool heyctl set artifact web --store /srv/artifacts --ref web-v2 heyctl pull web --wait # Roll back: pin exact bytes by digest heyctl pull web --ref <digest>
The edge, the autoscaler, and the control plane
app-lb is one Rust process built on Pingora. It terminates HTTP and HTTPS, routes each request by host and path, and boots, health-checks, drains, and reaps microVMs to match the traffic each deployment is getting. Its admin API and dashboard run deployments, secrets, builds, artifact pulls, and certificates.
A pool can sleep at zero. When a request arrives at an empty pool, app-lb boots a VM and holds the request until it is healthy.
Managed pool
A microVM template plus a scaling policy: min, max, warm spares, target concurrency, and an idle timeout before scale-to-zero.
Static upstreams
A fixed list of origins you already run, balanced least-in-flight with failover. Cordon and drain one without dropping requests.
Static site
A directory on the host, served straight off disk — ETags, byte ranges, custom 404, SPA fallback.
- Automatic TLS — set an ACME email and every exact host route gets a Let’s Encrypt certificate, renewed 30 days before expiry. Wildcards over DNS-01.
-
Builds from git — a
buildblock runsheyvm mvm buildon the host and rolls the pool onto the result. - Candidate-first rollouts — new replicas boot unrouted, cut over only when healthy, and the old ones drain.
-
Private by default — a
deployment with no routes is still autoscaled
and reachable with
execandshell. The normal shape for an agent sandbox.
# A public pool that sleeps at zero heyctl create deployment web --host web.example.com \ --image web-v2 --port 8080 --min 0 --max 4 # Tune the policy in place; the pool keeps running heyctl scale web --warm 1 --scale-to-zero-after 600 heyctl rollout status web # Ship the next commit heyctl build web --ref main --logs
A SIEM in the load balancer
Security monitoring is on by default. app-lb
analyzes every request off the request path, so
detection never slows traffic, and raises alerts
with ECS field names. Alerts ship to app-obs; the
/siem console shows each finding with
a runbook and a pre-filled block rule.
Authentication abuse
Brute force, password spraying across deployments, identity enumeration, and scope denials.
Attack signatures
RCE, path traversal, SQL injection, XSS, and secret probes. Query strings are scanned but never stored.
Traffic anomalies
Scanners walking many paths for 4xx, and rate spikes from a single source.
Block and allow rules are enforced on the data plane and persist across restarts. Match on client address or CIDR, host, deployment, path, method, or user agent; give a rule an expiry; and try a broad one in dry-run mode first, where it counts hits but refuses nothing.
# Block a source for an hour curl -XPOST localhost:9090/security/rules -H 'content-type: application/json' \ -d '{"action":"block","match":{"client":"203.0.113.9"},"expires_in_secs":3600}'
CI on your own metal, a fresh microVM per job
Agents push dozens of times an hour. Paying a
metered runner to cold-start for each one, while
your source and secrets take a trip through
someone else’s datacenter, is the slow way.
ci runs the pipeline on runner
hosts you own: any machine running
heyvmd in a heyvm network, with no
agent to install.
Workflows you already write
GitHub-Actions-shaped YAML — jobs,
needs, matrices, expressions — plus a
vm: block that describes the
machine to boot, built from a Dockerfile.
Submit, don’t push
git submit sends an exact
revision as a pinned base and a patch
— even uncommitted work with
--dirty. No webhook, no
repository archive.
Durable queue
Postgres is the source of truth; NATS JetStream is the queue. Logs stream live to the dashboard.
Secrets stay home
Secrets resolve per job from HeyoSecret and are masked in logs. Build outputs upload to your artifact store.
# Check workflows offline, no database or broker needed ci --check-workflows .ci/workflows/build.yml # Submit HEAD, or include uncommitted tracked changes git submit git submit --dirty # Run just one workflow git submit --only app-lb
Logs, latency, and errors with no code changes
app-obs runs next to app-lb and follows every managed VM’s console and start output straight from the heyvm daemon — no shipper or agent inside the guest. It polls app-lb’s metrics for request counts, errors, p50/p90/p99 latency, pool state, and CPU and memory, and it is never part of the data plane: if it goes down, traffic keeps flowing.
Push when you want
Applications can also push logs over HTTP or syslog to their default gateway.
Parquet you own
Hive-partitioned Parquet, compacted in the background, deleted past a retention window.
Dashboard and alerts
Fleet view, per-deployment charts, a log viewer, and webhook alerts on error counts. No CDN required.
# Webhook when "web" logs more than 5 errors in a minute curl -XPOST localhost:9600/api/alerts \ -H 'content-type: application/json' \ -d '{"deployment": "web", "threshold": 5, "webhook_url": "https://hooks.example.com/obs"}'
Sign-in in front of anything, no auth code behind it
Add an auth block to any deployment
— a VM pool, a static upstream, or a site
— and app-lb runs the gate in the proxy
before a backend is chosen. Turning a gate on or
off never restarts the pool, and the application
gets the signed-in user as forwarded identity
headers.
OAuth with PKCE, admitted by Workspace domain or individual email. Sessions are HMAC-signed, so a restart signs nobody out.
JWT and OIDC
Verify tokens from Auth0, Okta, Cognito, Keycloak, or your own issuer, with claim constraints. Declare a provider once per namespace and inherit it.
App-tokens
Scoped, revocable, optionally expiring bearer tokens for programs and agents. Pair with Google for a UI an agent also drives.
Secrets
app-lb’s secret store is write-only and injects values by name. HeyoSecret keeps the canonical copies, versioned and AES-256-GCM encrypted.
# Put a deployment behind Google sign-in heyctl create secret google --from-stdin client_secret < ~/.google-oauth-secret heyctl set auth web \ --client-id 1234-abc.apps.googleusercontent.com \ --secret google/client_secret \ --allow-domain example.com
Run the whole cloud from your agent
heyo-mcp gives coding agents such as
Claude Code 65 tools across sandboxes, app-lb
deployments, app-obs logs and metrics, ci runs, and
the artifact store. Run it locally over stdio, or
host it over HTTP as an app-lb deployment behind a
sign-in gate, acting as each caller with their own
token.
Deploy
applb_deploy validates a spec,
creates or updates the deployment, starts
the right job, waits, and reports TLS.
Diagnose
diagnose_empty_pool combines
pool state, logs, and metrics to explain
why a pool won’t fill.
Guardrails
Read-only tools only issue GETs.
Destructive tools carry the MCP
destructiveHint.
# Add HWS to Claude Code claude mcp add heyo \ -e HEYO_API_KEY=heyo_api_… \ -- node /path/to/hws/mcp/dist/index.js
kubectl verbs, without the cluster
heyctl drives the app-lb admin API:
apply declarative specs, use
create, scale, and
set to write them for you, and read
them back with get,
describe, and top. Named
contexts switch between fleets, and
exec and shell get you
inside any VM.
heyctl ships in the
hws
crate, which is also a Rust client library. Depend
on it with default-features = false
for the typed client without the CLI — the
foundation for building your own sandbox platform.
# Install the heyctl CLI cargo install hws # Copy a deployment from one load balancer to another heyctl get deployment web -o json | heyctl --context staging apply -f - # Cargo.toml: the typed client, no CLI hws = { version = "0.1", default-features = false }
Rent the cloud, or run your own
HWS runs anywhere with Linux and
/dev/kvm: a desktop under your desk,
servers you rent, or
Heyo’s bare metal. One bootstrap script turns a fresh Debian or
Ubuntu machine into an app-lb host in one step.
Managed databases, sandbox platforms, hosted CI, app hosting — each one is a fine product and a permanent line item. They add up to a cloud you rent forever for software you wrote yourself. HWS is the other path: the same primitives, running as files and pools on machines with your name on them.
Renting the cloud
- Every service is a separate bill that scales with usage
- Idle capacity is billed like peak capacity
- Agents get throwaway sandboxes priced per seat
- Your images, data, and build history live in their region
Running your own
- One stack runs apps, Postgres, agents, and CI
- Scale-to-zero pools release their VMs when idle and wake on demand
- Agent sandboxes are deployments on hardware you already pay for
- Images are content-addressed files you keep, move, and roll back
Wondering how this stacks up next to E2B, Modal, Daytona, Northflank, or Microsandbox? See the head-to-head → · Read the installation docs →
Build your own cloud
Open source, on your hardware, driven from your agent.