Docker Deployment
Deploy OpenQA using Docker — the recommended method for production. The official image is published on Docker Hub at orkalab/openqa.
📌 Default Port: 4242
OpenQA listens on port 4242 by default. You can change this via the WEB_PORT environment variable.
Docker Hub (Recommended)
Pull the pre-built image directly — no need to clone the repository or build anything.
🎯 Quick Start: Minimal Setup
You can start OpenQA with zero environment variables and configure everything via the web interface:
1# Minimal setup - configure via web UI2docker run -d \3 -p 4242:4242 \4 -v openqa-data:/app/data \5 --name openqa \6 orkalab/openqa:latest7 8# Then open http://localhost:4242 and configure via UIThis is perfect for demos and development. All configuration (API keys, target URL, etc.) can be done through the /config page.
Full Configuration (Environment Variables)
For production deployments with pre-configured settings:
1# Pull the latest image2docker pull orkalab/openqa:latest3 4# Run with your API key5docker run -d \6 -p 4242:4242 \7 -e LLM_PROVIDER=openai \8 -e OPENAI_API_KEY=sk-xxx \9 -e OPENQA_JWT_SECRET=$(openssl rand -hex 32) \10 -e SAAS_URL=https://your-app.com \11 -e DATA_PATH=/app/data \12 -e DB_PATH=/app/data/openqa.db \13 -v openqa-data:/app/data \14 --name openqa \15 orkalab/openqa:latest🗂️ Why DATA_PATH and DB_PATH?
The Docker image uses an entrypoint script that fixes directory permissions before starting the app. It uses DATA_PATH to know which directory to chown for the unprivileged openqa user.
If DATA_PATH is omitted, the entrypoint defaults to /data — but the volume is mounted at /app/data. The result: the database directory is owned by root and the app cannot write to it.
DB_PATH makes the database path explicit and prevents ambiguity across restarts.
Then open http://localhost:4242 — first run will prompt you to create an admin account.
Available tags
orkalab/openqa:latest— latest stable releaseorkalab/openqa:2.x.x— pinned version (recommended for production)
Simple Deployment (Dokploy, VPS, etc.)
For quick deployment on your server, Dokploy, or any Docker-compatible platform, use this ready-to-go configuration:
📦 One-Click Deploy
Download the files from the repository:
- •
docker-compose.simple.yml— Production-ready compose file - •
.env.simple.example— Environment template with all options
1# 1. Download the files2wget https://raw.githubusercontent.com/Orka-Community/OpenQA/main/docker-compose.simple.yml3wget https://raw.githubusercontent.com/Orka-Community/OpenQA/main/.env.simple.example4 5# 2. Create your .env file6cp .env.simple.example .env7 8# 3. Edit .env with your configuration9nano .env10# Required: OPENAI_API_KEY, OPENQA_JWT_SECRET, SAAS_URL11 12# 4. Start OpenQA13docker compose -f docker-compose.simple.yml up -d14 15# 5. Access at http://your-server:4242🔐 Security Reminder
Always generate a strong JWT secret: openssl rand -hex 32
1# Create .env with your keys2cat > .env <<EOF3LLM_PROVIDER=openai4OPENAI_API_KEY=sk-xxx5OPENQA_JWT_SECRET=$(openssl rand -hex 32)6SAAS_URL=https://your-app.com7EOF8 9# Start10docker compose up -dBuild from Source
If you prefer to build the image yourself from the repository:
1# 1. Clone the repository2git clone https://github.com/Orka-Community/OpenQA.git3cd OpenQA4 5# 2. Build the image6docker build -t orkalab/openqa:latest .7 8# 3. Run9docker run -d -p 4242:4242 --env-file .env --name openqa orkalab/openqa:latestDocker Compose Configuration
The production Docker Compose file includes:
1services:2 openqa:3 image: orkalab/openqa:latest4 platform: linux/amd645 container_name: openqa6 restart: unless-stopped7 ports:8 - "${EXTERNAL_PORT:-4242}:4242"9 environment:10 - NODE_ENV=production11 - WEB_PORT=424212 - WEB_HOST=0.0.0.013 - LLM_PROVIDER=${LLM_PROVIDER:-openai}14 - OPENAI_API_KEY=${OPENAI_API_KEY}15 - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}16 - OLLAMA_BASE_URL=${OLLAMA_BASE_URL:-}17 - SAAS_URL=${SAAS_URL}18 - OPENQA_JWT_SECRET=${OPENQA_JWT_SECRET}19 - GITHUB_TOKEN=${GITHUB_TOKEN:-}20 - GITHUB_OWNER=${GITHUB_OWNER:-}21 - GITHUB_REPO=${GITHUB_REPO:-}22 volumes:23 - openqa_data:/app/data24 healthcheck:25 test: ["CMD", "wget", "-qO-", "http://localhost:4242/api/health"]26 interval: 30s27 timeout: 10s28 retries: 329 start_period: 40s30 31volumes:32 openqa_data:💡 Custom Port
To use a different port, set both EXTERNAL_PORT (host) and WEB_PORT (container):
1# Example: Run on port 80802EXTERNAL_PORT=8080 WEB_PORT=8080 docker compose up -dWith HTTPS (Nginx)
For production with SSL:
1# 1. Update nginx.conf with your domain2nano nginx.conf3 4# 2. Get SSL certificate5sudo certbot certonly --standalone -d your-domain.com6 7# 3. Start with Nginx profile8docker-compose -f docker-compose.production.yml --profile with-nginx up -dProduction Dockerfile
The multi-stage Dockerfile optimizes for production:
1# Build stage2FROM node:20-alpine AS builder3WORKDIR /app4COPY package*.json ./5RUN npm ci6COPY . .7RUN npm run build8 9# Production stage10FROM node:20-alpine11WORKDIR /app12RUN apk add --no-cache chromium13ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser14COPY --from=builder /app/dist ./dist15COPY --from=builder /app/node_modules ./node_modules16COPY package*.json ./17USER node18EXPOSE 424219CMD ["node", "dist/cli/index.js", "start"]Useful Commands
1# View logs2docker logs -f openqa3# or with Compose:4docker compose logs -f5 6# Restart7docker compose restart8 9# Stop10docker compose down11 12# Update to latest image13docker pull orkalab/openqa:latest14docker compose up -d15 16# Backup data volume17docker cp openqa:/app/data ./backup-$(date +%Y%m%d)Troubleshooting
Container won't start?
- • Check logs:
docker logs openqa - • Verify environment variables are set
- • Ensure port 4242 is not in use
Playwright/Browser issues?
- • The Dockerfile installs Chromium automatically
- • For ARM64 (M1/M2), use
--platform linux/amd64
🔥 Firewall blocking access?
If you can access the app locally (curl http://localhost:4242) but not from outside, the firewall is blocking the port.
1# UFW (Ubuntu/Debian)2sudo ufw allow 4242/tcp3sudo ufw reload4 5# iptables6sudo iptables -A INPUT -p tcp --dport 4242 -j ACCEPT7 8# Check if port is open9sudo netstat -tlnp | grep 4242Note: Cloud providers (Hetzner, OVH, DigitalOcean, AWS) often have an additional firewall in their control panel. Make sure to open the port there too!
🐳 Dokploy / Traefik Setup
When using Dokploy or Traefik as a reverse proxy, you need to configure the network and labels correctly.
Step 1: Configure Domain in Dokploy UI
- • Go to Domains tab
- • Set Container Port to
4242 - • Enable HTTPS with Let's Encrypt
Step 2: Complete Docker Compose Configuration
If you get a 404 error, you need to add the Traefik network and labels to your compose file:
1services:2 openqa:3 image: orkalab/openqa:latest4 platform: linux/amd645 container_name: openqa6 restart: unless-stopped7 ports:8 - "8080:4242"9 environment:10 - NODE_ENV=production11 - WEB_PORT=424212 - WEB_HOST=0.0.0.013 - CORS_ORIGINS=https://your-domain.com14 - LLM_PROVIDER=${LLM_PROVIDER:-openai}15 - OPENAI_API_KEY=${OPENAI_API_KEY}16 - SAAS_URL=${SAAS_URL}17 - OPENQA_JWT_SECRET=${OPENQA_JWT_SECRET}18 labels:19 - "traefik.enable=true"20 - "traefik.http.routers.openqa-app.rule=Host(`your-domain.com`)"21 - "traefik.http.routers.openqa-app.entrypoints=websecure"22 - "traefik.http.routers.openqa-app.tls.certresolver=letsencrypt"23 - "traefik.http.services.openqa-app.loadbalancer.server.port=4242"24 networks:25 - dokploy-network26 volumes:27 - openqa_data:/app/data28 29volumes:30 openqa_data:31 32networks:33 dokploy-network:34 external: true⚠️ Important: Use openqa-app (not openqa) in Traefik labels to avoid conflicts with Dokploy's auto-generated services.
🔒 CORS: Set CORS_ORIGINS to your domain (e.g., https://your-domain.com) to avoid CORS errors during setup. You can specify multiple origins separated by commas.
Step 3: Verify Traefik Routing
1# Check if Traefik sees the container2docker logs dokploy-traefik --tail 100 | grep openqa3 4# Should NOT show errors like "cannot be linked automatically with multiple Services"5# If you see this error, rename your router/service in labels (e.g., openqa-app)6 7# Restart Traefik if needed8docker restart dokploy-traefik⚠️ 404 Page Not Found?
This usually means the reverse proxy is routing to the wrong port. Verify:
- • Container Port in Dokploy/Traefik is set to
4242(not 3000) - • Check logs:
docker logs openqashould show"url":"http://0.0.0.0:4242" - • Test locally:
curl http://localhost:4242should return HTML
🔧 Quick Diagnostic Commands
1# Check container is running with correct port mapping2docker ps | grep openqa3# Should show: 0.0.0.0:4242->4242/tcp4 5# Test from inside the server6curl http://localhost:42427# Should return: Found. Redirecting (or HTML)8 9# Check what port the app is listening on10docker logs openqa | grep "running"11# Should show: "url":"http://0.0.0.0:4242"🚫 CORS Error: origin not allowed?
If you see Error: CORS: origin https://your-domain.com not allowed in the logs when creating an account:
1# Add CORS_ORIGINS environment variable (note the S at the end!)2# In your docker-compose.yml or Dokploy environment settings:3CORS_ORIGINS=https://your-domain.com4 5# Multiple origins (comma-separated):6CORS_ORIGINS=https://your-domain.com,https://www.your-domain.com7 8# Then redeploy9docker compose down && docker compose up -dNote: The CORS_ORIGINS must match exactly the domain you're accessing the app from (including https://). Use CORS_ORIGINS (with an S), not CORS_ORIGIN.
⚠️ X-Forwarded-For validation error?
If you see ValidationError: The 'X-Forwarded-For' header is set but the Express 'trust proxy' setting is false:
This is fixed in the latest version. Make sure you're using orkalab/openqa:latest and redeploy. The app now correctly handles reverse proxies like Traefik and Nginx.
