Skip to main content
Self-hosted CruciHiL is free and has no rig limits — the open source stack never enforces quotas on your own server. Register as many rigs as your benches need.

What the stack is

Docker Compose runs three services plus an optional virtual agent: The React dashboard (port 5173) runs natively via ./dev.sh (Vite HMR) or as a container through the development override compose file. Real rig agents run natively on your bench machines, not in Docker — they connect outbound to the server over WebSocket.

Prerequisites

  • Docker and Docker Compose (v2 plugin or v1 standalone — both are detected)
  • curl or wget, and python3 (used by the bootstrap script)

Bootstrap with setup.sh

From the project root:
One command does the full bootstrap, and it is idempotent — safe to re-run:
  1. Validates prerequisites (docker, docker compose)
  2. Creates .env from .env.example and generates SECRET_KEY and REGISTRATION_TOKEN automatically
  3. Starts db + server and waits for health (Alembic migrations run on startup)
  4. Registers a default-rig and saves its API key to .env as CRUCIHIL_API_KEY
  5. Starts all services (control plane + MCP server)
When it finishes:
  • Control plane: http://localhost:8000 (API docs at /docs)
  • MCP server: http://localhost:8001/sse
Other modes:
setup.sh warns if POSTGRES_PASSWORD is still changeme. Change it in .env before exposing the server beyond localhost.

Environment variables

All configuration lives in .env (created from .env.example):
string
PostgreSQL username, used by the db service. Default: crucihil.
string
PostgreSQL password. Must be changed from the default changeme for production.
string
Database name. Default: crucihil.
string
Full connection string used by the server and Alembic, e.g. postgresql://crucihil:changeme@db:5432/crucihil. The hostname must match the compose service name db.
string
JWT signing secret. Generated automatically by setup.sh (or create one with python -c "import secrets; print(secrets.token_hex(32))"). Must be changed before production use.
string
Static token required to register new rigs (POST /api/v1/rigs). Generated automatically by setup.sh. Keep it private.
string
API key the MCP server uses to authenticate to the control plane. Written by setup.sh after it registers the default rig.

First org and admin — the one-shot /setup bootstrap

The dashboard and API use org-scoped users. Create the first organisation and admin account with a single call:
It returns a JWT and the org slug. Log in to the dashboard with the same email and password. The endpoint only succeeds while no organisation exists — every subsequent call returns 409 to prevent accidental re-initialisation. Admins can then invite team members from Settings → Team → Invite member.

Local development — dev.sh

For working on CruciHiL itself: backend in Docker, dashboard natively with Vite HMR.
The Docker virtual agent (rigs/virtual.toml) can also be started directly:

Installing agents on bench machines

Each HiL bench machine runs a native agent that connects outbound to your control plane. Register the rig first (via POST /api/v1/rigs with the REGISTRATION_TOKEN, the dashboard, or the register_rig MCP tool) to get its API key, then install:
The installer (requires Python 3.11+, systemd, and sudo):
  1. Creates a crucihil system user and installs the package into a venv at /opt/crucihil
  2. Copies the rig TOML to /opt/crucihil/rigs/<name>.toml
  3. Writes CRUCIHIL_BASE_URL and CRUCIHIL_API_KEY to /etc/crucihil/<name>.env (chmod 600)
  4. Installs the systemd template unit crucihil-agent@.service
  5. Enables and starts crucihil-agent@<name>
Optional flags: --dir (install directory, default /opt/crucihil) and --user (service user, default crucihil). Manage the service afterwards:
The unit restarts the agent automatically on failure, backing off up to 5 minutes. The rig appears as connected in the dashboard within seconds of the agent starting.
Agents can also self-register: set registration_token in the rig TOML’s [rig.cloud] section, and on first boot the agent exchanges it for a permanent API key stored in ~/.crucihil/credentials.toml. The CRUCIHIL_BASE_URL / CRUCIHIL_API_KEY environment variables take precedence over [rig.cloud]. See Rig Configuration.

Connecting an AI client

Point any MCP client at your self-hosted MCP server. For Claude Desktop, add to claude_desktop_config.json:
See MCP Overview for the full tool list and configuration options.

Deploying to Fly.io + Vercel

The repo ships Fly configs for the two backend services:
The MCP app’s SECRET_KEY must match the control plane — set it with fly secrets set SECRET_KEY=... --app crucihil-mcp.

See also