Docker Deployment

LumaBrowser Docker packages the full browser automation platform into a self-hosted container. It runs a lightweight Linux desktop with LumaBrowser, exposing the REST API, MCP tools, and a web-based visual desktop via your browser.

Docker deployment requires an Enterprise Fleet license with the HEADLESS_DEPLOY entitlement. Get a license →

┌─── Docker Container ───────────────────────────────────┐ │ │ │ entrypoint.sh │ │ ├── validate-license.js (Keygen API check) │ │ └── supervisord │ │ ├── Xvfb :1 (virtual display) │ │ ├── fluxbox (lightweight WM) │ │ ├── x11vnc → localhost:5900 │ │ ├── websockify/noVNC → :6080 (HTTP) │ │ └── electron (LumaBrowser) → :3000 │ │ │ │ Exposed: 3000 (REST API) 6080 (Web Desktop) │ │ Volume: /data (SQLite DB + app data) │ └─────────────────────────────────────────────────────┘
Requirements
  • Docker 20.10+ with Docker Compose v2
  • Enterprise Fleet license from lumabyte.com/pricing
  • 2 GB+ RAM allocated to the container (Chromium requires adequate shared memory)
  • Network access to api.keygen.sh for license validation on startup
Quick Start

1. Create a .env file

LUMA_LICENSE_KEY=your-enterprise-license-key
LUMA_VNC_PASSWORD=your-secure-password

2. Run with Docker Compose

docker compose up -d

3. Access LumaBrowser

ServiceURLDescription
Web Desktophttp://localhost:6080Visual browser desktop via noVNC
REST APIhttp://localhost:3000/api/healthHealth check and API access
MCP Toolshttp://localhost:3000/api/mcp/toolsAvailable MCP tool listing

4. Verify

# Check the API is responding
curl http://localhost:3000/api/health

# List available MCP tools
curl http://localhost:3000/api/mcp/tools

# View container logs
docker logs lumabrowser
Environment Variables

Required

VariableDescription
required LUMA_LICENSE_KEY Enterprise Fleet license key from Keygen.sh. The container will not start without a valid key with the HEADLESS_DEPLOY entitlement.
required LUMA_VNC_PASSWORD Password for the web-based desktop access. Required for secure VNC connections.

Optional

VariableDefaultDescription
optional LUMA_API_PORT 3000 REST API port inside the container
optional LUMA_VNC_PORT 6080 noVNC web desktop port inside the container
optional LUMA_DATA_DIR /data Persistent data directory mount point
optional LUMA_MACHINE_ID container hostname Stable machine fingerprint for license activation. Set this to persist the same machine ID across container restarts.
LLM Provider Configuration

Configure LLM providers via environment variables so AI features (AI Chat, Template Builder, Timed Tasks) work immediately on startup.

OpenAI-Compatible (LM Studio, Ollama, vLLM)

VariableExampleDescription
LUMA_LLM_PROVIDERopenaiSet the active provider
LUMA_OPENAI_ENDPOINThttp://host.docker.internal:1234OpenAI-compatible API base URL
LUMA_OPENAI_KEYlm-studioAPI key (use any value for LM Studio)
LUMA_OPENAI_MODELqwen2.5-7b-instructDefault model to use

Anthropic (Claude)

VariableExampleDescription
LUMA_LLM_PROVIDERanthropicSet the active provider
LUMA_ANTHROPIC_KEYsk-ant-...Anthropic API key
LUMA_ANTHROPIC_MODELclaude-sonnet-4-6-20250514Default Claude model
LUMA_ANTHROPIC_ENDPOINThttps://api.anthropic.comAPI endpoint (default works for most)

Example: LM Studio on Host Machine

# .env file
LUMA_LICENSE_KEY=your-enterprise-key
LUMA_VNC_PASSWORD=secret123
LUMA_LLM_PROVIDER=openai
LUMA_OPENAI_ENDPOINT=http://host.docker.internal:1234
LUMA_OPENAI_KEY=lm-studio
LUMA_OPENAI_MODEL=qwen2.5-7b-instruct

Use host.docker.internal to reach services running on the Docker host machine (e.g., LM Studio, Ollama).

Data & Volumes

LumaBrowser stores all settings, templates, network watchers, and license cache in a SQLite database at /data/settings.db. Mount a volume to persist data across container restarts.

volumes:
  - luma-data:/data

Shared Volumes (Multi-Instance)

Multiple containers can share the same data volume. SQLite WAL mode supports concurrent readers, and a 5-second busy timeout handles write contention gracefully.

Note: For deployments with heavy write workloads, use separate volumes per instance to avoid contention.

Single Instance

Using Docker Run

docker run -d \
  -e LUMA_LICENSE_KEY=your-enterprise-key \
  -e LUMA_VNC_PASSWORD=your-password \
  -p 3000:3000 \
  -p 6080:6080 \
  -v luma-data:/data \
  --shm-size=2g \
  --name lumabrowser \
  lumabyte/lumabrowser:latest

Using Docker Compose

docker compose up -d

See Docker Compose Reference for the full configuration file.

Multi-Instance Deployment

Run multiple LumaBrowser instances behind a single Enterprise Fleet license. Each instance activates a floating machine slot. Use offset ports to avoid conflicts.

# docker-compose.multi.yml
services:
  lumabrowser-1:
    build: { context: ., dockerfile: docker/Dockerfile }
    environment:
      - LUMA_LICENSE_KEY=${LUMA_LICENSE_KEY}
      - LUMA_VNC_PASSWORD=${LUMA_VNC_PASSWORD}
    ports:
      - "3001:3000"
      - "6081:6080"
    volumes:
      - shared-data:/data
    shm_size: '2gb'

  lumabrowser-2:
    build: { context: ., dockerfile: docker/Dockerfile }
    environment:
      - LUMA_LICENSE_KEY=${LUMA_LICENSE_KEY}
      - LUMA_VNC_PASSWORD=${LUMA_VNC_PASSWORD}
    ports:
      - "3002:3000"
      - "6082:6080"
    volumes:
      - shared-data:/data
    shm_size: '2gb'

