Repository navigation
desktop: run the server and worker from the published image instead of building on the host - #852
dustywusty wants to merge 10 commits into
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8995cf09c0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
This is the biggest UX win in the install work: no more host Bun or 20+ minute
Related, but not something this PR needs to fix: our bar is that a non-technical person is never asked to install Docker or WSL, or to run a command. Today a Windows machine without WSL ends on "Open PowerShell as an administrator, run |
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.
…ring" The Start screen showed the wait for /health as a step named "Answering", "waiting for OpenBot to answer". It is the longest step on a cold machine, so name it for what the person is waiting for and say it can take a few minutes the first time.
6023929 to
2547772
Compare
|
Thanks — agree on all of it. Status:
The red |

OpenBot Desktop starts OpenBot's server and worker as containers from the published server image, instead of downloading Bun, running
bun install, building the web app and supervising three host processes. Stacked on #832; needs #851 and a release that includes it.Review the last six commits. The four before them are copies of #851, so this branch can run on top of #832. #851 is now on
main; they drop out of the diff once #832 is updated frommainand this branch is rebased onto it.Today and proposed
Bun is still installed on first use of the self-hosted Intelligence sign-in, the one host script left.
What changes
bun install. The self-hosted Intelligence sign-in helper is the only thing on the host that still runs a Bun script; it now prepares Bun and the packages on first use and reuses them after that.compose up. It is still never written to disk; Compose hands it to theservercontainer only.COMPUTER_NETWORK=<project>_default, so per-Bot computers sit on the server's network. On Linux it also setsOPENBOT_SERVER_USERto the install folder's owner..openbot, then raisesserverandworkerwith the other services./healthon the app and server ports, and stops early if Stop is pressed.env.rs): Bots callhttp://server:3001/api/agent-tools/call. The server getshost.docker.internaladdresses for local Intelligence, and the browser keepslocalhost(via Run OpenBot's server, app and worker from the published server image #851'sINTELLIGENCE_BROWSER_GATEWAY_WS_URL). An installed harness gets its container address.openbotprofile; Compose skips a profile's services unless it is named.servercontainer instead of host pids. Restart runscompose restart server worker.Verification
From
desktop/src-tauri:cargo fmt --checkandcargo clippy --all-targets -- -D warningsare clean.cargo test --lib --bins: 651 and 184 passed. New tests cover container addresses, harness container URL,project_name, the host token reaching Compose atup,COMPUTER_NETWORK, the.openbotfolder, port ownership and the readiness wait.Not run end to end yet. It needs a release whose server image contains the worker (#851).
Open before this can merge
Done: the minimum-release check (163a20d). An install pinned to a release whose Compose file has no
server/workerservice is sent back to Install and moved to the latest release, keeping its data volume andKEY_ENCRYPTION_KEY.Still open:
deployment_problemstill requires theserver/,app/andworker/folders and theservescript.openbot-.host-gatewaycan't reach k3d's127.0.0.1-bound ports on Docker Engine.