Self-host - Docker (pre-built images)
Pull published OpenQuok self-host container images from GHCR or Docker Hub — registry env vars, version tags, multi-arch, and when to rebuild the web image.
Connect your agent today
Draft from chat, review in your calendar, and publish only what you approve.
Overview
OpenQuok publishes multi-architecture container images for the self-host stack so you can skip local TypeScript builds for the API, BullMQ workers, and (optionally) the agent server. Images are built from this monorepo when maintainers push a git tag such as self-host-v1.0.0 (image tag 1.0.0).
Default path for most operators
Clone the repo, configure infra/self-host/.env, and run docker compose … up --build — see Docker Compose (self-host). Use this page when you want registry pulls for faster bring-up on the same machine architecture.
Compose definitions live in the monorepo under infra/self-host/ — there is no separate compose-only repository. You still need a Supabase project (hosted or local on the host) and a filled .env before the stack will run.
Registries and image names
| Registry | Prefix | Example pull |
|---|---|---|
| GitHub Container Registry (default) | ghcr.io/ratimon | docker pull ghcr.io/ratimon/openquok-api:latest |
| Docker Hub mirror | docker.io/ratimon | docker pull docker.io/ratimon/openquok-api:latest |
| Image name | Compose services | Dockerfile in repo |
|---|---|---|
| openquok-api | api | backend/Dockerfile |
| openquok-web | web | web/Dockerfile |
| openquok-orchestrator | worker-* (three services) | orchestrator/Dockerfile |
| openquok-agent-server | agent-server (cli profile) | agent/server/Dockerfile |
Registry listings (when packages are public):
- openquok-api on GHCR
- openquok-web on GHCR
- openquok-orchestrator on GHCR
- openquok-agent-server on GHCR
- Docker Hub: ratimon (same image names under
docker.io/ratimon/)
Version tags and multi-arch
- Release tags: git tag self-host-v1.0.0 → images tagged 1.0.0, latest, and per-arch tags such as 1.0.0-amd64 / 1.0.0-arm64 (manifest lists combine amd64 and arm64).
- Maintainers: cut and verify releases via infra/self-host/PUBLISHING.md (push a self-host-v0.1.0-style tag on main after .github/workflows/self-host-containers.yml is merged).
- Pinning: set OPENQUOK_IMAGE_TAG in infra/self-host/.env to a semver (for example
1.0.0) instead oflatestfor reproducible deploys. - Verify architecture:
docker manifest inspect ghcr.io/ratimon/openquok-api:1.0.0should listlinux/amd64andlinux/arm64when the release job completed successfully.
Compose environment variables
Set these in infra/self-host/.env (see infra/self-host/.env.example):
| Variable | Default | Role |
|---|---|---|
| OPENQUOK_IMAGE_REGISTRY | ghcr.io/ratimon | Registry host + org (use docker.io/ratimon for Docker Hub) |
| OPENQUOK_IMAGE_TAG | latest | Image tag for all openquok-* services |
| OPENQUOK_PULL_WEB | false | When true, opt into pulling a pre-built web image only if your VITE_* match the published bake (advanced) |
Base compose file infra/self-host/docker-compose.yml always declares both image: and build: so docker compose up —build still works from a git clone. Registry-first pulls use the overlay infra/self-host/docker-compose.images.yml (sets pull_policy: always on API, workers, and agent server).
Web image and VITE_*
VITE_* values are baked into the web image at build time. CI publishes a web image with self-host-friendly defaults (empty Supabase/Stripe keys, VITE_API_BASE_URL empty for same-origin proxy, VITE_FRONTEND_DOMAIN_URL=http://localhost:4007). If your Supabase URL, publishable key, or public site URL differ, build the web service locally — do not set OPENQUOK_PULL_WEB unless you know the pulled bundle matches your .env.
Future: runtime VITE injection
A single universal pulled web image for every Supabase project would require runtime injection of public config — that is not available today. Until then, treat pulled openquok-web as an optional shortcut for localhost demos, not a substitute for compose build web on real projects.
Pull and start
Prerequisites match System requirements and the Supabase keys documented on Docker Compose (self-host).
Configure .env
Copy infra/self-host/.env.example to infra/self-host/.env, fill Supabase and backend secrets, and set matching VITE_PUBLIC_SUPABASE_* for the web build.
Optionally uncomment and set:
OPENQUOK_IMAGE_REGISTRY=ghcr.io/ratimon
OPENQUOK_IMAGE_TAG=latest Pull API and workers
From the repository root:
docker compose -f infra/self-host/docker-compose.yml -f infra/self-host/docker-compose.images.yml pull This downloads openquok-api, openquok-orchestrator, and (if you use the cli profile) openquok-agent-server. The web service still builds by default.
Build web and bring the stack up
docker compose -f infra/self-host/docker-compose.yml -f infra/self-host/docker-compose.images.yml up -d --build The —build step compiles the web image with your VITE_* build args. Omit —build only when you intentionally pull web (see below).
Open http://localhost:4007 (override with OPENQUOK_WEB_HOST_PORT).
Optional: pull pre-built web (advanced)
When your public URL and Supabase publishable settings match the CI bake:
- Set OPENQUOK_PULL_WEB=true in .env.
- Uncomment the
web:block in docker-compose.images.yml (pull_policy: missing). - Run
pullagain, thenup -dwithout—buildfor web.
Optional: CLI profile
Same as compose docs — include —profile cli on pull and up when you need Postgres and the agent server for device-flow login.
Clone-and-build vs pull (summary)
| Approach | When to use |
|---|---|
docker compose -f infra/self-host/docker-compose.yml up —build | Default — contributors and operators with custom VITE_* |
Base compose + docker-compose.images.yml + pull | Faster API/worker startup; still build web for real Supabase projects |
| Pinned OPENQUOK_IMAGE_TAG | Production-like self-host when you want a known semver |