volumes:
  shared-data:
docker compose -f docker-compose.multi.yml up -d
Docker Compose Reference
# docker-compose.yml
services:
  lumabrowser:
    build:
      context: .
      dockerfile: docker/Dockerfile
    environment:
      # Required
      - LUMA_LICENSE_KEY=${LUMA_LICENSE_KEY}
      - LUMA_VNC_PASSWORD=${LUMA_VNC_PASSWORD}
      # Ports
      - LUMA_API_PORT=${LUMA_API_PORT:-3000}
      - LUMA_VNC_PORT=${LUMA_VNC_PORT:-6080}
      - LUMA_DATA_DIR=/data
      # LLM Configuration (optional)
      - LUMA_LLM_PROVIDER=${LUMA_LLM_PROVIDER:-}
      - LUMA_OPENAI_ENDPOINT=${LUMA_OPENAI_ENDPOINT:-}
      - LUMA_OPENAI_KEY=${LUMA_OPENAI_KEY:-}
      - LUMA_OPENAI_MODEL=${LUMA_OPENAI_MODEL:-}
      - LUMA_ANTHROPIC_KEY=${LUMA_ANTHROPIC_KEY:-}
      - LUMA_ANTHROPIC_MODEL=${LUMA_ANTHROPIC_MODEL:-}
      - LUMA_ANTHROPIC_ENDPOINT=${LUMA_ANTHROPIC_ENDPOINT:-}
    ports:
      - "${LUMA_API_PORT:-3000}:3000"
      - "${LUMA_VNC_PORT:-6080}:6080"
    volumes:
      - luma-data:/data
    shm_size: '2gb'
    restart: unless-stopped

volumes:
  luma-data:
Architecture

The container runs five managed processes via supervisord:

ProcessRole
XvfbVirtual framebuffer providing a 1920x1080 display
fluxboxLightweight window manager
x11vncVNC server attached to the virtual display
websockifynoVNC proxy providing HTTP-based desktop access
electronLumaBrowser with REST API, MCP tools, and all extensions

Startup Sequence

  1. Entrypoint validates LUMA_LICENSE_KEY against Keygen.sh API
  2. Verifies Enterprise tier with HEADLESS_DEPLOY entitlement
  3. Activates machine fingerprint (auto-registers if new)
  4. Pre-seeds license key and LLM config into SQLite database
  5. Starts all processes via supervisord
  6. LumaBrowser opens on the virtual display with REST API on port 3000

License Heartbeat

Enterprise floating licenses send a heartbeat ping to Keygen every 5 minutes. On container shutdown, the machine slot is automatically released so it can be reused by another instance.

Ports & Access
PortProtocolServiceExternal
3000HTTPREST API + MCP proxyYes
6080HTTPnoVNC web desktopYes
5900VNCInternal VNC serverNo (localhost only)

API Endpoints

All LumaBrowser REST API endpoints are available inside the container. Key routes:

EndpointDescription
GET /api/healthHealth check with extension list
GET /api/mcp/toolsList all available MCP tools
POST /api/mcp/callExecute any MCP tool
GET /api/browser/tabsList open browser tabs
POST /api/browser/tabsCreate a new tab
Security
  • Non-root user: LumaBrowser runs as the luma user inside the container, not root.
  • VNC password required: The container refuses to start without a LUMA_VNC_PASSWORD.
  • Internal VNC port: Port 5900 is only accessible inside the container. External access goes through noVNC on port 6080.
  • License key: Passed as a runtime environment variable, never baked into the image.
  • Shared memory: shm_size: 2gb is required. Chromium uses /dev/shm for rendering; the Docker default of 64MB causes crashes.

Production Recommendations

  • Place an HTTPS reverse proxy (nginx, Caddy, Traefik) in front of the noVNC port for encrypted desktop access.
  • Use Docker secrets or a .env file (gitignored) instead of passing credentials on the command line.
  • Restrict network access so only trusted clients can reach ports 3000 and 6080.
Troubleshooting

Container exits immediately

Check docker logs lumabrowser for license validation errors. Common causes:

  • LUMA_LICENSE_KEY not set or invalid
  • License is not Enterprise tier (Pro/Community keys won't work)
  • Missing HEADLESS_DEPLOY entitlement
  • License has reached its machine limit — deactivate another instance first
  • No network access to api.keygen.sh

noVNC shows a black screen

  • Wait 10-15 seconds for LumaBrowser to fully initialize
  • Check that shm_size is at least 2gb in your compose file
  • Verify Xvfb is running: docker exec lumabrowser ps aux | grep Xvfb

REST API not responding

  • Verify the container is healthy: docker ps should show (healthy)
  • Check LumaBrowser started: docker logs lumabrowser | grep "HTTP server listening"
  • Ensure port 3000 is mapped: docker port lumabrowser

LLM features not working

  • Verify LLM env vars are set (LUMA_LLM_PROVIDER, endpoint, key, model)
  • For local LLM servers, use host.docker.internal instead of localhost
  • Check the LLM server is accessible from inside the container: docker exec lumabrowser curl http://host.docker.internal:1234/v1/models

D-Bus errors in logs

Messages like Failed to connect to the bus are cosmetic warnings. There is no system bus inside the container, but this does not affect LumaBrowser functionality.