Crovly

Self-Hosting

Run Crovly on your own infrastructure. Contact us for self-hosting options.

Note: Self-hosting is available as a custom deployment option. Contact us to discuss self-hosting for your organization.

Requirements

  • Docker or Node.js 22+
  • PostgreSQL 16+
  • Redis 7+
  • ~256MB RAM, 1 CPU core (handles millions of verifications/day)

Docker Compose

services:
  crovly:
    image: ghcr.io/crovly/crovly:latest
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgres://user:pass@db:5432/crovly
      REDIS_URL: redis://redis:6379
      AUTH_SECRET: your-random-secret-here
      AUTH_URL: https://captcha.yourdomain.com
      NEXT_PUBLIC_APP_URL: https://captcha.yourdomain.com
      NEXT_PUBLIC_APP_NAME: Crovly
    depends_on:
      - db
      - redis
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: crovly
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
    volumes:
      - pgdata:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine
    command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
    volumes:
      - redisdata:/data

volumes:
  pgdata:
  redisdata:

Environment Variables

VariableRequiredDescription
DATABASE_URLYesPostgreSQL connection string
REDIS_URLYesRedis connection string
AUTH_SECRETYesRandom secret for session signing (generate with openssl rand -base64 32)
AUTH_URLYesPublic URL of your instance
NEXT_PUBLIC_APP_URLYesSame as AUTH_URL — used by the frontend
NEXT_PUBLIC_APP_NAMENoDisplay name (default: Crovly)
RESEND_API_KEYNoFor transactional emails (password reset, etc.)

Widget Configuration

Point the widget to your self-hosted API instead of the default:

<script src="https://captcha.yourdomain.com/widget.js"
        data-site-key="YOUR_SITE_KEY"
        data-api-url="https://captcha.yourdomain.com"></script>
<div id="crovly-captcha"></div>

Self-Hosting the Widget

For a fully self-contained setup, host widget.js yourself instead of using the CDN:

  1. Download widget.js from https://get.crovly.com/widget.js
  2. Serve it from your own domain
  3. Update the script src to your domain
<script src="https://captcha.yourdomain.com/widget.js"
        data-site-key="YOUR_SITE_KEY"
        data-api-url="https://captcha.yourdomain.com"></script>

Database Migrations

On first run, the application automatically runs database migrations. No manual setup is required.

Health Check

Verify your instance is running:

curl https://captcha.yourdomain.com/api/health
{
  "status": "ok",
  "checks": { "db": "ok", "redis": "ok" },
  "timestamp": "2026-01-01T00:00:00Z"
}

Reverse Proxy

If running behind nginx or a load balancer, ensure these headers are forwarded:

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;

Crovly uses the client IP for challenge binding and rate limiting. Without proper header forwarding, all requests appear to come from the proxy IP.

On this page