Run Auto Browser locally with Docker, verify its controller, and understand the remote-access security boundary
Auto Browser gives an agent and a human operator access to a shared Playwright browser. This guide covers a local Docker deployment, authenticated REST checks, local noVNC takeover, and practical maintenance. It does not provide a validated remote noVNC or MCP-client deployment: the available documentation does not establish the complete public-host, gateway, Origin, and WebSocket configuration. We explain where a Localtonet HTTP tunnel fits, but keep both application ports unpublished until that security boundary is established.
๐ What's in this guide
What this guide establishes, and what it does not
This article concerns LvcidPsyche/auto-browser on GitHub, not the similarly named Chrome extension. The Docker project combines a browser controller with a browser-node component. Its local interface includes a dashboard, REST API, an HTTP MCP endpoint, and a noVNC page for human takeover.
A real browser can render JavaScript applications, retain login state, and allow a person to recover a workflow that automation cannot complete. That flexibility also makes the deployment sensitive. A controller credential can grant authority over a browser, while a takeover connection can expose whatever is visible in its desktop. Use a disposable browser session and a harmless page during installation, not an account containing production data.
Why the scope stops at localhost
noVNC uses WebSockets to carry desktop traffic. Auto Browser's security release also describes an Origin check at this boundary. The available evidence does not establish Localtonet HTTP-tunnel WebSocket behavior for this application, the project's supported public-Origin configuration, its public takeover URL settings, or the complete gateway recommendations. A successful HTTP page load would therefore be insufficient evidence for a working, protected takeover connection.
The same caution applies to publishing the controller. A forwarding client on the Docker host may reach the application over loopback even when the original caller is remote. A loopback deployment setting must not become an authorization shortcut for those callers. We do not supply an off-box configuration or a remote MCP-client recipe without the missing primary documentation.
Do not create tunnels to ports 8000 or 6080 as part of this procedure. Do not disable Origin checks, enable tokenless access, or restore raw VNC publishing to make remote access work. The remote-access section is an acceptance checklist, not an instruction to publish an unverified deployment.
Prerequisites and release selection
Use a machine you control with Docker Engine or Docker Desktop, the Docker Compose plugin, Git, and a browser that can reach the Docker host's localhost ports. The command examples use Bash. They also use curl, jq, and standard Unix utilities. On Windows, run them in an appropriate Bash environment with Docker access rather than pasting Bash arrays into PowerShell.
docker version
docker compose version
git --version
curl --version
jq --version
Docker must be running, and your account must be permitted to use it. Access to the Docker daemon is powerful host access; use a trusted machine and do not grant it to untrusted users just to complete this tutorial. Ports 8000 and 6080 must be available. Installation needs network access to fetch the repository, container dependencies, and the example web page.
The supplied evidence does not establish a supported operating-system matrix, minimum memory, or a required Docker version. The published-image workflow described in the existing project material targets linux/amd64. Do not assume ARM support or emulation compatibility. A source build is not, by itself, proof that every browser dependency supports another architecture.
A reproducible baseline is not a current security recommendation
The primary release evidence supplied for this revision verifies Auto Browser v1.11.2, a historical security release. It does not identify today's stable release. Accordingly, the commands below pin that known tag for a disposable, local-only lab. We do not label it current, recommend it for production, or imply it contains all later fixes.
For any ongoing deployment, select a current stable version from the project's releases, review intervening security notes, and record its exact commit and image digests. If you cannot establish a supported current release, stop before putting sensitive accounts into the browser. Neither an unpinned main checkout nor a floating latest image solves that verification problem.
The historical v1.11.2 fixes matter because they span both components: the controller receives application fixes, the browser-node image receives the VNC fix, and the Compose configuration stops publishing port 5900. Updating only a client library or MCP bridge does not deploy those server-side protections.
Install a local-only Docker lab
The basic project workflow is clone, configure if needed, optionally run diagnostics, and build with Compose. Here we add an explicit release pin and configuration inspection before startup. The repository's base Compose file and environment example are useful contextual references, but the files in your pinned checkout govern the deployment you actually run.
Fetch the historical lab release
Clone the repository at v1.11.2 and record the resulting commit. Keep this lab separate from an existing installation.
Prepare and inspect the environment
Copy the example environment file, keep tokenless mode disabled, and retain loopback-only published ports. Do not add a tunnel or a gateway overlay.
Run the optional diagnostic check
If Make is installed, run make doctor from a normal terminal with Docker access and permission to open localhost sockets.
Build and start the stack
Start the services from the pinned checkout. Inspect their state and logs before proceeding.
Confirm the controller credential exists
With the default authenticated loopback setup and no explicit bearer token, the controller generates data/api-token. Treat that file as a secret.
git clone --branch v1.11.2 --depth 1 \
https://github.com/LvcidPsyche/auto-browser.git auto-browser-lab
cd auto-browser-lab
git rev-parse HEAD
umask 077
cp .env.example .env
chmod 600 .env
# Inspect locally. Resolved configuration may contain secrets.
docker compose config
# Optional, if Make is available:
make doctor
docker compose up --build -d
docker compose ps
docker compose logs --tail=100
# Check without printing the token.
test -s data/api-token && printf 'API token file exists\n'
Review the resolved port mappings before startup. Published application ports should bind to 127.0.0.1, not 0.0.0.0 or a LAN address. There should be no published port 5900. A browser-node service may use internal container networking without making that service available on the host; distinguish internal ports from published host ports.
Do not copy resolved Compose output into a public ticket. It can contain environment values, credentials, filesystem paths, and other operational details. If the token file does not appear, inspect startup errors and whether an explicit API_BEARER_TOKEN or alternate token file is configured.
Prebuilt-image alternative
The project also describes a GHCR image overlay. To reproduce the historical lab with that path, use the same pinned repository checkout and explicitly select the matching image tag instead of accepting the floating default:
export AUTO_BROWSER_IMAGE_TAG=1.11.2
docker compose -f docker-compose.yml \
-f docker-compose.images.yml pull
docker compose -f docker-compose.yml \
-f docker-compose.images.yml up -d
Choose either the source-build path or the image-overlay path and keep using that configuration for status, shutdown, updates, and recovery. The controller's prebuilt image omits agent command-line tools; the documented source-build alternative for CLI authentication uses INSTALL_AGENT_CLIS=true. That optional integration is outside this local REST tutorial.
Optional isolated sessions introduce another image dependency. In that workflow, docker-compose.images.yml must come after docker-compose.isolation.yml, otherwise the isolation overlay can select a stale or nonexistent local browser-node image. Isolation is not needed for the basic lab here.
Verify authentication, the browser, and local takeover
| Interface | Local address | Verification goal |
|---|---|---|
| API documentation | http://127.0.0.1:8000/docs | Inspect the local API; authorize requests with the controller token. |
| Dashboard | http://127.0.0.1:8000/dashboard | Enter the token when requested and inspect the operator interface. |
| MCP endpoint | http://127.0.0.1:8000/mcp | Endpoint location only. This guide does not configure or validate an MCP client. |
| noVNC | http://127.0.0.1:6080/vnc.html?autoconnect=true&resize=scale | Connect to the desktop and observe the test browser session. |
Use a credential without putting it in shell history
A literal bearer token in a shell command can remain in history. Expanding a token into curl's command-line arguments can also expose it through process inspection. The following Bash example stores the header in a private temporary file and tells curl to read it. It avoids printing the credential, although the file still needs protection and cleanup.
# Run from the project directory in Bash.
# Do not run with shell tracing enabled.
set +x
umask 077
AUTH_FILE=$(mktemp)
trap 'rm -f "$AUTH_FILE"; unset TOKEN' EXIT
# For the default generated-token setup:
TOKEN=$(cat data/api-token)
# If you configured your own token, use this instead:
# IFS= read -r -s -p 'API token: ' TOKEN
# printf '\n'
printf 'Authorization: Bearer %s\n' "$TOKEN" > "$AUTH_FILE"
unset TOKEN
On a shared host, a private temporary file does not protect secrets from an administrator or a compromised account. Do not record the terminal session, enable curl tracing, or upload diagnostic bundles containing credentials.
Check refusal before creating a session
Use the observation path with a deliberately nonexistent session ID to test authentication without requesting a browser action:
curl -sS -o /dev/null -w 'No credential: %{http_code}\n' \
http://127.0.0.1:8000/sessions/auth-check-nonexistent/observe
curl -sS -o /dev/null -w 'Wrong credential: %{http_code}\n' \
-H 'Authorization: Bearer deliberately-invalid' \
http://127.0.0.1:8000/sessions/auth-check-nonexistent/observe
Expect an authentication refusal, normally 401, rather than an authorized observation. A generic error alone is not proof that authentication is enforced. If the application accepts unauthenticated protected requests, stop and inspect tokenless mode and the resolved environment before continuing.
Create and observe a harmless session
curl --fail-with-body -sS \
--header @"$AUTH_FILE" \
-H 'Content-Type: application/json' \
-X POST http://127.0.0.1:8000/sessions \
-d '{"name":"local-demo","start_url":"https://example.com"}' | jq
Copy the session ID from the JSON response. Then request an observation:
read -r -p 'Session ID from the response: ' SESSION_ID
curl --fail-with-body -sS \
--header @"$AUTH_FILE" \
"http://127.0.0.1:8000/sessions/$SESSION_ID/observe" | jq
A successful result verifies more than a listening socket: the credential was accepted, the controller created a session, and the browser node could produce an observation. If your curl version lacks --fail-with-body, use --fail and inspect errors separately.
Verify local noVNC separately
Open the local noVNC URL from the table. Confirm that the desktop connects and that you can see the browser showing the test page. The historical release notes state that noVNC requests VNC_PASSWORD when one is configured. Set a separate value through the checkout's environment configuration if you want to verify that behavior, recreate the affected containers, and test both an incorrect and the correct password.
The supplied evidence does not establish the password backend's length rules or a complete public-host configuration. Do not treat this password as authorization to publish the desktop. A local successful connection validates only the local path and its configured password behavior.
When finished with the API checks, remove the temporary header file:
rm -f "$AUTH_FILE"
unset AUTH_FILE SESSION_ID
trap - EXIT
Understand the authentication and exposure boundaries
The available production-hardening specification states that API_BIND_SCOPE=exposed requires an API bearer token of at least 32 characters, with an alternate token-file mechanism available. The base Compose deployment declares loopback scope to match its loopback publishing and can generate a token automatically.
These are two different ideas: a Docker host binding controls where a socket is reachable, while application bind scope controls application security behavior. Keeping the Docker mapping on localhost does not make tunneled traffic local in the security sense. Conversely, changing an application setting does not automatically change Docker's published addresses.
API_ALLOW_TOKENLESS_LOOPBACK=true removes the credential requirement in the described local mode. Other containers can then drive the browser, and a forwarding process may make remote requests arrive from a locally trusted address. Keep authentication enabled even in the lab.
For a future exposed deployment, a long random API token, explicit exposed semantics, and preserved authorization headers are necessary requirements, not a complete hardened configuration. The supplied hardening excerpt is truncated, and the full gateway configuration has not been established here. Merely placing a variable in .env is also insufficient if the Compose service does not consume it or overrides it.
Keep credentials out of URL fragments, screenshots, chat messages, and repositories. Although a fragment is not normally sent in an HTTP request, it can still appear in history or screen captures. Paste the dashboard credential into its prompt instead of bookmarking a token-bearing URL.
Approvals are not a replacement for authentication
The v1.11.2 release explains that an approval is spent when a call claims it, before the action runs. If the action subsequently fails, do not assume it had no effect. Observe the page or check the external outcome before approving another attempt. Retrying with the same spent approval is intentionally refused.
Only qualifying browser actions that stop before beginning return approval, and the response identifies this with approval_given_back. If the session has closed, request a new action in a live session rather than attempting to reuse that session's approval. A rejection after the action begins is too late to cancel it and is refused.
When crossing the v1.11.2 upgrade boundary, old governed-tool approvals must be requested again. Old pending entries shown as takeover requests should be rejected. The release also describes subtleties with AUTONOMOUS_APPROVALS=true; keep autonomous approval disabled unless you deliberately accept those semantics. The project's MCP-client and approval documentation is the relevant integration reference, but this guide does not claim a configured MCP client.
What must be established before remote access
Our platform uses a client on a device that can reach the target service. That client establishes an outbound connection to a Localtonet relay, avoiding inbound router port forwarding. HTTP tunnels provide a public HTTPS address. They are available only while the chosen device is connected and the tunnel is running.
A client running directly on the Docker host can reach host-loopback ports. A client in a separate container cannot use its own 127.0.0.1 to reach the host. Moving the client to another LAN machine also does not make a loopback-only service reachable. Do not broaden the application's binding as an improvised fix.
For general HTTP setup, our HTTP tunnel documentation is the authoritative workflow. Process Types include Random Sub Domain, Custom Sub Domain, and Custom Domain; available device tokens and relay servers come from the current dashboard. Creating a tunnel is separate from pressing Start. We do not reproduce an exact field-by-field sequence here because the current HTTP setup page was not included in the supplied evidence and this narrowed guide does not create a tunnel.
Required acceptance checks for a future deployment
- Controller configuration: establish how the selected release declares exposed scope while retaining a strong API credential and protected endpoints.
- Gateway behavior: incorporate the supported recommendations from the project's deployment documentation, including relevant forwarded-header and public-host handling.
- Negative authentication: prove that missing and incorrect credentials fail through the public path, not just on localhost.
- Desktop transport: verify the complete noVNC WebSocket upgrade, sustained interaction, and reconnect behavior through the selected tunnel.
- Origin enforcement: verify that the supported public Origin succeeds and an unapproved Origin fails. Do not remove the check.
- Password behavior: verify incorrect-password refusal and correct-password success through the complete desktop path.
- Public links: establish supported takeover URL configuration rather than distributing localhost links or inventing environment variables.
- MCP integration: validate one named client's documented configuration, authentication, initialization, tool discovery, and actual operation.
Until those requirements are satisfied, neither a second tunnel to 6080 nor a controller tunnel to 8000 is part of this tutorial. Our McpNet Gateway guide describes a separate integration; it is not evidence that Auto Browser's MCP server or noVNC path has been validated.
Routine operation, updates, rollback, and secrets
Start, inspect, and stop
# Source-build configuration:
docker compose up -d
docker compose ps
docker compose logs --tail=100
# Stop without removing containers:
docker compose stop
# Remove the stack's containers and networks:
docker compose down
For the prebuilt workflow, include the same two -f arguments and selected image tag every time. Do not add down -v casually: it can delete Compose-managed volumes. Ordinary shutdown is not a backup, and the exact storage inventory must be checked before destructive operations.
The data directory contains sensitive state, including the generated token in the default workflow. Saved authentication profiles can represent signed-in sessions. Restrict access, encrypt backups appropriately, and avoid public synchronization destinations. Do not assume that ignoring a file in Git protects it from backup tools or local users.
Use explicit manual startup until boot behavior is verified
This tutorial uses manual startup. After a host reboot, start Docker, enter the same checkout, select the same configuration, run up -d, and repeat the local checks. Do not promise automatic availability without testing an actual reboot.
The repository includes ops/systemd, but the available evidence does not establish its unit names, installation commands, or service dependencies. We therefore do not invent a systemd installation. An unattended deployment requires review of those units, persistent storage, restart policy, and secret availability before it can be considered operationally complete.
Update both server components
Before updating, stop new work, close active sessions, record the current commit and image identifiers, and take a consistent backup with the stack stopped. Include the configuration and all configured persistent storage, not just the source checkout. Protect that backup as carefully as the live credentials.
git rev-parse HEAD
docker compose images
docker compose stop
# Fetch release tags without switching to an unpinned branch.
git fetch --tags
read -r -p 'Reviewed release tag to deploy: ' TARGET_RELEASE
git checkout --detach "$TARGET_RELEASE"
# Source-build path: rebuild both components from the selected checkout.
docker compose build --pull
docker compose up -d --force-recreate
docker compose ps
The tag prompt is intentional: no current stable release has been verified in the supplied evidence. Select a reviewed release, not an arbitrary tag. For prebuilt deployments, select its matching AUTO_BROWSER_IMAGE_TAG, pull with the image overlay, and recreate the services using the same overlay. Record the pulled digests; a version label alone is not necessarily immutable.
Review changes to Compose and environment files during the upgrade. If ISOLATED_BROWSER_IMAGE is explicitly set, update it to the matching reviewed browser-node image. Close old isolated sessions and recreate their containers so they cannot continue using a vulnerable image. Re-run both authenticated and rejected-request tests after the upgrade.
Rollback means restoring a compatible set
Keep the previous reviewed source commit or image digests, configuration, and pre-upgrade data snapshot together. If the new version fails, stop it first. Restore that compatible set, recreate the stack, and verify locally before resuming work. Do not assume a new release's data is backward-compatible with an older controller.
No automatic migration reversal or project-specific rollback command is established here. If release notes do not confirm downgrade compatibility, restore the pre-upgrade snapshot rather than running old code against modified state. Never roll back to a release with a known security flaw simply to restore remote connectivity.
Rotate credentials after suspected exposure
First stop any existing tunnels and stop the application. Replace an explicitly configured bearer token using a protected editor or your secret-management process, not a literal shell command. Recreate the services that consume it, update authorized callers, and verify that the old token fails and the new one succeeds. Update a configured VNC password separately and test it locally.
The supplied evidence does not establish a hot-rotation API or the complete generated-token replacement procedure. Do not assume deleting data/api-token while the service runs revokes an in-memory credential. Keep the service stopped until the selected release's credential source and restart behavior are understood. If browser session state may have leaked, revoke affected website sessions as well; changing the controller token does not revoke website cookies.
For any separately validated Localtonet deployment, stopping or deleting its tunnel belongs to lifecycle operations, not creation. Stop the tunnel when remote work ends. Stopping public forwarding does not stop the local containers or erase their data.
Troubleshooting without weakening controls
| Symptom | Likely area | Safe next step |
|---|---|---|
| Docker commands fail | Daemon or permissions | Confirm Docker is running and the terminal has authorized Docker access. |
| make doctor fails in a sandbox | Local socket restrictions | Run from a normal terminal on the Docker host. Do not disable host security globally. |
| 8000 or 6080 is already in use | Port conflict | Identify the owner and stop the conflicting service if appropriate. Avoid improvised remapping. |
| Protected API calls return 401 | Credential mismatch | Check whether the deployment uses a generated file or an explicit bearer token. Recreate the temporary header file from the correct source. |
| Unauthenticated protected calls succeed | Authentication configuration | Stop the stack and inspect tokenless settings and resolved configuration. Do not publish it. |
| Controller refuses startup | Configuration or secret validation | Read local logs. Exposed scope requires a bearer token of at least 32 characters. |
| Documentation page is blank | Swagger asset loading | The described UI loads assets from cdn.jsdelivr.net. Check browser access or use curl for the local tests. |
| Session creation works but observation fails | Browser-node or target access | Inspect both services' logs and verify the harmless target page is reachable. |
| Raw VNC on 5900 refuses connections | Intentional security change | Use local noVNC on 6080. Do not republish 5900. |
| noVNC HTML loads but desktop does not | Desktop transport or authentication | Check local password behavior and service logs. HTML delivery alone does not validate WebSockets. |
| Prebuilt image fails on ARM | Image architecture | Use a supported image architecture; ARM compatibility is not established here. |
| An approved action cannot be retried | Spent approval | Check whether the action already took effect before requesting another approval. |
Debug in layers: container startup, listening ports, authentication, session creation, observation, and desktop interaction. Record the first failing layer. Do not add a tunnel to fix a service that fails locally, and do not interpret a gateway or transport error as a reason to remove authorization.
Frequently asked questions
Does this guide provide working remote noVNC access?
No. It validates local controller and desktop behavior. The complete public-host, Origin, password, gateway, and WebSocket path is not established by the available evidence, so remote noVNC publication is excluded.
Is v1.11.2 the recommended current release?
No. It is a verified historical security release used as a reproducible disposable-lab baseline. A current stable release was not established here. Review current releases before any ongoing or sensitive deployment.
Does localhost binding make a tunneled controller private?
No. A forwarding process can make a loopback service remotely reachable. Preserve application authentication and establish the supported exposed-scope and gateway configuration before publication.
Where is the default controller token?
In the described default authenticated loopback deployment, the controller generates data/api-token. An explicitly configured bearer token or alternate token file changes the credential source. Do not print the token into logs or place it in command history.
Does a successful REST request validate an MCP client?
No. It validates that REST path and its credential. MCP requires a supported client configuration and protocol-level testing. This guide deliberately does not promise a completed MCP integration.
Is a Localtonet HTTP tunnel a VPN?
No. An HTTP tunnel publishes an individual HTTP service. Our VPN Manager is the separate private mesh VPN feature. Neither connectivity model removes the need to secure a browser controller and desktop.
Establish the local boundary before adding remote connectivity
Finish the local authentication and browser checks first. When your application's supported gateway and public-host configuration is established, use our HTTP tunnel documentation to plan a controlled Localtonet deployment without inbound router port forwarding.
Explore HTTP tunnel configuration โ