Self-host with Docker Compose
The whole stack on one host, free and without limits.
The compose stack runs web (control plane), a runner, Postgres 17, Hatchet (job queue),
MinIO (storage) and the open-source Steel browser. Requirements: Docker with Compose v2, about
4 GB of RAM, and openssl.
Get the code and generate secrets
git clone https://github.com/qaitai/qaitai && cd qaitai
sh docker/init-env.shdocker/init-env.sh writes docker/.env with generated secrets (QAITAI_MASTER_KEY,
BETTER_AUTH_SECRET, QAITAI_INTERNAL_SECRET, database and storage passwords) and never overwrites an
existing file. Back up QAITAI_MASTER_KEY: without it, stored model keys and test secrets can't be
decrypted.
Configure
Edit docker/.env: set QAITAI_URL, a way to sign in, and a model key (ANTHROPIC_API_KEY or
AI_GATEWAY_API_KEY). All settings: Environment variables.
Start it
docker compose -f docker/compose.yml up -dOn first start the stack creates the database roles (the app connects as qaitai_app, which can't
bypass row-level security), mints a Hatchet worker token, runs migrations and creates the storage bucket.
Sign in as the admin
Open QAITAI_URL (default http://localhost:3000). No email or GitHub App yet? The web container prints a
one-time sign-in link while the instance has no users:
docker compose -f docker/compose.yml logs web | grep -A2 "no users yet"The first account becomes the instance admin. Sign-up is invite-only after that unless you set
QAITAI_ALLOW_SIGNUP=true, for every method: GitHub, Google, magic link and email + password.
Email + password needs no extra setup. With SMTP configured, new password accounts confirm their email before signing in and Forgot password? sends a reset link; without mail they sign in unconfirmed and reset isn't available. Existing users can add a password under Settings → Account.
Operating it
- Only
webis published (default0.0.0.0:3000). Put TLS in front with your reverse proxy and setQAITAI_URLto the public https URL. - Health:
GET /api/health(liveness) andGET /api/health?db=1(readiness). - Upgrade: set
QAITAI_VERSION, thendocker compose -f docker/compose.yml pull && docker compose -f docker/compose.yml up -d. - More runners:
docker compose -f docker/compose.yml up -d --scale runner=3. - Backups:
docker compose -f docker/compose.yml exec postgres pg_dumpall -U postgres > backup.sql, and keepQAITAI_MASTER_KEYapart from them. - Domain verification is off by default on your own instance
(
QAITAI_REQUIRE_DOMAIN_VERIFICATION=false); turn it on if untrusted people share the instance.
Browsers, email, the GitHub App and more: docs/self-hosting.md.