helm

Browserless Helm Chart

Deploy Browserless on Kubernetes with Browserless v2 defaults, token authentication enforcement, and image presets for multiple browsers.

Features

Prerequisites

Install

helm repo add icoretech https://icoretech.github.io/helm
helm repo update
helm upgrade --install browserless icoretech/browserless \
  -n browserless --create-namespace \
  --set config.token="replace-me"

OCI:

helm upgrade --install browserless oci://ghcr.io/icoretech/charts/browserless \
  -n browserless --create-namespace \
  --set config.token="replace-me"
config:
  token: null
  tokenSecretRef:
    name: browserless-auth
    key: token

Browser presets

image:
  browser: firefox
  # repository: ghcr.io/browserless/firefox # optional explicit override
  # tag: v2.57.0                 # optional override

Strict Token Authentication

Set config.strictTokenUse=true to require the configured token on HTTP and WebSocket routes that normally opt out of authentication, including direct page connections. Static files remain public so debugger and DevTools assets can load. Leaving this field unset preserves upstream’s default (false).

config:
  token: null
  tokenSecretRef:
    name: browserless-auth
    key: token
  strictTokenUse: true

The default readiness probe and Helm test already use the authenticated /pressure endpoint and work with strict mode. Custom probes, management clients, and direct page WebSocket clients must also supply a valid token. Strict mode requires a token at application startup; the chart’s existing token validation remains in effect.

Session Scratch Storage

Each browser session gets an owned directory under config.scratchDir, passed to the browser as TMPDIR and removed when the session ends. Unset config.scratchDir uses browserless-scratch-dirs under the container’s temporary directory.

Use a writable, pod-local emptyDir for a dedicated scratch mount. Size it for your session concurrency and workload; this example limits it to 1 GiB and grants the published image’s group (999) write access. Keep scratch separate from reusable browser profiles in config.dataDir, and use short paths to stay within Chromium’s Unix socket path-length limit.

config:
  scratchDir: /scratch/browserless
podSecurityContext:
  fsGroup: 999
volumes:
  - name: browser-scratch
    emptyDir:
      sizeLimit: 1Gi
volumeMounts:
  - name: browser-scratch
    mountPath: /scratch

Multiple Replicas

Active browsers and session/reconnect identifiers live inside the replica that created them. An established WebSocket stays on its replica, but reconnect and session-management requests must reach that same replica through affinity or explicit routing. A shared volume does not share running browser processes. Account for active sessions before scaling down or rolling out pods, and keep scratch storage local to each pod.

Flux Example

apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: HelmRepository
metadata:
  name: icoretech
  namespace: flux-system
spec:
  type: oci
  interval: 30m
  url: oci://ghcr.io/icoretech/charts
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: browserless
  namespace: browserless
spec:
  interval: 5m
  chart:
    spec:
      chart: browserless
      version: ">=0.1.1"
      sourceRef:
        kind: HelmRepository
        name: icoretech
        namespace: flux-system
  values:
    image:
      browser: chromium
    config:
      tokenSecretRef:
        name: browserless-auth
        key: token

Configuration reference

Values

Key Type Default Description
affinity object {} Affinity.
autoscaling.enabled bool false Enable HPA.
autoscaling.maxReplicas int 20 Maximum replicas.
autoscaling.minReplicas int 1 Minimum replicas.
autoscaling.targetCPUUtilizationPercentage int 80 Target CPU utilization percentage.
autoscaling.targetMemoryUtilizationPercentage string nil Target memory utilization percentage.
config object {"allowFileProtocol":null,"allowGet":null,"concurrent":4,"corsAllowMethods":null,"corsAllowOrigin":null,"corsMaxAge":null,"cpuEmaAlpha":null,"cpuOverloadHysteresis":null,"cpuSampleIntervalMs":null,"dataDir":null,"debug":"-*","downloadDir":null,"enableCors":null,"errorAlertUrl":null,"external":null,"host":"0.0.0.0","machineStatsSource":null,"maxCpuPercent":null,"maxMemoryPercent":null,"metricsJsonPath":null,"port":3000,"queued":10,"scratchDir":null,"strictTokenUse":null,"timeout":600000,"token":"change-me","tokenSecretRef":null} Browserless configuration mapped to environment variables.
config.allowFileProtocol string nil Allow file:// protocol.
config.allowGet string nil Allow GET requests.
config.concurrent int 4 Max concurrent sessions.
config.corsAllowMethods string nil CORS allowed methods.
config.corsAllowOrigin string nil CORS allowed origins.
config.corsMaxAge string nil CORS max age (seconds).
config.cpuEmaAlpha string nil CPU exponential moving average alpha for overload smoothing.
config.cpuOverloadHysteresis string nil CPU overload hysteresis in percentage points.
config.cpuSampleIntervalMs string nil CPU sampler interval in milliseconds for overload smoothing.
config.dataDir string nil Data directory path.
config.debug string "-*" Debug selector (e.g. “-*” to reduce logs).
config.downloadDir string nil Download directory path.
config.enableCors string nil Enable CORS.
config.errorAlertUrl string nil Callback URL for Browserless runtime errors.
config.external string nil Example: https://browserless.example.com
config.host string "0.0.0.0" Bind host.
config.machineStatsSource string nil Machine stats source for overload checks (auto, host, or cgroup).
config.maxCpuPercent string nil Overload protection CPU threshold percentage.
config.maxMemoryPercent string nil Overload protection memory threshold percentage.
config.metricsJsonPath string nil Metrics JSON path.
config.port int 3000 Bind port.
config.queued int 10 Max queued sessions.
config.scratchDir string nil Root for Browserless-owned per-session temporary files. Null uses the upstream temporary directory; keep this separate from reusable browser profiles.
config.strictTokenUse bool nil Require TOKEN on all routes, including routes that normally opt out of authentication. Static files remain public. Null preserves the upstream default (false).
config.timeout int 600000 Max session timeout in milliseconds.
config.token string "change-me" Change this in production.
config.tokenSecretRef string nil key: token
envFrom list [] Extra envFrom entries.
extraEnv list [] Additional environment variables.
fullnameOverride string "" Override fully-qualified release name.
image.browser string "chromium" Supported presets: chromium, chrome, firefox, multi.
image.pullPolicy string "IfNotPresent" Image pull policy.
image.repository string "" Image repository override. When empty, defaults to ghcr.io/browserless/.
image.tag string "" Image tag override. Defaults to Chart appVersion.
imagePullSecrets list [] List of image pull secrets.
livenessProbe object {"failureThreshold":3,"initialDelaySeconds":5,"periodSeconds":10,"successThreshold":1,"tcpSocket":{"port":"http"},"timeoutSeconds":1} Liveness probe.
nameOverride string "" Override chart name.
nodeSelector object {} Node selector.
podAnnotations object {} Pod annotations.
podLabels object {} Pod labels.
podSecurityContext object {} Pod security context.
readinessProbe object {"exec":{"command":["/bin/sh","-ec","wget -qO- \"http://127.0.0.1:${PORT:-3000}/pressure?token=${TOKEN}\" >/dev/null"]},"failureThreshold":3,"initialDelaySeconds":5,"periodSeconds":10,"successThreshold":1,"timeoutSeconds":1} Readiness probe.
replicaCount int 1 Number of replicas.
resources object {} Container resources.
securityContext object {} Container security context.
service.annotations object {} Service annotations.
service.externalTrafficPolicy string nil External traffic policy.
service.loadBalancerIP string nil Optional LoadBalancer IP.
service.loadBalancerSourceRanges list [] Optional CIDRs allowed via LoadBalancer.
service.nodePort string nil Optional nodePort.
service.port int 80 Service port.
service.type string "ClusterIP" Service type.
serviceAccount.annotations object {} Service account annotations.
serviceAccount.create bool true Create a service account.
serviceAccount.name string "" Service account name.
tolerations list [] Tolerations.
volumeMounts list [] Additional volume mounts.
volumes list [] Additional volumes.