Deployment

Images

PDF Server ships as an Alpine-based image (using tini as PID 1) with a browser installed. Two families are published:

ImageBrowserBROWSER_COMMAND
…:latest-chromiumChromiumchromium-browser
…:latest-firefoxFirefoxfirefox

Multi-arch (amd64 + arm64) images are built via Earthly. You layer your templates on top — see Build your image.

Browser choice

  • Chromium is the default and most-tested. It supports both factory modes.
  • Firefox ships different BROWSER_ARGS and must use --factory-type=runner.

Factory modes

--factory-type controls how browsers back the pool:

ModeBehaviorNotes
runner (default)One browser process per pooled object.Robust isolation; works on Chromium and Firefox.
pageOne browser process; each pooled object is a tab.Lower per-render overhead; Chromium only.

Process model

The runner mode launches each browser in its own process group and, on teardown, escalates from SIGTERM to SIGKILL across the whole group to reap Chromium helper processes (GPU, renderers, crash handler). This prevents zombie processes accumulating. The wait before escalation is --browser-process-group-wait-timeout (default 10s).

Running as non-root

The image runs as a non-root user. Combined with the browser sandbox caveat (see Security model), run the container with a restrictive seccomp profile and, ideally, user-namespace isolation.

Configuration

Everything is set via flags or environment variables — see the CLI & configuration reference. Common production settings:

-e RENDER_POOL_MAX_TOTAL=4      # concurrency (browsers + render workers)
-e RENDER_TIMEOUT=30s
-e FACTORY_TYPE=runner
-e LOG_FORMAT=json

See Tuning for sizing guidance and Observability for tracing/logging.