142 lines
5.4 KiB
YAML
142 lines
5.4 KiB
YAML
services:
|
|
# Postgres for backend metadata (users, actor registry, billing,
|
|
# repo/container mappings). PRD §11.
|
|
postgres:
|
|
image: postgres:16-alpine
|
|
container_name: growqr-postgres
|
|
environment:
|
|
POSTGRES_USER: ${POSTGRES_USER:-growqr}
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-growqr}
|
|
POSTGRES_DB: ${POSTGRES_DB:-growqr}
|
|
ports:
|
|
- "5432:5432"
|
|
volumes:
|
|
- postgres-data:/var/lib/postgresql/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-growqr}"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 10
|
|
restart: unless-stopped
|
|
|
|
# ── Central Gitea (one org-wide instance, changes.md §2A) ──
|
|
# Every user gets a repo inside the GrowQR organization on this instance.
|
|
# Per-user Gitea containers are REMOVED — the backend no longer spawns them.
|
|
gitea:
|
|
image: gitea/gitea:1.22
|
|
container_name: growqr-gitea
|
|
environment:
|
|
USER_UID: "1000"
|
|
USER_GID: "1000"
|
|
GITEA__server__ROOT_URL: ${GITEA_ROOT_URL:-http://localhost:3001}
|
|
GITEA__server__SSH_PORT: "2222"
|
|
GITEA__security__INSTALL_LOCK: "true"
|
|
GITEA__service__DISABLE_REGISTRATION: "true"
|
|
ports:
|
|
- "3001:3000" # HTTP (Gitea listens on 3000 internally)
|
|
- "2222:2222" # SSH
|
|
volumes:
|
|
- gitea-data:/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "wget -qO- http://localhost:3000/api/v1/version || exit 1"]
|
|
interval: 10s
|
|
timeout: 10s
|
|
retries: 15
|
|
restart: unless-stopped
|
|
|
|
# Self-hosted Rivet engine. The backend's Rivet Kit client connects here.
|
|
# The unified user agent runs as a durable Rivet actor (changes.md §5).
|
|
rivet-engine:
|
|
image: rivetdev/engine:latest
|
|
container_name: growqr-rivet
|
|
ports:
|
|
- "6420:6420" # API
|
|
- "6421:6421" # Guard/edge
|
|
environment:
|
|
RIVET__FILE_SYSTEM__PATH: /data
|
|
RIVET__AUTH__ADMIN_TOKEN: ${RIVET_ADMIN_TOKEN:-dev-admin-token}
|
|
volumes:
|
|
- rivet-data:/data
|
|
restart: unless-stopped
|
|
|
|
# The HTTP backend (Hono + Rivet Kit client + Docker manager).
|
|
# Mounts the host Docker socket so it can spawn per-user OpenCode containers.
|
|
backend:
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile
|
|
container_name: growqr-backend
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
gitea:
|
|
condition: service_healthy
|
|
rivet-engine:
|
|
condition: service_started
|
|
ports:
|
|
- "4000:4000"
|
|
environment:
|
|
PORT: 4000
|
|
NODE_ENV: ${NODE_ENV:-production}
|
|
DATABASE_URL: postgres://${POSTGRES_USER:-growqr}:${POSTGRES_PASSWORD:-growqr}@postgres:5432/${POSTGRES_DB:-growqr}
|
|
# Central Gitea (shared org-wide instance)
|
|
# Internal is backend -> compose service. Public is Git remote URL used by OpenCode/spawned containers.
|
|
GITEA_INTERNAL_URL: http://gitea:3000
|
|
GITEA_PUBLIC_URL: ${GITEA_PUBLIC_URL:-http://host.docker.internal:3001}
|
|
GITEA_ADMIN_USER: ${GITEA_ADMIN_USER:-growqr-admin}
|
|
GITEA_ADMIN_PASSWORD: ${GITEA_ADMIN_PASSWORD:-growqr-admin-dev}
|
|
GITEA_ADMIN_TOKEN: ${GITEA_ADMIN_TOKEN:-}
|
|
GITEA_ORG_NAME: ${GITEA_ORG_NAME:-growqr}
|
|
# Version tracking for image rollouts (changes.md §9)
|
|
OPENCODE_IMAGE_VERSION: ${OPENCODE_IMAGE_VERSION:-dev}
|
|
MIGRATION_VERSION: ${MIGRATION_VERSION:-1}
|
|
PROMPT_VERSION: ${PROMPT_VERSION:-4}
|
|
# Rivet
|
|
RIVET_ENDPOINT: http://default:${RIVET_ADMIN_TOKEN:-dev-admin-token}@rivet-engine:6420
|
|
RIVET_CLIENT_ENDPOINT: ${RIVET_CLIENT_ENDPOINT:-http://127.0.0.1:4000/api/rivet}
|
|
# Auth
|
|
CLERK_SECRET_KEY: ${CLERK_SECRET_KEY}
|
|
CLERK_PUBLISHABLE_KEY: ${CLERK_PUBLISHABLE_KEY}
|
|
SERVICE_TOKEN: ${SERVICE_TOKEN:-dev-service-token}
|
|
A2A_ALLOWED_KEY: ${A2A_ALLOWED_KEY:-dev-a2a-key}
|
|
# LLM
|
|
OPENCODE_API_KEY: ${OPENCODE_API_KEY}
|
|
LLM_PROVIDER: ${LLM_PROVIDER:-opencode}
|
|
LLM_BASE_URL: ${LLM_BASE_URL:-https://opencode.ai/zen/v1}
|
|
LLM_MODEL: ${LLM_MODEL:-kimi-k2.6}
|
|
GROW_AGENT_MODEL: ${GROW_AGENT_MODEL:-kimi-k2.6}
|
|
# Per-user OpenCode containers
|
|
OPENCODE_IMAGE: ${OPENCODE_IMAGE:-growqr/opencode:dev}
|
|
USER_CONTAINER_HOST: ${USER_CONTAINER_HOST:-host.docker.internal}
|
|
USER_DATA_ROOT: /data/users
|
|
USER_PORT_RANGE_START: 20000
|
|
USER_PORT_RANGE_END: 29999
|
|
# Microservices
|
|
INTERVIEW_SERVICE_URL: ${INTERVIEW_SERVICE_URL:-http://host.docker.internal:8007}
|
|
ROLEPLAY_SERVICE_URL: ${ROLEPLAY_SERVICE_URL:-http://host.docker.internal:8008}
|
|
QSCORE_SERVICE_URL: ${QSCORE_SERVICE_URL:-http://host.docker.internal:8000}
|
|
RESUME_SERVICE_URL: ${RESUME_SERVICE_URL:-http://host.docker.internal:8002}
|
|
# Frontend
|
|
FRONTEND_ORIGIN: ${FRONTEND_ORIGIN:-http://localhost:3000}
|
|
volumes:
|
|
# Docker-out-of-Docker: backend uses host Docker to spawn per-user OpenCode containers.
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
# Shared host dir that per-user containers will also bind-mount their
|
|
# workspace from (so backend and spawned containers see the same files).
|
|
- ./.data/users:/data/users
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "wget -qO- http://localhost:4000/healthz || exit 1"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 6
|
|
restart: unless-stopped
|
|
|
|
# Only per-user OpenCode containers are spawned dynamically now.
|
|
# Gitea is a central shared service defined above.
|
|
# See src/docker/manager.ts for the per-user OpenCode lifecycle.
|
|
|
|
volumes:
|
|
rivet-data:
|
|
postgres-data:
|
|
gitea-data:
|