# ========================================================================= # Maestro — zero-configuration local trial. # # docker compose -f docker-compose.quickstart.yml up -d # open http://localhost:8080 # # Runs the published GHCR images, so nothing is built locally. Everything is # published on 127.0.0.1 only. If something already owns port 8080, pick # another one — MAESTRO_PORT=8090 docker compose -f ... up -d — it is applied # to the proxy, the site address, and the link-building SITE_URL together. # # NOT A DEPLOYMENT. The credentials below are fixed, public, and identical on # every machine that runs this file. They are safe here for exactly two # reasons: nothing is reachable from outside the loopback interface, and # ENVIRONMENT stays `development` — the backend refuses to boot in production # with secrets this weak. To run Maestro for real, use # docker-compose.prod.yml plus your own .env.prod (see docs/DEPLOYMENT.md). # # Chat runs on whichever provider key you add under Settings > API Keys; # Google Gemini has a genuine free tier (no card). Embeddings run locally in # the bundled Ollama service, so RAG needs no key. To run chat locally too: # # docker compose -f docker-compose.quickstart.yml exec ollama ollama pull qwen3.5:9b # # and restart the backend — OLLAMA_CHAT_ENABLED is already true. # # The image tag is pinned to a release rather than `latest` or `main`, so a # clone of any tag runs the code that tag actually shipped. It must be bumped # in the same commit as the release, or the trial silently runs older code than # the README describes. MAESTRO_TAG=main overrides it to the newest build. # # Requires Compose v2.17+ for `service_completed_successfully`. # ========================================================================= name: maestro-quickstart x-trial-logging: &trial-logging driver: json-file options: max-size: "10m" max-file: "3" services: postgres: image: postgres:16-alpine restart: unless-stopped logging: *trial-logging environment: POSTGRES_USER: maestro POSTGRES_PASSWORD: maestro POSTGRES_DB: maestro volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U maestro -d maestro"] interval: 10s timeout: 5s retries: 5 mongo: image: mongo:7 restart: unless-stopped logging: *trial-logging environment: MONGO_INITDB_ROOT_USERNAME: maestro MONGO_INITDB_ROOT_PASSWORD: maestro volumes: - mongodata:/data/db healthcheck: test: - CMD - mongosh - --quiet - -u - maestro - -p - maestro - --authenticationDatabase - admin - --eval - db.adminCommand('ping').ok interval: 10s timeout: 5s retries: 5 qdrant: image: qdrant/qdrant:v1.18.2 restart: unless-stopped logging: *trial-logging volumes: - qdrantdata:/qdrant/storage # No healthcheck: the image is distroless, so no in-container probe can run. redis: image: redis:7-alpine restart: unless-stopped logging: *trial-logging command: - redis-server - --maxmemory - 128mb - --maxmemory-policy - allkeys-lru - --save - "" - --appendonly - "no" healthcheck: test: ["CMD-SHELL", "redis-cli ping | grep -q PONG"] interval: 10s timeout: 5s retries: 5 # Embeddings for RAG. A chat model is not pulled here — see the header for # the one command that adds it. ollama: image: ollama/ollama:latest restart: unless-stopped logging: *trial-logging volumes: - ollamadata:/root/.ollama healthcheck: test: ["CMD", "/bin/ollama", "list"] interval: 10s timeout: 5s retries: 5 start_period: 20s # Idempotent: exits immediately once the model is in the volume. ollama-pull: image: ollama/ollama:latest restart: "no" logging: *trial-logging entrypoint: ["/bin/ollama"] command: ["pull", "nomic-embed-text"] environment: OLLAMA_HOST: http://ollama:11434 depends_on: ollama: condition: service_healthy # Runs `alembic upgrade head` and exits; the API waits for it to succeed. migrate: image: ghcr.io/yigtwxx/maestro-backend:${MAESTRO_TAG:-0.1.2} restart: "no" logging: *trial-logging command: ["alembic", "upgrade", "head"] environment: &backend-env ENVIRONMENT: development POSTGRES_URL: postgresql+asyncpg://maestro:maestro@postgres:5432/maestro MONGODB_URL: mongodb://maestro:maestro@mongo:27017/?authSource=admin MONGODB_DB_NAME: maestro QDRANT_URL: http://qdrant:6333 REDIS_URL: redis://redis:6379/0 # Local-trial values only — see the header. Both are deliberately # readable rather than random: the master key loader accepts base64, hex # or raw UTF-8 as long as it decodes to 32 bytes, and a plain 32-character # string cannot be mistaken for a real credential by a human or by a # secret scanner. Count the characters before changing this line. JWT_SECRET: quickstart-insecure-jwt-secret-not-for-any-real-deployment API_KEY_MASTER_KEY: quickstart-insecure-master-key00 # Console provider: verification links are printed to the backend log. # Verification is off here so the trial needs no mail round-trip at all. EMAIL_PROVIDER: console EMAIL_VERIFICATION_REQUIRED: "false" SITE_URL: http://localhost:${MAESTRO_PORT:-8080} FREE_MODEL_ENDPOINT: http://ollama:11434/v1 EMBEDDING_ENDPOINT: http://ollama:11434/v1 OLLAMA_CHAT_ENABLED: "true" # The Docker socket is not mounted here, so the sandbox stays off. CODE_EXECUTION_ENABLED: "false" TRUST_PROXY_HEADERS: "true" depends_on: postgres: condition: service_healthy backend: image: ghcr.io/yigtwxx/maestro-backend:${MAESTRO_TAG:-0.1.2} restart: unless-stopped logging: *trial-logging environment: *backend-env depends_on: postgres: condition: service_healthy mongo: condition: service_healthy qdrant: condition: service_started redis: condition: service_healthy migrate: condition: service_completed_successfully ollama-pull: condition: service_completed_successfully frontend: image: ghcr.io/yigtwxx/maestro-frontend:${MAESTRO_TAG:-0.1.2} restart: unless-stopped logging: *trial-logging environment: INTERNAL_API_ORIGIN: http://backend:8000 SITE_URL: http://localhost:${MAESTRO_PORT:-8080} depends_on: - backend # Single origin, so the browser needs no baked-in API URL and there is no # CORS. The shared Caddyfile skips certificate provisioning when DOMAIN # carries an explicit http:// scheme. caddy: image: caddy:2-alpine restart: unless-stopped logging: *trial-logging ports: - "127.0.0.1:${MAESTRO_PORT:-8080}:${MAESTRO_PORT:-8080}" environment: DOMAIN: http://localhost:${MAESTRO_PORT:-8080} volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro - caddydata:/data - caddyconfig:/config depends_on: - backend - frontend volumes: pgdata: mongodata: qdrantdata: ollamadata: caddydata: caddyconfig: