BrowserBox Documentation

07 Run & deploy

Setup and Backend Modes

Customer guide · v19.3.1 · September 29, 2026

In this chapter

7.1 bbx setup #

Customer-facing setup shape:

bbx setup [--port|-p <port>] [--hostname|-h <hostname>]
          [--token|-t <token>] [--zeta|-z]
          [--backend <http|https>]
          [--flipbook-record <dir>]
          [--flipbook-description <text>]
          [--for <user>|--for=<user>]
  • --port chooses the main BrowserBox service port.

  • --hostname sets the hostname customers use.

  • --token sets the login token explicitly instead of generating one.

  • --zeta enables host-per-service mode.

  • --backend http|https selects whether BrowserBox itself serves HTTP or HTTPS.

  • --flipbook-record enables flipbook recording (see Section 17).

  • --flipbook-description sets an optional description for the recording.

  • --for runs setup on behalf of an unprivileged user (see Section 9). Both --for <user> and --for=<user> are accepted.

Runtime values are written to:

~/.config/dosaygo/bbpro/test.env

7.2 Login-token lifecycle #

A normal BrowserBox setup has one login token for one configured BrowserBox runtime. Running bbx setup without --token generates a new random token; passing --token uses the supplied value. The selected token is stored in test.env. bbx stop, bbx start, and bbx restart do not rotate it: stop removes the published login.link, and the next start reconstructs the link from the retained runtime configuration. Re-running bbx setup without an explicit token rotates it.

The resulting login link is a persistent connector for that runtime, not a one-time-use link and not an end-user identity. It may be used again to reconnect while the runtime remains valid. Multiple clients that possess the same connector join the same shared browser state, subject to BBX_MAX_CONNECTIONS; this is BrowserBox’s co-browsing model. Use a separate runtime or Fleet allocation wherever users require separate browser state. In Fleet deployments, applications integrate with fleet acquire and fleet release rather than invoking bbx setup directly for each external user.

7.3 Connection types keep their own configuration #

Each way of launching BrowserBox — a plain bbx start (the setup configuration), cf-run, zt-run, tor-run, ng-run, and win9x-run — keeps its own saved configuration. When you switch from one to another, BrowserBox files the current test.env under the type that wrote it and loads the configuration of the type you are starting, printing a line such as Loaded the setup configuration; cf had it last. The saved copies live beside test.env as test.env.profile.<type>.

In practice this means a tunnel run no longer changes how a later plain bbx start behaves. For example, after bbx cf-run (which serves plain HTTP behind the tunnel), bbx start returns to the HTTPS address and login link from your last bbx setup.

Related behavior:

  • bbx restart relaunches with the connection type BrowserBox was last started with, and prints which one it is using.

  • bbx start --port <p> --hostname <h> saves a changed address: BrowserBox stops, re-runs setup with the new address (keeping the token, zeta mode, backend mode, and flipbook settings), then starts. Ports must be between 1024 and 65535.

  • user.env (below) is never part of a saved configuration and always applies on top of whichever type is running.

7.4 Persistent configuration overrides (user.env) #

Running bbx setup regenerates test.env, which overwrites any values you added there directly. To make overrides that survive a re-setup, place them in:

~/.config/dosaygo/bbpro/user.env

BrowserBox sources user.env after test.env every time it starts, so values set there take precedence and are never touched by bbx setup. The file is not created automatically—create it once and it persists indefinitely.

Example:

# ~/.config/dosaygo/bbpro/user.env
# Overrides that survive bbx setup regeneration.
export BBX_MAX_TABS=4
export BBX_SHUTDOWN_IDLE_MS=3600000

Any valid environment variable accepted by BrowserBox may be placed in user.env. The file is loaded by both bbx start (bbx.sh) and the service runner (_conrun.sh).

At service startup, the orchestrator exports every active BBX_* variable together with the standard proxy, CA, and sound-session variables described in Sections 2.7 and 2.8. The main, audio, docs, and DevTools services therefore receive the same relevant startup environment. If user.env contains proxy credentials, restrict it to the service user:

chmod 600 ~/.config/dosaygo/bbpro/user.env

