042: A Docker host can be a BB machine, reached through BB
Status: accepted, 1 October 2026. Extends 031: the Docker backend reaches a BB machine’s Docker without SSH. Checked after it was built: on a Windows PC, the relay reaches Docker Desktop’s socket in WSL, and privileged boxes there start and enrol (#233). Extended by 049: Docker images are rebuilt through the same relay. Extended by 055: a cloud VM is a Docker host through the same relay.
Context
A developer’s PC that runs Docker already, for example in WSL on Windows,
could host boxes. The Docker backend reaches a Docker host through a local
socket or ssh://. On a Windows PC with WSL, SSH needs sshd in WSL, a key,
a port proxy from Windows to WSL and a firewall rule, on each PC. Such a PC
is often a BB machine already: BB’s daemon runs there, in WSL on Windows,
and keeps an outbound connection to BB’s server.
A spike on 1 October 2026 measured bb-box’s host entry from a throwaway
plugin, on a linux-docker box that was a BB machine:
- A host call from bb-box’s server took 424 ms at the median, 2 ms of it
in the machine, and about 0.9 s to a worker that had stopped. A result
holds about 6 MiB of bytes at most. Over SSH,
box_run truetakes about 0.1 s, so calls suit setup, not commands. - BB carries no byte stream between a plugin’s server side and its host entry. Calls and signals together carried 0.12 to 1.1 MiB/s.
- A WebSocket that the worker opens out to a route of bb-box’s own works
today. The route has
auth: "none", and checks a one-time secret that a host call gives the worker. It opened in 0.4 to 0.53 s, echoed in 0.3 ms at the median, and carried 54 to 142 MiB/s. It needs only the outbound HTTPS that BB’s daemon uses. - BB stops a worker after 5 idle minutes unless it holds a lease. A plugin reload ends the worker and its sockets. A call in flight failed in about 3 s when the machine went.
Decision
Build it, in the Docker backend. A Docker host can be a BB machine. It
is neither a backend of its own nor a new transport: bb-box relays Docker’s
API, so the docker CLI on BB’s server drives the machine’s Docker as it
drives a local socket. Containers, labels, docker exec for commands,
copies, the desktop and terminals, Cua’s MCP, capacity, the doctor and the
sweep all work as they are. The backend interface does not change.
The relay.
- For each Docker host that is a BB machine, bb-box’s server listens on a
unix socket that only BB’s user can use, and gives the
dockerCLI that socket as the host. - Each connection to that socket is a channel on one WebSocket for the
machine. The machine’s worker opens the WebSocket out to a route of
bb-box’s, with
auth: "none"and a secret of 128 random bits that a host call gives it. The route accepts each secret once, within 10 s. - The worker connects each channel to Docker as the
dockerCLI there would:DOCKER_HOST, else the current context’s endpoint, else the default socket or named pipe. - Each side of a channel sends only as much as the other side has granted,
1 MiB at first, and grants more as its own socket drains. This keeps a
slow side from filling memory, as BB’s plugin socket gives no
backpressure
(request 2).
Each direction ends on its own, as
docker execanddocker cpclose their input before their output. Frames are at most 64 KiB, and a ping every 15 s finds a dead relay. - The relay opens when a
dockercommand needs it, with one host call. The worker holds a lease while it is open. It stays open while bb-box has a box on the machine or a channel is open, and closes after 5 idle minutes otherwise. - A plugin reload, a deploy or the machine reconnecting ends the relay. The
next
dockercommand opens it again, in about 0.5 s, or about 1 s if the worker had stopped. Containers keep running. Terminals and desktops reconnect, as after any plugin restart.
Which machines. The operator turns on each machine.
- BB Box’s settings list, under Docker, the BB machines that can host boxes: connected, persistent, not made by bb-box, and with Docker answering the host entry. Each row shows the machine’s name, Docker’s version, cores and memory, and a switch.
- bb-box’s own boxes, spares and your machines (036) are BB machines with Docker too (041), so the list leaves out every machine bb-box’s provider made.
- Turning a machine on adds a Docker backend whose host is that machine,
last in acquire order. The configuration names the machine by its BB
machine ID, as
bb:<machine ID>. Its offers and boxes say “Docker on”. Turning it off removes that backend, as for any other. - No machine is used without its switch. A box is a privileged container, root on the machine (041), and takes its memory, so a person decides.
Images. Turning a machine on builds any image it lacks there, with
bb-box’s setup/docker/build.sh run on BB’s server against the machine’s
socket, as docker build sends its files through the API. The row shows
the build until it ends. The doctor gives the same fix when an image is
missing or old. Images are built, not copied, as everywhere now.
A machine that is offline. Capacity reads the machine’s state from BB, with no host call, so an acquire takes the next offer at once. Commands and copies on its boxes fail at once, saying the machine is offline. A release waits as an interrupted release does, and the sweep finishes it when the machine is back. Boxes do not move to another host.
Ruled out.
- A backend of its own, which would repeat the Docker backend’s kinds, images, capacity, doctor and labels.
- Running the
dockerCLI on the machine, with lifecycle in host calls and each process’s input and output relayed, as the spike proposed. Each operation would need a second path, and each lifecycle call would take about 0.5 s. Relaying the API keeps one path and makes one host call each time the relay opens. - BB’s shared ports, which publish a machine’s loopback TCP ports through BB’s gate. Docker’s API is a unix socket, and root on the machine.
- SSH, which stays for Docker hosts that are not BB machines. On a Windows PC it needs the setup above on each PC.
Consequences
- A developer turns their PC on in settings. It needs no SSH, key, port proxy or firewall rule, only BB’s daemon and Docker.
- A
dockercommand costs a few round trips between BB’s server and the machine, and about 0.5 s more when the relay must open first. - bb-box depends on more of BB’s experimental APIs: the host entry,
experimental_retainWorkerandexperimental_websocket, and a route withauth: "none"guarded by a one-time secret. Request 7, extended, would replace the route and the secret. If these APIs change, a Docker host overssh://still works. - BB’s server needs the
dockerCLI, as for any Docker host. The CLI agrees an API version with the machine’s Docker. - With Docker Desktop’s WSL integration, WSL may not reach containers’
addresses. Nothing here needs them: the desktop goes through
docker exec, as now. Before the build ends, a check on a Windows PC with Docker Desktop: the worker reaches Docker’s socket in WSL, a privileged box starts, and a box enrols in BB. - Through Docker, the relay is root on the machine, as an
ssh://host is. It is not a security boundary. - The images are x86_64. On an Arm machine they run under emulation, slowly, and the doctor says so, as now.