Docker Deployment

July 12, 2026 · View on GitHub

Deploy InnoClaw with Docker in under 2 minutes.

Prerequisites

  • Docker Engine 24+ and Docker Compose v2
  • At least one AI API key (OpenAI, Anthropic, etc.)

Quick Start

git clone https://github.com/SpectrAI-Initiative/InnoClaw.git
cd InnoClaw
cp .env.production.example .env.production.local
# Edit .env.production.local — set at least one API key
docker compose up -d

Open http://localhost:3000.

Configuration

Environment Variables

Edit .env.production.local before starting. Key variables:

VariableRequiredDescription
WORKSPACE_ROOTSYesComma-separated paths inside the container (e.g., /research)
OPENAI_API_KEYAt least one AI keyOpenAI API key
ANTHROPIC_API_KEYAnthropic API key
DATABASE_URLNoSQLite path (default: ./data/innoclaw.db)
AUTH_MODENoSet to disabled only for trusted deployments that should bypass registration/login
AUTH_SINGLE_ADMINNoSet to true to enforce one bootstrapped administrator and ordinary-user registration
AUTH_COOKIE_SECURENoDefaults to true in production; use false only for a temporary plain-HTTP rollout
AUTH_SECRETProductionLong random value used to sign session cookies
LLM_PROVIDERNoDefault provider (openai, anthropic, etc.)
OPENAI_REASONING_EFFORTNoOpenAI reasoning effort; ultra is normalized to xhigh

See .env.production.example for the full list.

To run without application-level registration or login, set AUTH_MODE=disabled in .env.production.local before starting the container. Anyone who can reach the service gets admin-level access, so use it only behind trusted network access or another access-control layer.

Bootstrap a Single Administrator

For a public multi-user deployment, configure at least:

AUTH_MODE=local
AUTH_SINGLE_ADMIN=true
AUTH_COOKIE_SECURE=true
AUTH_SECRET=replace-with-a-long-random-secret
WORKSPACE_ROOTS=/research

Start the container so migrations complete, then create the sole administrator with a password supplied only through standard input:

umask 077
openssl rand -base64 32 > /tmp/innoclaw-admin-password
docker compose exec -T innoclaw node /app/admin-cli/scripts/bootstrap-admin.js \
  --email admin@example.com --name Administrator \
  < /tmp/innoclaw-admin-password

Store the generated password in your password manager and securely remove the temporary file after delivery. Re-running the same command is idempotent and does not rotate an existing administrator password. Bootstrap must finish before public registration becomes available. Registered users are always ordinary users and cannot promote themselves or another account.

For a temporary plain-HTTP rollout, set AUTH_COOKIE_SECURE=false so browsers can send the session cookie. This does not encrypt credentials or traffic. Move to HTTPS and restore AUTH_COOKIE_SECURE=true as soon as possible.

OpenAI-Compatible Reasoning

OPENAI_REASONING_EFFORT accepts none, minimal, low, medium, high, and xhigh. The operator-friendly value ultra is normalized to xhigh before OpenAI language-model calls. Omit the variable to retain the provider default. The setting does not affect embeddings or non-OpenAI providers; verify that a custom OpenAI-compatible endpoint supports the normalized value.

Volumes

Container PathPurposeCompose Default
/app/dataSQLite database, HF datasets, embeddingsNamed volume innoclaw-data
/researchYour workspace filesHOST_WORKSPACE_PATH env var or ./workspace

In single-administrator mode, an ordinary user's effective root is provisioned lazily at /research/users/<immutable-user-id> with private permissions. Users can create and operate only their own workspaces. The administrator can view and manage workspace records across the full /research operator root.

To expose multiple workspace directories, add more volume mounts in docker-compose.yml and update WORKSPACE_ROOTS accordingly:

volumes:
  - innoclaw-data:/app/data
  - /home/user/papers:/papers
  - /home/user/code:/code
WORKSPACE_ROOTS=/papers,/code

Port

Default: 3000. Change in docker-compose.yml:

ports:
  - "8080:3000"

Reverse Proxy

InnoClaw works behind any reverse proxy. Examples:

Nginx

limit_req_zone $binary_remote_addr zone=innoclaw_login:10m rate=10r/m;
limit_req_zone $binary_remote_addr zone=innoclaw_register:10m rate=1r/m;

server {
    listen 443 ssl;
    server_name innoclaw.example.com;

    ssl_certificate     /etc/ssl/certs/innoclaw.pem;
    ssl_certificate_key /etc/ssl/private/innoclaw.key;

    location = /api/auth/login {
        limit_req zone=innoclaw_login burst=10 nodelay;
        limit_req_status 429;
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        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;
    }

    location = /api/auth/register {
        limit_req zone=innoclaw_register burst=2 nodelay;
        limit_req_status 429;
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        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;
    }

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        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;
    }
}

Caddy

innoclaw.example.com {
    reverse_proxy localhost:3000
}

Caddy handles TLS automatically.

Persistent Data & Backups

All persistent state lives in the innoclaw-data volume:

  • innoclaw.db — SQLite database (notebooks, chat history, settings)
  • hf-datasets/ — cached HuggingFace datasets

Back up the database while the service is running:

docker compose exec -T innoclaw node -e \
  'const Database=require("better-sqlite3");const db=new Database("/app/data/innoclaw.db");db.backup("/app/data/innoclaw.db.backup").then(()=>db.close())'
docker cp "$(docker compose ps -q innoclaw):/app/data/innoclaw.db.backup" ./backup.db

The online backup API includes committed WAL state. Also back up the root-readable environment file and reverse-proxy configuration, and retain the previous image until login, workspace isolation, and model inference smoke tests pass.

Upgrading

git pull
docker compose build
docker compose up -d

Database migrations run automatically on container startup — no manual steps needed. The canonical workspace-path preflight runs before the unique path index. If two legacy rows resolve to the same filesystem path, startup stops and reports the colliding workspace IDs instead of deleting or reassigning data.

Build from Scratch

docker build -t innoclaw .
docker run -d \
  --name innoclaw \
  -p 3000:3000 \
  --env-file .env.production.local \
  -v innoclaw-data:/app/data \
  -v /path/to/your/research:/research \
  innoclaw

Troubleshooting

IssueFix
/app/data is not writableEnsure the Docker volume is mounted and the container user has write access
workspace root missingMount your host directory in docker-compose.yml and match WORKSPACE_ROOTS
no AI API key detectedEdit .env.production.local and set at least one valid API key
drizzle-kit migrate failedUsually harmless on first run; check that /app/data is writable
Container exits immediatelyRun docker compose logs innoclaw to see the startup error