The following profile is a good starting point for high-throughput deployments on well-provisioned hosts. It keeps adaptive imagery enabled so BrowserBox continuously tunes screencast quality and frame cadence to the connection, and keeps WebRTC enabled so BrowserBox can use it when it is the best available transport and fall back to WebSocket when conditions change. On more constrained or high-latency hosts, keep BBX_LOW_END_MODE at its default and tune settings to your workload.

# Keep adaptive quality and frame-rate control active.
export BBX_ADAPTIVE_IMAGERY=true

# Avoid Chrome's forced low-end behavior on adequately provisioned hosts.
export BBX_LOW_END_MODE=false

# Optional when the deployment does not need BrowserBox audio.
export BBX_NO_AUDIO=true

# GPU hosts only; requires working vendor EGL/DRI userspace and permissions.
export BBX_GPU=true

Do not set BBX_DISABLE_WEBRTC=true in this profile. BBX_GPU is an explicit bare-metal hardware opt-in, not an automatic default, and it carries three prerequisites — all of them must hold before the flag is retained in production:

  1. An actual hardware GPU is attached to the machine (for cloud instances, a GPU-equipped shape such as one with an NVIDIA L4 or T4).

  2. The correct vendor drivers and EGL/DRI userspace are installed and the BrowserBox user has permission to access the device.

  3. Chrome on that machine verifies acceleration is live: browse to chrome://gpu inside the BrowserBox session and confirm the Graphics Feature Status entries report green “Hardware accelerated”. If entries report “Software only” or SwiftShader appears as the renderer, the flag is not delivering hardware acceleration and should be removed.

Diagnostic settings such as BBX_DIAG and BBX_CDP_METRICS are intentionally omitted here because they are troubleshooting tools rather than production performance settings.

7.4.2 Cross-origin iframe instrumentation #

Some pages embed third-party content in cross-origin iframes. Chrome may place those frames in separate renderer processes. BrowserBox now attaches to those targets by default so its supported in-frame capabilities remain available:

# Temporary compatibility fallback for a problematic site:
export BBX_OOPIF=false
bbx restart

Keep the default enabled unless diagnosing a specific compatibility issue. Disabling it removes BrowserBox instrumentation from separately rendered cross-site frames. See Section 4.4 for the persistent setting and support guidance.

7.5 Reverse proxy and HTTP backend #

If BrowserBox sits behind nginx, Caddy, or another edge proxy that terminates TLS:

export BBX_EXTERNAL_TLS=true
bbx setup --hostname example.com --port 8888 --backend http

In HTTP backend mode the edge owns public DNS and TLS. BrowserBox does not run its direct-public-IP DNS gate or generate a BrowserBox certificate for that hostname. Internal and split-horizon names are resolved through the host’s configured resolver rather than hard-coded public resolvers.

When installing a new host that will use this topology, export the external-TLS intent before invoking the installer so certificate acquisition is skipped during installation as well:

export BBX_EXTERNAL_TLS=true
curl -fsSL https://browserbox.io/install.sh | bash
bbx setup --hostname example.com --port 8888 --backend http

The older compatibility form is still available:

bbx setup --http-only

7.6 Reverse proxy: preserving service origins (audio and DevTools) #

BrowserBox is a multi-service architecture. In addition to the main browser service, it runs separate services for audio streaming, document viewing, and remote DevTools. These services communicate over distinct ports and require their own origin (hostname + port combination) to function correctly.

When all services are proxied through a single origin, audio and DevTools will stop working. This is a browser security constraint: the audio service uses a protocol that requires a unique origin, and the DevTools bridge is likewise origin-sensitive.

The recommended pattern gives each service its own subdomain, all served over port 443. With a main port of 8888, the four services and their facade hostnames are:

Service Port Derived from Facade hostname
audio 8886 main − 2 p8886.example.com
docs 8887 main − 1 p8887.example.com
main 8888 main p8888.example.com
devtools 8889 main + 1 p8889.example.com

When the first label of the hostname matches p<port>, BrowserBox derives the sibling service origins from it automatically and addresses them on port 443. This behaviour is driven entirely by the URL the client is served from, so it requires no special server mode: a standard --backend http setup behind your own proxy is sufficient.

