Reference deployments
Reference deployments
Two deployments that are worth copying, drawn rather than walked through.
One is built and serving: mechabedo on spica, a single-node cluster, with a beam host beside it. The other is planned and not built: a Coder workspace template that carries its own beam host inside the workspace. They differ in one decision - where the host lives - and almost everything else follows from it.
This page is architecture only. The procedures for either shape are Running mechabedo as a server, Running a beam host and Upgrading, and they do not change because of which shape you picked.
The tandem
Both deployments are the same pair of programs in the same relation:
Drawing the diagram…
The installation never listens. It dials, claims a slot, and answers requests that arrive down that connection. The host never holds the work: it holds tunnels, and it can be restarted without losing any. That relation is what makes either deployment possible, and it is the only thing the two have in common at the infrastructure level.
What differs is where the host runs, and that one choice decides the public surface, the credential, and who can join.
| Host beside the installation | Host inside the installation | |
|---|---|---|
| Built example | spica | the Coder template (planned) |
| Where it listens | Its own workload, on its own host | Loopback in the same process |
| Public surface | One, TLS at the edge, shared | None |
| Slot credential | In the host's BEAM_SLOTS, minted by its operator | Minted into <settings>/beam-host/, one entry |
| Who joins | Any machine the host's operator invites | The person at that workspace, with a code |
| Reached by | https://<host>/__beam/go/<slot> | The platform's own port forward |
| Bedos, routines, fleet | Yes | Yes, on that one host |
| One host serves | Many installations | Exactly one |
Read the left column as a fleet, the right as one machine. Neither is a lesser version of the other; they answer different questions, and a fleet of workspaces that each ran their own host would have no shared archive, no peering, and no marketplace.
spica: an installation in a cluster, one host at the edge
spica is a single-node k0s cluster, and mechabedo runs on it as an OpenChoreo component. The beam host is a separate deployment in the same cluster, and that is the decision the rest of the shape rests on.
Drawing the diagram…
Both pods are on the same node and the traffic still leaves through the public address. That is deliberate rather than careless: the tunnel is a dial-out and the browser's entry point is the host either way, so a project-visibility shortcut between two OpenChoreo projects would be another route to configure for no behavioural gain.
Why the host is not embedded here. An embedded host has no TLS, no public address and no fleet sign-in; it is meant for one machine and for machines that reach it over a private network. spica already terminates TLS for one hostname at the edge, and one public surface is the thing that costs least and fails least. Putting a host inside the pod would trade that for a second door per workspace and nothing gained.
What the platform owns, and what the installation owns
| Piece | Owner | Notes |
|---|---|---|
| Project, Component, Workload | The deployment program | A stateful-workload with a volume claim, project visibility only |
| The volume | The platform | The installation. Restoring it is restoring the deployment |
| The Secret, the PushSecret, the SecretReference | The deployment program | The vendor document and the slot token, through OpenBao |
| The slot and its token | The beam stack | Read with a stack reference, so no address or credential is written twice |
| The image | mechabedo's own Dockerfile | Built from a checkout, never vendored |
Everything above /data | The installation | Kits, loadouts, sessions, transcripts, harnesses |
Two consequences worth knowing before you change anything:
- The slot is not this deployment's to issue. A slot the beam stack does not name is a preview error, not a pod that dials forever.
- A config-only change still needs the pod restarted. Nothing reads the environment twice; a changed vendor document reaches the process on the next start, and rolling the pod is what applies it.
The vendor document is the interface
The pod carries no ConfigMap and no seeded file. The whole document arrives as MECHABEDO_VENDOR_CONFIG, which is what a platform with secrets and environment but no way to put a file on a volume before the first start wants.
What it carries is the deployment, section by section: the login, the gateway, the workspaces root, the telemetry that has to be stated rather than defaulted, and - seeded once onto the volume, then the settings page's - the kits and the loadouts. A deployment that states a kit with autonomous drive and a self-learning pass starts able to take work on its own, with nothing left to call after the first start.
The secrets stay in a Secret and reach the pod as environment. A platform that mounts secrets as files instead names the path with <VAR>_FILE and puts nothing in the process environment; that is what the Coder shape below uses, and it is a choice the document does not have to make for you.
The Coder workspace template (planned, not built)
Nothing here exists yet
This is the shape and the decisions it forces, recorded so the template is built against a plan rather than discovered. There is no template, no image pin and no support claim here.
The question this shape answers: a workspace in a cloud IDE should be able to take work on its own, without anybody deploying a beam host for it. The transport for that exists already - the host runs inside the server on loopback, and that server is its operator (mechabedo ADR 664) - so the template is mostly a matter of getting the volume, the login and the policy right.
Drawing the diagram…
What the shape gives you
- Bedos work with no beam host deployed. Threads, inbox, desk, routines and
bedo_requestall live on the embedded host, so a workspace is not a lesser installation. - The workspace's own desktop can join it. The installation holds the host's operator token, so
Invite a machineissues a one-time code, and a laptop redeems it with an address and a code typed by a person. No environment edit, no restart, no token pasted into a chat. - The archive converges. Desktop and workspace push to a shared logbook, so what was done in either is searchable from the other.
- Nothing is public. The host binds loopback. Reaching a workspace is the platform's job, by the same port forward or SSH that reaches anything else in it.
What it gives up, and must not pretend otherwise
| Not available | Because |
|---|---|
| A fleet host | One host per installation, in that process. A machine cannot run a host for others and be a workspace |
| TLS, a hostname, fleet sign-in | The embedded host has none, by design. A public host is still built from a checkout and run on its own |
| A shared public entry point | Each workspace is reached the platform's way. There is no /__beam/go/<slot> a stranger can be handed |
| Logbook sharing with everyone by default | The shared logbook is joined by invite, and the workspace's host is not a member of anything until it is |
The decisions the template still owes
These are the questions the plan has to answer, in the order they bite:
- The image. The vendor container, pinned by digest, with the host's start compiled in. A workspace that installs on first start is a workspace that takes ten minutes to be useful.
- The volume.
/dataas one volume, because the database and the settings directory are one unit. A template that gives/data/settingsits own lifecycle produces a machine that reclaims the wrong slot. - The login. Vendor mode refuses to start without a valid
authsection, which for a template means a parameter that becomes the basic login, or OIDC against the platform's own identity provider. The failure mode to avoid is a template that comes up unauthenticated. - Who answers cards. A workspace nobody sits at cannot answer a consent card. The vendor document's
unattendedhalf is the policy that stands in -agentsfor its own sessions,remotefor other installations,roomsfor the Bedo threads - and leaving itoffmeans an autonomous workspace that stalls at its first question. - Secrets as files. A platform that mounts a credential as a file names it with
<VAR>_FILErather than carrying the value in the environment, which also keeps it out of every harness the server spawns. - What the workspace is for. A kit with autonomous drive and a self-learning pass, seeded once in the vendor document, is the difference between a remote shell and a workspace that takes work on its own.
What both deployments share
Three things hold in either shape, and they are what to check first when one of them misbehaves:
- The volume is the installation. The database and the settings directory go together; restoring half of them produces a state that never existed.
- One slot, dialed out. Losing the host interrupts access and loses no work. A slot held by another machine is reported as such, and the installation waits rather than fighting for it.
- The vendor document is the deployment. In both shapes what the document names is written back on every start, so a container that drifted heals when it restarts and a setting changed in the UI that the document also names does not survive.
Next
- The architecture - every component and hop, in full
- Cloud agentic workspaces - a fleet of these, with patterns and capacity
- Running mechabedo as a server - the container in either shape
- Beam, server setup - the three container shapes and the embedded host