diff --git a/.env.example b/.env.example index 310e88f23..40d249058 100644 --- a/.env.example +++ b/.env.example @@ -343,6 +343,13 @@ COMPUTER_TOKEN= # credentialed proxy here is an operator's decision. # COMPUTER_SHELL_ENV=JAVA_HOME,GOPATH +# The address the computer listens on. Unset, a managed computer listens on every interface, which +# a container needs. A computer run straight on a laptop (`bun run dev` in agent-computer) is then +# reachable from the local network too; its API needs the computer token, but nothing else needs to +# reach it, so set 127.0.0.1 there. A computer driving a native Chrome (OpenBot Desktop's) always +# listens on loopback, whatever this says. +# COMPUTER_BIND=127.0.0.1 + # --------------------------------------------------------------------------- # The computer's profile and where its traffic leaves from # --------------------------------------------------------------------------- diff --git a/CHANGELOG.md b/CHANGELOG.md index 54c57cadc..989045d58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,6 +84,14 @@ The built-in safety rules hand paying, purchasing or moving money to you, but a (such as `SHOPIFY_CREATE_REFUND`) passed straight through: "refund" was not one of the words the rule looked for. It is now, so issuing a refund is handed to you like any other movement of money. +### A computer run on a laptop can stay off the local network + +A managed computer listens on every network interface, which a container needs. Run straight on a +laptop with `bun run dev`, that left its token-protected API reachable from the local network. +`COMPUTER_BIND` now chooses the address it listens on: set `COMPUTER_BIND=127.0.0.1` to keep it to +the machine itself. Unset, nothing changes, and a computer driving a native Chrome (OpenBot +Desktop's) still always listens on loopback. + ### A computer closes browsers nobody is using when its memory runs high A computer runs one browser for each Bot that is browsing, and the only limits were a count and half diff --git a/agent-computer/src/browser-runtime.ts b/agent-computer/src/browser-runtime.ts index 032905ecf..bdff7b1cd 100644 --- a/agent-computer/src/browser-runtime.ts +++ b/agent-computer/src/browser-runtime.ts @@ -5,7 +5,7 @@ export type BrowserRuntime = { channel: "chromium" | "chrome"; mode: BrowserMode; useVirtualDisplay: boolean; - hostname?: "127.0.0.1"; + hostname?: string; allowExec: boolean; }; @@ -21,6 +21,9 @@ export function browserRuntimeFromEnv( ); } const local = backend === "local-chrome"; + // Where the HTTP process listens. Native Chrome always listens on loopback. A managed computer listens on every interface unless COMPUTER_BIND names an address, + // so a computer that runs on a person's own machine (not in a container) can be kept off the network: COMPUTER_BIND=127.0.0.1. + const bind = env.COMPUTER_BIND?.trim(); /* * Headed wherever a hosted computer runs, which is Linux: a container, a Kubernetes pod, the * desktop app's Podman machine. Headless Chromium is the browser bot checks are best at spotting @@ -45,7 +48,7 @@ export function browserRuntimeFromEnv( channel: local ? "chrome" : "chromium", mode, useVirtualDisplay: platform === "linux" && mode === "headed", - ...(local ? { hostname: "127.0.0.1" as const } : {}), + ...(local ? { hostname: "127.0.0.1" } : bind ? { hostname: bind } : {}), allowExec: !local, }; } diff --git a/agent-computer/tests/browser-runtime.test.ts b/agent-computer/tests/browser-runtime.test.ts index 94d1f2998..f65736bc2 100644 --- a/agent-computer/tests/browser-runtime.test.ts +++ b/agent-computer/tests/browser-runtime.test.ts @@ -13,6 +13,16 @@ describe("the configured browser runtime", () => { }); }); + test("a managed computer listens on every interface unless COMPUTER_BIND names one", () => { + expect(browserRuntimeFromEnv({}, "linux").hostname).toBeUndefined(); + expect( + browserRuntimeFromEnv({ COMPUTER_BIND: " 127.0.0.1 " }, "win32").hostname, + ).toBe("127.0.0.1"); + expect( + browserRuntimeFromEnv({ COMPUTER_BIND: "127.0.0.1" }, "win32").allowExec, + ).toBe(true); + }); + test.each(["darwin", "win32"])( "managed %s, a developer's own machine, stays headless", (platform) => {