Users must reach the main service through its facade hostname (https://p8888.example.com/login?token=...). A bare hostname without the p<port> label does not trigger the rewiring, and audio will not function.

Configure BrowserBox to serve plain HTTP behind the proxy, using the parent domain as the hostname:

export BBX_EXTERNAL_TLS=true
bbx setup --hostname example.com --port 8888 --backend http
bbx start

Then publish one virtual host per service. BrowserBox can generate the complete four-service configuration from the saved setup values:

# Inspect or send the configuration to an external edge operator.
bbx ng-config print > browserbox-facade.conf

# Check saved configuration and wildcard certificate coverage.
bbx ng-config validate

# Or install one BrowserBox-owned include, test nginx, and reload it.
bbx ng-config apply

print writes only nginx configuration to standard output and never changes the system. validate is also non-mutating. apply owns only a stable <user>-browserbox-facade.conf include; it writes atomically, runs nginx -t, and restores the prior BrowserBox include if validation or reload fails. It does not delete or rewrite operator-maintained nginx files.

The generated configuration contains one block in the following shape for each of the four ports:

server {
    listen 443 ssl;
    server_name p8886.example.com;      # repeat for p8887 / p8888 / p8889

    ssl_certificate     /path/fullchain.pem;
    ssl_certificate_key /path/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8886;   # matching backend port
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # required: audio and DevTools use WebSockets
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # required: streaming must not be buffered or timed out
        proxy_buffering off;
        proxy_read_timeout 3600s;
    }
}

Requirements for this layout:

  • DNS resolves each p<port>.example.com name to the proxy.

  • The TLS certificate covers every facade hostname; a wildcard *.example.com satisfies this.

  • The Upgrade and Connection headers are forwarded, and proxy_buffering is off. Without these the audio stream will not establish.

  • If your facade hostnames are long, nginx may report could not build server_names_hash. Raise it in the http block: server_names_hash_bucket_size 128;

Where you prefer the existing all-in-one nginx workflow, see bbx ng-run (Section 8.2). Use ng-run when BrowserBox should own route generation and startup together; use ng-config when an operator or external edge owns nginx lifecycle.

7.6.2 Direct multi-port exposure (alternative) #

If DNS subdomain routing is not available, expose each port directly from the edge without rewriting the request to a shared origin. Each port must be reachable as its own origin from the client browser.

7.6.3 Audio connects but is silent #

If bbx status reports Audio: Degraded, or the client reports that audio is connected but nothing is heard, check the capture side in order:

  1. Is a sound server reachable for the service user? Run pactl info as that user. If it fails, the user has no active session — see Section 2.8.

  2. Is the BrowserBox capture source present? Run pactl list short sources as the service user and confirm that rtp.monitor is listed. On a PipeWire host, if only auto_null.monitor appears, run browserbox --install to reapply the command-install assets, then stop and restart the BrowserBox runtime so pipewire-pulse reloads its configuration.

  3. Is the browser feeding it? With a page playing sound, run pactl list short sink-inputs. An active stream should be listed. On PipeWire, the stream should use the channel sink. If the list is empty, the browser is not rendering into the sound server.

  4. Was the browser started inside the service user’s session? A browser process started outside that session cannot reach the sound server and will render to a null output. Run bbx stop; it terminates Chrome roots owned by the BrowserBox profile while leaving unrelated personal Chrome processes untouched. Then start BrowserBox again from the service user’s session.

7.6.4 Minimal mode (no audio or DevTools) #

For environments where audio and DevTools are not needed, run in minimal mode to avoid starting those services entirely:

export BBX_MINIMAL_MODE=true
bbx start

7.7 External TLS hint #

If BrowserBox is behind an edge that terminates HTTPS and BrowserBox itself is serving plain HTTP, the runtime can be told to treat the frontend as secure:

export BBX_EXTERNAL_TLS=true
bbx start

This is useful when a reverse proxy or cloud edge is doing TLS termination for customer traffic.

BrowserBox · Published by DOSAYGOHappy browsing.