Architecture
Overalls is a monorepo of small services, each named after something or someone, with one NixOS deployment that wires them together. Marshall holds the record of what should exist. Lilly hosts make it physically true and report back. The other services sit at the edges: SSH, DNS, egress, inference, integrations, clients and notifications.
Components
| Name | Role | What it gives you |
|---|---|---|
Marshallmarshall/ | Web app and control plane (Elixir, Phoenix, Ash) | Accounts with magic links and passkeys, Cedar authorization, machine lifecycle, scheduling, sharing, teams, the browser terminal and agent threads. |
Lillylilly/ | Host provisioner (Elixir) | Runs Firecracker guests on ZFS behind jailed, isolated networks, with a durable actor for each VM. Guests keep running when Lilly restarts. |
Porscheporsche/ | SSH management gateway | ssh <gateway> <command> manages machines with the same account and permissions as the web. |
Audiaudi/ | DNS and ingress | Authoritative DNS and ingress for guest SSH, public web apps and personal browser editors. |
Bradybrady/ | Egress proxy and cache | Guest downloads go through verified upstreams, and public anonymous responses are cached. |
Enricoenrico/ | Read-only GitHub mirror | Caches registered public GitHub repositories for Marshall's repository browser. |
Galileogalileo/ | Integration gateway | Named integrations at <name>.integration.internal; credentials are added at the edge. |
Ziggyziggy/ | Inference proxy | llm.internal for guests, with no provider keys inside the VM and usage recorded per account. |
Lyralyra/ | CLI and guest tools (Rust) | The overalls CLI: wildcard SSH, open for repos, agent prompts. It also runs the agent's tools inside the guest. |
Marvinmarvin/ | Browser extension | Opens the repository page you're on in your Overalls deployment. |
Milamila/ | Native desktop and mobile client (preview) | Native clients over a shared Rust core for iOS, Android, macOS, Linux and Windows. Manages machines and threads over one SSH connection to Porsche after browser approval of a device key; platform verification remains partial. |
Susansusan/ | Push notification relay | Relays end-to-end encrypted Mila notifications to APNs, FCM and WNS without seeing their content. |
Peachpeach/ | Guest reflection service | Serves reflection.internal: a secret-free view of the integrations a running guest may use, authorized by Marshall. |
Protocolprotocol/ | Shared wire schemas | Validates the messages services exchange, so their interfaces stay consistent. |
Fleet, Nix and Buck2fleet/ nix/ buck/ | Declarative infrastructure and builds | NixOS modules, host inventory, guest images, secrets, and the host install and enroll tools. Buck2 builds with Nix-pinned toolchains and assembles host deployments. |
Control plane and hosts
You can run multiple Marshall instances against a shared PostgreSQL. Machine capacity is admitted atomically, so concurrent requests can't overbook a host. Every lifecycle change is a durable operation with an audit trail. Each host's Lilly dials out to Marshall with its own revocable credential, sends capacity reports and receives commands. A generation fence stops a delayed launch from starting a guest after a stop has already been requested.
┌──────────────────────────────────────────┐
browser ─HTTPS─▶│ HAProxy TLS, ACME, verified backends │
└────────────────────┬─────────────────────┘
▼
ssh ──────────▶ Porsche ───▶ ┌────────────────┐ ┌────────────┐
overalls CLI ──────────────▶ │ Marshall × 1…N │◀───▶│ PostgreSQL │
│ Phoenix · Ash │ └────────────┘
│ Cedar · Oban │
└───────▲────────┘
│ HTTPS, per-host credential
│ reports up · commands down
┌─────────────┴─────────────┐
┌──────┴──────┐ ┌──────┴──────┐
│ Lilly host │ · · · │ Lilly host │
│ ZFS · KVM │ │ ZFS · KVM │
└─────────────┘ └─────────────┘
Regions
We recommend running Marshall in a single region. Its instances share one PostgreSQL, and admission, sharing and lifecycle decisions all depend on that database, so keep them close to it. Run several instances in that region for high availability.
Lilly hosts connect to Marshall over HTTPS, so you can put hosts in every region where your developers work. Cross-host cloning and relocation also require reachable, authenticated transfer SSH endpoints.
Where the traffic goes depends on how you connect. SSH, VS Code over Remote-SSH, shared web apps and the browser editor enter through Audi on the machine's own host. Their data stays in that region, while Marshall authorises access. The browser terminal is relayed through Marshall, over the connection the host dialled out, so it pays the round trip to the control-plane region.
┌─ control plane · one region ───────────────────────────────┐
│ │
│ HAProxy ─▶ Marshall · Marshall · Marshall ◀─▶ PostgreSQL │
│ several Marshall instances for high availability │
│ │
└──────────────────────────────┬─────────────────────────────┘
▲
│ HTTPS, dialled out by every host
│
┌────────────────────────────┼────────────────────────────┐
┌──────────┴──────────┐ ┌──────────┴──────────┐ ┌──────────┴──────────┐
│ WASHINGTON DC │ │ LONDON │ │ SINGAPORE │
│ Lilly Lilly Lilly │ │ Lilly Lilly │ │ Lilly Lilly │
│ guests on ZFS │ │ guests on ZFS │ │ guests on ZFS │
│ Audi: SSH, web apps │ │ Audi: SSH, web apps │ │ Audi: SSH, web apps │
└─────────────────────┘ └─────────────────────┘ └─────────────────────┘
▲ ▲ ▲
developers in developers in developers in
the Americas Europe Asia-Pacific
┌─ control plane · one region ─────────────────────────────────────────┐
│ HAProxy ─▶ Marshall · Marshall · Marshall ◀─▶ PostgreSQL │
└───────▲──────────────────────────────────────────────────────▲───────┘
│ browser terminal relay over HTTPS, │
│ dialled out by Lilly │
│ │
┌────────────┴────────────┐ ┌──────────────┴─────────────┐
│ DEVELOPER IN SINGAPORE │ │ HOST IN SINGAPORE │
│ browser terminal │ │ │
│ ssh, VS Code, web apps, │ direct, same region │ │
│ browser editor ────────┼─────────────────────────▶│ Audi ─▶ Lilly ─▶ guest │
└─────────────────────────┘ └────────────────────────────┘
A machine's life
A machine is an identity first and a process second. Its UUID, name, private address, sharing and disk outlive any particular Firecracker process, so stopping, resizing and relocating it don't create a new machine. Running relocations involve downtime. Cloning creates an independent machine: the copy is private, gets a new identity, name and address, and starts without the source's RAM.
new ─▶ [pending] ─▶ [running] ◀── start ─── [stopped]
│ │ ▲
│ └────── stop ────────┤
│ │
└───────┬───────────────┘
├─ relocate ─▶ another host
├─ clone ────▶ new private identity and disk
├─ resize ───▶ CPU, memory and disk size
└─ rm ───────▶ disk deleted
From inside a guest
Guests reach the outside world through services that can check, cache and record the traffic. Brady handles public HTTP and HTTPS, Ziggy handles inference, and Galileo handles integrations. Enrico serves Marshall's repository browser. Lateral traffic between guests and to private address ranges is blocked by Lilly's nftables policy. The locked-down customer profile removes outbound networking entirely.
┌─ guest ─────────────────────────────┐ │ apt · nix · pip · npm ──────────────┼──▶ Brady · proxy and cache ─▶ internet │ https://llm.internal ───────────────┼──▶ Ziggy ─▶ OpenAI, Anthropic │ https://x.integration.internal ─────┼──▶ Galileo · adds credentials └─────────────────────────────────────┘ platform credentials stay outside the guest; usage is recorded per account
Principles
- Declared, reviewed, then applied. Hosts, images, users and secret recipients live in Git. Hosts install from a reviewed plan and update from a pinned branch.
- Make it your own. Your fork is yours to change. Patch a component, pin a package or add tools to the guest images with a Nix overlay rather than carrying a long-lived fork of the code.
- Secrets never travel in the clear. SOPS and age documents are encrypted to each host's SSH-derived key and to named recovery users. Private keys are generated where they're used.
- Authority is checked at execution time. Cedar policies are evaluated when each action runs, not when a page was loaded, so revoked access takes effect on pages that are already open.
- Uncertainty is explicit. If a request might not have reached a host, the system asks for deliberate reconciliation rather than guessing.
Decision records
Every design decision is written up as an architecture decision record (ADR), with a review recording the evidence. Some good places to start:
- ADR-0018 · Persisted sharing and machine access
- ADR-0022 · Browser terminal and live login checks
- ADR-0030 · NixOS deployment and TLS
- ADR-0036 · Automatic host updates
- ADR-0043 · Declarative host provisioning
- ADR-0048 · Single-host service deployment
- ADR-0055 · Queued machine cloning
- ADR-0077 · Teams and shared resources
- ADR-0153 · Official-source browser editor
- ADR-0157 · Multi-provider repository launch
- ADR-0161 · Monospace Web presentation
- ADR-0190 · Native guest kernels and image admission
- ADR-0199 · Suspension, relocation and demand wake
- ADR-0249 · Mila's Rust core and native clients
- ADR-0269 · Buck2 builds with Nix toolchains
- ADR-0271 · Host self-deployment through Buck2