Skip to main content
Camofox ships with a production-ready Dockerfile that pre-bakes the Camoufox browser binary and all dependencies into the image. This eliminates first-run downloads and ensures consistent builds.

Quick start

Build the image

The build process:
  1. Installs Firefox dependencies (GTK, DBus, ALSA, X11 libs)
  2. Installs fonts (Liberation, Noto Color Emoji)
  3. Downloads and installs yt-dlp for fast YouTube transcripts
  4. Pre-downloads the pinned Camoufox browser binary (~300MB)
  5. Installs Node.js dependencies
  6. Copies server code
Build time is ~5 minutes on first run. Subsequent builds are faster due to layer caching.

Run the container

The container exposes port 3000 internally (set by CAMOFOX_PORT=3000 in the Dockerfile), but you map it to host port 9377 for consistency with the standalone server’s default port.
Access the server at http://localhost:9377.

Test the deployment

Expected response:
browserConnected: false is normal - the browser launches lazily on first request.

Dockerfile overview

The Dockerfile is optimized for production use:
Key features:
  • Pinned Camoufox version via build args (update CAMOUFOX_VERSION to upgrade)
  • Pre-baked browser binary eliminates first-run download
  • Production npm install skips dev dependencies
  • 128MB V8 heap limit keeps memory usage low (override with MAX_OLD_SPACE_SIZE)

Environment variables

Pass environment variables with -e flags:

Common variables

See the environment variables reference for all options.

Volume mounts

To use cookie import, mount the cookies directory:
The :ro flag makes the mount read-only for security.
For production, use Docker secrets or a secrets manager instead of mounting files directly.

Persistent cache (optional)

Camofox caches browser data in /root/.cache/camoufox. This is baked into the image, but you can override it:
This is rarely needed - the default image cache is sufficient.

Memory limits

Set Docker memory limits to prevent OOM kills:
Recommended limits:
  • Idle: 50-100MB
  • 1 tab open: 200-300MB
  • 5 tabs open: 400-600MB
  • 10 tabs open: 800MB-1GB
The browser shuts down after 5 minutes of inactivity to conserve memory.

CPU limits

Limit CPU usage to prevent resource exhaustion on shared hosts:
This caps the container at 1 CPU core.

Fly.io deployment

Fly.io is a global edge platform for running Docker containers.

Setup

1

Install flyctl

2

Login to Fly.io

3

Create app

In the camofox-browser directory:
Choose a name and region. Fly will detect the Dockerfile and create fly.toml.
4

Set secrets

5

Deploy

The app will build and deploy. Access it at https://your-app.fly.dev.

fly.toml configuration

The included fly.toml is pre-configured:
Key settings:
  • auto_stop_machines: Shuts down when idle (saves costs)
  • auto_start_machines: Wakes on incoming request
  • min_machines_running = 0: Scales to zero when unused

Scaling on Fly.io

Scale horizontally:
Scale vertically (more RAM):

Railway deployment

Railway is a platform-as-a-service with GitHub integration.

Setup

1

Connect GitHub repo

  1. Go to railway.app
  2. Click “New Project” → “Deploy from GitHub repo”
  3. Select your camofox-browser fork
2

Configure variables

In the Railway dashboard:
  1. Go to your service → Variables
  2. Add:
    • CAMOFOX_API_KEY = your-secret-key
    • CAMOFOX_PORT = 3000
    • MAX_SESSIONS = 20
3

Deploy

Railway auto-detects the Dockerfile and deploys. Access your app at the generated URL.

railway.toml configuration

The included railway.toml configures the build:

Custom cloud providers

Google Cloud Run

AWS ECS / Fargate

  1. Push image to ECR:
  1. Create task definition with environment variables
  2. Create service in ECS cluster

Azure Container Instances

Health checks

All platforms should configure health checks: Endpoint: GET /health Expected response: 200 OK
Recommended settings:
  • Interval: 30 seconds
  • Timeout: 10 seconds
  • Unhealthy threshold: 3 consecutive failures

Logging

Camofox outputs structured JSON logs to stdout:
View logs with:

Troubleshooting

Container fails to start

Symptoms: Container exits immediately Check logs:
Common causes:
  • Missing dependencies (check Dockerfile)
  • Port conflict (change host port: -p 9378:3000)
  • Memory limit too low (increase to 512MB minimum)

Browser launch timeout

Symptoms: Requests fail with “Browser launch timeout (30s)” Causes:
  • Insufficient memory (increase --memory)
  • Insufficient CPU (increase --cpus)
  • Missing system libraries
Fix: Increase container resources or rebuild the image to verify dependencies.

Out of memory (OOM)

Symptoms: Container killed by OOM killer Causes:
  • Too many concurrent sessions
  • Memory limit too low
Fix: