Repository navigation
Production Deployment
Canonical source:
docs/08-runtime-devops/deployment-guide.md— this page is rendered from it on every publish; edit the source.
Dev vs prod setup, SSL, scaling considerations, monitoring, and backup.
| Software | Version | Purpose |
|---|---|---|
| Node.js | >= 20 | Running services locally |
| Docker | >= 24 | Container runtime |
| Docker Compose | >= 2 | Container orchestration |
| Git | >= 2.40 | Version control |
# 1. Clone the repository
git clone <repo-url> && cd Claw
# 2. Copy environment config
cp .env.example .env
# Edit .env with your values
# 3. Start everything
./scripts/claw.sh up -d
# 4. Wait for services to be healthy (~2-5 minutes first run)
./scripts/claw.sh ps
# 5. Access the application
# Frontend: http://localhost:3000
# API (via nginx): http://localhost:4000
# RabbitMQ Management: http://localhost:15672# Linux/macOS
./scripts/install.sh
# Windows PowerShell
.\scripts\install.ps1The install scripts:
- Check prerequisites (Node.js, Docker, Docker Compose)
- Install npm dependencies
- Generate a
.envfile with default values - Build shared packages
- Start Docker containers
- Wait for health checks
- Ollama model downloads take 10-30 minutes (~10 GB total)
- PostgreSQL databases are created automatically
- Prisma migrations run on container startup
- Seed data (admin user, default policies) is applied on first startup
# The only supported way: claw.sh stitches the split prod compose files
# (docker/docker-compose.prod.{databases,services,ollama}.yml) and the GPU overlay
./scripts/claw.sh --prod up| Aspect | Development | Production |
|---|---|---|
| Dockerfile | Dockerfile.dev |
Dockerfile |
| Source mounts | Yes (hot reload) | No (baked into image) |
| Dependencies | All (dev + prod) | Production only |
| Next.js | Turbopack dev server | Optimized static build |
| Port exposure | All ports to host | Only nginx (4000) |
| Restart policy | unless-stopped |
always |
| NODE_ENV | development |
production |
| Source maps | Enabled | Disabled |
Critical variables to configure for production:
# Security (MUST change from defaults)
JWT_SECRET=<random-64-char-hex>
ENCRYPTION_KEY=<random-64-char-hex>
ADMIN_PASSWORD=<strong-password>
# Database passwords (MUST change from defaults)
PG_AUTH_PASSWORD=<strong-password>
PG_CHAT_PASSWORD=<strong-password>
# ... (all 13 PostgreSQL instances)
MONGO_PASSWORD=<strong-password>
RABBITMQ_DEFAULT_PASS=<strong-password>
# CORS (restrict to your domain)
CORS_ORIGINS=https://your-domain.com
# Frontend URL
NEXT_PUBLIC_API_URL=https://your-domain.com/api/v1
NEXT_PUBLIC_APP_URL=https://your-domain.comFor production, add SSL termination at the Nginx layer:
Add to infra/nginx/nginx.conf:
server {
listen 443 ssl;
server_name your-domain.com;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
# ... existing location blocks
}
server {
listen 80;
server_name your-domain.com;
return 301 https://$host$request_uri;
}Mount certificates in Docker Compose:
volumes:
- ./ssl/fullchain.pem:/etc/nginx/ssl/fullchain.pem:ro
- ./ssl/privkey.pem:/etc/nginx/ssl/privkey.pem:roUse Cloudflare, AWS ALB, or Traefik in front of Nginx for SSL termination. This simplifies certificate management and provides DDoS protection.
Only chat-service can run as several replicas: it has no container_name and
no published host port in docker/docker-compose.prod.services.yml, and its
stream bus and Stop broadcast live in Redis. Every other service fixes a
container_name, so Docker refuses to scale it. Set the replica count in .env
and recreate the service:
# .env: CHAT_SERVICE_REPLICAS=4
./scripts/claw.sh --prod service:recreate chat-servicenginx reaches the replicas through the chat-service network alias and
re-resolves it per request, so no upstream block is needed. The block below is
only the general nginx pattern for a fixed set of named backends:
Update Nginx to load-balance:
upstream chat-backend {
server chat-service-1:4002;
server chat-service-2:4002;
server chat-service-3:4002;
}For Ollama, increasing GPU memory allows larger models. Check model requirements against available VRAM.
- PostgreSQL: Consider connection pooling (PgBouncer) for high-traffic services
- MongoDB: Enable replica sets for audit/log durability
- Redis: Redis Cluster for high-availability caching
The health service (port 4009) aggregates health from all services:
curl http://localhost:4000/api/v1/healthReturns status for each service (HEALTHY, DEGRADED, UNHEALTHY) with response times.
# Check all container statuses
./scripts/claw.sh ps
# Resource usage
docker stats
# Specific service health
docker inspect --format='{{json .State.Health}}' claw-chat-serviceServices emit structured JSON logs (Pino):
# Follow service logs
docker compose logs -f chat-service
# Last 100 lines
docker compose logs --tail=100 routing-serviceThe server-logs-service (port 4011) stores backend logs in MongoDB with 30-day TTL, accessible via the frontend Logs page.
# PostgreSQL backup (single database)
docker exec claw-pg-chat pg_dump -U claw claw_chat > backup_chat_$(date +%Y%m%d).sql
# PostgreSQL backup (all databases)
for db in auth chat connector routing memory files ollama images file-generations; do
docker exec claw-pg-${db} pg_dump -U claw claw_${db} > backup_${db}_$(date +%Y%m%d).sql
done
# MongoDB backup
docker exec claw-mongodb mongodump --out /tmp/backup
docker cp claw-mongodb:/tmp/backup ./mongo_backup_$(date +%Y%m%d)
# Redis backup (if persistence enabled)
docker exec claw-redis redis-cli BGSAVE
docker cp claw-redis:/data/dump.rdb ./redis_backup_$(date +%Y%m%d).rdb# PostgreSQL restore
docker exec -i claw-pg-chat psql -U claw claw_chat < backup_chat_20260411.sql
# MongoDB restore
docker cp ./mongo_backup claw-mongodb:/tmp/restore
docker exec claw-mongodb mongorestore /tmp/restore# Backup a Docker volume
docker run --rm -v claw_pg-chat-data:/data -v $(pwd):/backup alpine tar czf /backup/pg-chat-data.tar.gz -C /data .
# Restore a Docker volume
docker run --rm -v claw_pg-chat-data:/data -v $(pwd):/backup alpine tar xzf /backup/pg-chat-data.tar.gz -C /dataOllama models are stored in the ollama-data volume. Back up this volume or rely on re-pulling from the registry (models are public).
Prisma migrations run automatically on container startup. For manual migrations:
docker exec -it claw-chat-service npx prisma migrate deploy- MongoDB logs: 30-day TTL index automatically deletes old entries
- Docker container logs: Configure Docker daemon log driver with max-size/max-file
# Remove unused volumes
docker volume prune
# Remove all ClawAI volumes (DESTRUCTIVE)
./scripts/claw.sh down -vThe production deploy plans two kinds of container:
| Kind | Example | How it deploys |
|---|---|---|
| Built from a workspace | chat-service |
image built, then up -d --no-deps --no-build
|
| Built from a published image |
log-shipper (Vector) |
never built; up -d --no-deps --no-build --force-recreate
|
An image-only container is associated with its bind-mounted config through
CONFIG_DIR_SERVICES in scripts/deploy-prod.sh. Editing a file under a
mapped directory plans that container; a recreate is used rather than a restart
so the bind mount re-resolves.
Before 2026-09-20 such a container was filtered out of the plan entirely, so its config changes never reached production and the run still said "Deployment successful".
A compose service with a profiles: entry exists on a host only when one of
its profiles is live there. scripts/deploy-prod.sh resolves the live set
exactly the way scripts/claw.sh does, from the production .env:
| Profile | Live when |
|---|---|
local-ai |
CLAW_LOCAL_AI=true (env override > .env) |
crawl4ai, flaresolverr, firecrawl
|
named in CLAW_SCRAPER_PROFILES (env > .env) |
A profiled service whose profiles are all off is dropped from the catalogue
before any plan is made, so it is never built, created, recreated, health-waited
on or verified — on a broad-impact or first deployment too. The live set is
exported as COMPOSE_PROFILES, and the run logs active compose profiles: ….
The removed-service report reads the full catalogue, so a switched-off service
is never reported as removed.
Incident, 2026-09-25. The parser only recognised local-ai; every other
profile read as "always on", and the image-only branch ran before the profile
check. The first deploy after the scraper sidecars shipped (ADR-121) therefore
started all seven sidecar containers on production, Firecrawl crash-looped,
verification failed and the release stayed on the previous SHA. The fix and
its regression tests: parse_compose_services keeps every profile,
service_profiles_active gates the catalogue before the image-only branch,
tools/__tests__/deploy-prod.test.mjs runs the real functions on a fixture,
and tools/__tests__/deploy-prod-e2e.sh asserts every sidecar stays out with
its profile off and exactly the named one deploys with it on (against the old
script the rehearsal fails 19 assertions).
To add a new profiled service: give it a profile, and if it is not local-ai,
add the profile name to BOTH the CLAW_SCRAPER_PROFILES validation in
scripts/claw.sh and resolve_active_profiles in scripts/deploy-prod.sh.
ClawAI Wiki · source-controlled under wiki/ · generated/mirrored from the current repository knowledge layer.
ClawAI Wiki
Product
- Product-Vision
- Flagship-Features
- Business-Overview
- Requirements-Register
- Drift-Log
- Runtime-Managed-Connector-Providers
- Threads
- ADR-Index
Architecture
- System-at-a-Glance
- Architecture-Map
- System-Architecture
- Message-Flow
- End-to-End-Data-Flow
- Routing-Engine
- Event-Bus
- Security-Architecture
Platform
- Backend-Services
- Frontend-Architecture
- Shared-Packages
- Database-Reference
- API-Reference
- Provider-Catalog
- Memory-and-Context-Architecture
- File-Support-Architecture
- Research-and-Web-Crawling
Runtime & Ops
- Docker-Guide
- Nginx-Reference
- CI-CD-Pipeline
- Logging-and-Observability
- Operational-Runbooks
- Troubleshooting
Quality
Engineering OS
- AI-Native-Engineering-OS
- Generated-Manifests
- Rules-Catalog
- Skills-Catalog
- Context-Layer
- Engineering-Memory
- Tooling-and-Automation
- Scripts-and-Operations
- ESLint-and-Architecture-Enforcement
- Extended-Work-Skills
Agents
Reference