Repository navigation
desktop: install Podman when a machine has no engine, and run Intelligence on the same engine - #862
Draft
dustywusty wants to merge 10 commits into
Draft
dustywusty wants to merge 10 commits into
dustywusty wants to merge 10 commits into
Conversation
The server image already carries the API and the built app. Add worker/src and its node_modules (the isolated install's link to @openbot/shared), so the same published image can run the worker with `bun ../worker/src/index.ts`. Nothing uses it yet; this is step 1 of running OpenBot Desktop's server, app and worker as containers instead of building them on the customer's machine.
OpenBot's own server (the API and the built app it serves) and the routines worker, from the published server image, behind an `openbot` profile so scripts/start.sh and a plain `docker compose up -d` keep running them on the host as before. The server reads the same .env a host server does, with every address overridden to a service on the compose network, PORT and SERVER_PORT both pinned to 3001 (the server refuses to start when they disagree), NODE_ENV cleared so a local OpenBot may still reach private addresses, and the app and server host ports both mapped to it on loopback. The worker gets its three settings and sits on the data network only. Bots keep their host.docker.internal tool URL by default; whoever starts the server service points them at server:3001.
The runtime sends the browser the gateway's /client socket in /info, and the browser opens it itself. A server in a container reaches local Intelligence at host.docker.internal, which the browser on the host cannot resolve, while the browser's localhost is the container from inside it. INTELLIGENCE_BROWSER_GATEWAY_WS_URL, when set, is the address /info (and a trajectory grant) gives the browser; the server's own runner and channel sockets stay on INTELLIGENCE_GATEWAY_WS_URL. The compose server service sets it to the deployment's own gateway URL and reads its container address from INTELLIGENCE_CONTAINER_GATEWAY_WS_URL.
A Google or xAI sign-in leaves .openbot/model-oauth.json on the host, and the server reads and renews it itself (temp file plus rename, and a .lock folder beside it), so the folder is bind-mounted rather than the file. Not created by Compose, which would make it root-owned on Linux. The user is settable so the Linux desktop can run the server as the host user who owns that 0600 file.
…n addresses SERVICES now includes server and worker, and Stop names the openbot profile they sit behind. The settings point every Bot at server:3001, give the server host.docker.internal addresses for local Intelligence (the browser keeps the localhost ones), and give an installed harness its container address. The macOS Podman overlay publishes the server's two ports on IPv4 only.
… host Start now hands everything to Compose and waits for the `server` container to answer `/health` on both the app and API host ports, for up to 180 s. Docker's restart policy supervises the server and worker, so the host launch, readiness, pid recording and restart loop are gone. - The desktop host token is minted before `up` and reaches Compose, which names it for the server alone; it is still never persisted. - COMPUTER_NETWORK is `<compose project>_default` (new `stack::project_name`), so Bot computers join the server's network. On Linux OPENBOT_SERVER_USER is the deployment folder's uid:gid. - `.openbot/` is created before `up`, since its bind mount does not create it. - App and server ports count as ours when our container publishes them; the pre-spawn port check is gone. - Ownership for showing, restoring and asking OpenBot is now "this root's server container publishes the ports" (`stack::server_publishes`), not recorded host pids. - Status lists server and worker as containers; Restart runs `compose restart server worker`. - What is left of the supervisor polls the server for refused connections (`watch_connections`). - Start no longer requires the host Bun or packages. - Old Bun host processes from earlier installs are still stopped on Start and Stop, which is how an upgrade frees 3001/3010. Also brings tests left stale by the previous commit up to date (server/worker in the up list, `--profile openbot` on down).
Installing OpenBot is now pulling images. Bun and bun install are prepared only when somebody starts the self-hosted Intelligence sign-in, the one thing on the host that still runs a Bun script, and reused after that.
Rootless Podman maps container root to the person who started it and any other uid to one of their subordinate ids, so passing the owner's uid:gid made the server a stranger to the owner-only .openbot sign-in folder. Docker keeps the owner's numbers; Podman now gets 0:0.
A release from before the server and worker were Compose services has no server or worker to raise, and its server image has no worker, so keeping its pin left a working installation unable to start. Such a deployment now reads as needing installation, Install resolves the latest release instead of repairing the old pin, and if even the latest still runs the server on the host the app says so rather than failing inside Compose.
…n Intelligence on the same engine Docker Desktop's licence needs a paid subscription at larger companies, so a Mac or Windows machine with no engine now gets Podman instead of Docker Desktop. Docker is still used whenever somebody has it: an answering Docker as it is, an installed Docker Desktop is started, a Podman somebody has is used, and a stopped OrbStack or Colima is left for its owner to start. Docker Desktop's installer is kept. The step row says when macOS will ask for a password, and on Windows that Podman may offer to install WSL behind an administrator prompt and a restart. Local Intelligence's k3d needs rootful Podman (CopilotKit/Intelligence#2147), so the machine OpenBot creates is `--rootful`, and OpenBot addresses it through its `<name>-root` connection, the rootful engine, both for its own machine and for a running machine it adopts. On a rootful Windows machine the host-gateway setting goes to the system configuration. An existing rootless machine is never switched, ours included: its OpenBot lives in the rootless engine's storage, which the rootful engine does not see. Local Intelligence setup and start decline there instead, with a new `rootless-podman` failure whose row names `podman machine set --rootful`. Every Intelligence CLI process gets COPILOTKIT_LOCAL_ENGINE for the engine OpenBot runs on, recorded when the engine is ready and when Start pins it (or detected, before either). For a Podman machine it also gets CONTAINER_HOST and DOCKER_HOST naming the machine's forwarded API, drops an inherited DOCKER_CONTEXT, and has Podman's directory on PATH. The window's runtime row no longer says Docker Desktop.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
OpenBot Desktop installs Podman, not Docker Desktop, on a machine that has no container engine, and runs local Intelligence on the same engine. Docker Desktop's license needs a paid subscription at larger companies; Podman is Apache 2.0 and has no license window. Docker is still used whenever the machine has it. Stacked on #852.
Needs a CLI release with CopilotKit/Intelligence#2147, which teaches local Intelligence to run on rootful Podman. Until then, the CLI refuses Podman.
What changes
Engine choice (
install.rsinstall_engine_with), macOS and Windows:dockerthat isn't Docker Desktop → ask the person to start it.Docker Desktop's install code stays. The install step names the prompt honestly: on macOS, "Enter your Mac password when macOS asks for it". The Windows MSI installs per user. If WSL is missing, the Windows row says Podman will offer to install it, and Windows then asks for administrator approval and a restart.
Rootful Podman machine (
acquire.rs,engine.rs).podman machine init --rootful, because local Intelligence's k3d needs rootful.openbot-root). On the bare name, its containers would land in the rootless engine, and the supervisor's Docker socket mount would fail.Existing rootless machines are not switched. A rootless machine keeps its containers and volumes in rootless storage, which the rootful engine can't see. Switching would bring OpenBot back on an empty database, and releases up to 0.2.0 created
openbotrootless. Instead, local Intelligence refuses on a rootless machine with a row saying how to switch (Failure::RootlessPodman). Open question: following that advice also hides the machine's existing OpenBot data, so the wording, or a migration, needs a decision.One engine for both (
local_eval.rs). Every Intelligence CLI process getsCOPILOTKIT_LOCAL_ENGINE=docker|podman, matching the engine OpenBot runs on. Every process starts through one function. On Podman it also getsCONTAINER_HOST/DOCKER_HOSTset to the machine's API socket (Unix socket or named pipe), drops any inheritedDOCKER_CONTEXT, and has Podman on itsPATH. Nothing secret is added.Readiness text (
localReadiness.ts) no longer says "Docker Desktop".Verification
desktop/src-tauri:cargo fmt --checkandcargo clippy --all-targets -- -D warningsare clean.cargo test --lib --binspasses: 666 lib and 185 bin tests.desktop: Biome is clean, andbun testhas 275 pass.Not verified: needs a live run
.openbot/model-oauth.json(the server runs as uid 1001; whether Podman's file sharing on macOS, or WSL's on Windows, lets it read the person's 0600 file is untested);host.docker.internal;COPILOTKIT_LOCAL_ENGINE=docker.local setupstarting before the engine is ready.