Ctrl K
ComunidadGuías…

docker-compose.yml

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
version: "3.8"

services:
  api:
    build: ./services/api-rs
    container_name: gctrl-api
    ports:
      - "4000:4000"
    environment:
      - NODE_ENV=development
      - PHOENIX_OTLP_URL=${PHOENIX_OTLP_URL:-}
      - PHOENIX_SERVICE_NAME=gctrl-api
      - PORT=4000
      - RUST_LOG=${RUST_LOG:-info,gctrl_api=debug}
      - DATABASE_URL=postgresql://GCTRL:GCTRL@postgres:5432/GCTRL
      - REDIS_URL=redis://redis:6379
      - NEO4J_URI=bolt://neo4j:7687
      - NEO4J_USER=neo4j
      - NEO4J_PASSWORD=password
      - JWT_SECRET=${JWT_SECRET:-GCTRL-dev-jwt-secret-change-in-production}
      - JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET:-GCTRL-dev-refresh-secret-change-in-production}
      # AES-256-GCM key (base64 of 32 bytes) for at-rest secret encryption.
      # MUST be set & rotated in prod; losing it makes encrypted secrets unrecoverable.
      - GCTRL_SECRET_KEY=${GCTRL_SECRET_KEY:-rjFL483r7bwkbIpLSqYokmRqmZvq4Jt0XHUrEqczQ9g=}
      - MAIL_HOST=maildev
      - MAIL_PORT=1025
      # Origin the user's browser actually hits. The dockerized web (nginx) is
      # published on 3001 below, so the OAuth redirect_uri sent to Google and the
      # post-login redirect must point there too. Override via .env for prod/dev.
      - FRONTEND_URL=${FRONTEND_URL:-http://localhost:3001}
      - KEX_WORKER_URL=http://kex:4010
      - FUSE_URL=http://fuse:4020
      - INTERNAL_API_SECRET=${INTERNAL_API_SECRET:-gctrl-dev-internal-secret-change-me}
      - QDRANT_URL=http://qdrant:6333
      - QDRANT_API_KEY=${QDRANT_API_KEY:-}
      - OLLAMA_BASE=http://ollama:11434
      # Cloak Gateway cloud upstreams (default: the official hosts, pinned).
      # - ANTHROPIC_BASE=https://api.anthropic.com
      # - OPENAI_BASE=https://api.openai.com
      # Skips the official-host pin on those bases. Dev only, never in prod.
      # - GCTRL_CLOAK_UPSTREAM_UNPINNED=1
      # OAuth Connectors (set in .env or override here)
      - GCTRL_BASE_URL=${GCTRL_BASE_URL:-http://localhost:4000}
      # Root under which server-side Obsidian folder vaults must live (read-only mount below).
      - GCTRL_VAULTS_ROOT=/vaults
      # Remote MCP gateway (/api/agent/mcp) — lets external multi-agent
      # orchestrators drive the Pi harness over the network. OFF by default;
      # every call is api-key authed, clearance-scoped and audited. On by default
      # so the MCP gateway is reachable right after install; set to false to disable.
      - GCTRL_AGENT_GATEWAY_ENABLED=${GCTRL_AGENT_GATEWAY_ENABLED:-true}
      # ── Single source of truth for user-visible endpoint URLs ──────────────
      # The UI fetches GET /api/config/public and derives EVERY displayed URL
      # (MCP/n8n setup strings, Neo4j Browser links, agent health) from one
      # canonical external origin = FRONTEND_URL (above). Change the published
      # ports + FRONTEND_URL here / in .env and all displayed references update
      # automatically — no hardcoded host:port is baked into the web bundle.
      # The two vars below override the auto-derived Neo4j Browser / agent URLs.
      # Leave empty to let the frontend derive http://<browser-host>:7474 / :7070.
      - GCTRL_NEO4J_BROWSER_URL=${GCTRL_NEO4J_BROWSER_URL:-}
      - GCTRL_AGENT_URL=${GCTRL_AGENT_URL:-}
      # A4 memory-maintenance worker cadence (seconds). Default 600 (10 min).
      - GCTRL_MEMORY_TICK_SECS=${GCTRL_MEMORY_TICK_SECS:-600}
      - GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID:-}
      - GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET:-}
      - MICROSOFT_CLIENT_ID=${MICROSOFT_CLIENT_ID:-}
      - MICROSOFT_CLIENT_SECRET=${MICROSOFT_CLIENT_SECRET:-}
      - SLACK_CLIENT_ID=${SLACK_CLIENT_ID:-}
      - SLACK_CLIENT_SECRET=${SLACK_CLIENT_SECRET:-}
      - GITHUB_CLIENT_ID=${GITHUB_CLIENT_ID:-}
      - GITHUB_CLIENT_SECRET=${GITHUB_CLIENT_SECRET:-}
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_started
    volumes:
      # Expose operator-chosen vault folders read-only. The API reads .md bytes
      # from here for server-side Obsidian folder vaults (under GCTRL_VAULTS_ROOT).
      - ${GCTRL_VAULTS_ROOT_HOST:-./vaults}:/vaults:ro
      # The in-dashboard "Update now" button drives docker via this socket
      # (pull + recreate). Without it the update executor can't reach docker
      # (matches deploy/compose-template.yml, which already mounts it).
      - /var/run/docker.sock:/var/run/docker.sock:ro
      # Host hardware profile (true host RAM/GPU). Host RAM is unknowable from
      # inside the container (/proc only sees the WSL2 VM), so it's supplied here.
      # WITHOUT this mount the file is lost on every container recreate and the
      # Settings "System (host)" view + Re-scan go blank. See deploy/hardware.json.
      - ./deploy/hardware.json:/app/hardware.json:ro
    networks:
      - GCTRL
      - ollama-net
    restart: unless-stopped

  web:
    build: ./services/web
    container_name: gctrl-web
    ports:
      - "3001:80"
    depends_on:
      - api
    networks:
      - GCTRL
    restart: unless-stopped

  # gctrl-agent: license enforcement — disabled for local dev.
  # Re-enable for prod testing by pulling ghcr.io/gctrl-tech/agent:latest
  # after `docker login ghcr.io`.

  kex:
    build: ./services/kex
    container_name: gctrl-kex
    ports:
      - "127.0.0.1:4010:4010"
    environment:
      - OLLAMA_BASE=http://ollama:11434
      - NEO4J_URI=bolt://neo4j:7687
      - NEO4J_USER=neo4j
      - NEO4J_PASSWORD=password
      - REDIS_URL=redis://redis:6379
      - QDRANT_URL=http://qdrant:6333
      - QDRANT_API_KEY=${QDRANT_API_KEY:-}
      - QDRANT_COLLECTION=GCTRL_chunks
      - EMBEDDING_MODEL=nomic-embed-text
      - PG_URL=postgresql://GCTRL:GCTRL@postgres:5432/GCTRL
      - PORT=4010
      - INTERNAL_API_SECRET=${INTERNAL_API_SECRET:-gctrl-dev-internal-secret-change-me}
      # Worker credential fetch for keyed OpenAI-compatible runtimes (D7 in
      # docs/superpowers/specs/2026-09-04-mlx-runtime-and-backpressure-design.md).
      - GCTRL_INTERNAL_API_URL=http://api:4000
      - KEX_ENTITY_VERIFY=${KEX_ENTITY_VERIFY:-false}
      - PHOENIX_OTLP_URL=${PHOENIX_OTLP_URL:-}
      - PHOENIX_SERVICE_NAME=gctrl-kex
      - GLINER_MODEL=${GLINER_MODEL:-}
      - GLINER_FALLBACK_MODEL=${GLINER_FALLBACK_MODEL:-}
      - NER_THRESHOLD_BI=${NER_THRESHOLD_BI:-}
    volumes:
      - kex-models:/app/models
    depends_on:
      redis:
        condition: service_started
      postgres:
        condition: service_healthy
    networks:
      - GCTRL
      - ollama-net
    restart: unless-stopped

  fuse:
    build: ./services/fuse
    container_name: gctrl-fuse
    ports:
      - "127.0.0.1:4020:4020"
    environment:
      - NEO4J_URI=bolt://neo4j:7687
      - NEO4J_USER=neo4j
      - NEO4J_PASSWORD=password
      - REDIS_URL=redis://redis:6379
      - PORT=4020
      - SIMILARITY_THRESHOLD=0.85
      - RESOLVER_URL=http://resolver:8080
      # WIKI distillation: Postgres (wiki_pages), Qdrant (grounding chunks),
      # Ollama (page generation). Provider/model configurable; defaults are
      # zero-config local Ollama llama3.2.
      - PG_URL=postgresql://GCTRL:GCTRL@postgres:5432/GCTRL
      - QDRANT_URL=http://qdrant:6333
      - QDRANT_API_KEY=${QDRANT_API_KEY:-}
      - QDRANT_COLLECTION=GCTRL_chunks
      - OLLAMA_BASE=http://ollama:11434
      - INTERNAL_API_SECRET=${INTERNAL_API_SECRET:-gctrl-dev-internal-secret-change-me}
      - GCTRL_INTERNAL_API_URL=http://api:4000
      - GCTRL_DISTILL_PROVIDER=${GCTRL_DISTILL_PROVIDER:-ollama}
      - GCTRL_DISTILL_MODEL=${GCTRL_DISTILL_MODEL:-llama3.2}
      - PHOENIX_OTLP_URL=${PHOENIX_OTLP_URL:-}
      - PHOENIX_SERVICE_NAME=gctrl-fuse
    depends_on:
      redis:
        condition: service_started
      postgres:
        condition: service_healthy
    networks:
      - GCTRL
      - ollama-net
    restart: unless-stopped

  resolver:
    build:
      context: ../DataBorg Github/LIMES-master
      dockerfile: Dockerfile
    container_name: gctrl-resolver
    ports:
      - "8085:8080"
    environment:
      - JDK_JAVA_OPTIONS=-Xmx2G
    command: ["-s"]
    networks:
      - GCTRL
    restart: unless-stopped

  postgres:
    image: postgres:16-alpine
    container_name: gctrl-postgres
    ports:
      - "5433:5432"
    environment:
      - POSTGRES_USER=GCTRL
      - POSTGRES_PASSWORD=GCTRL
      - POSTGRES_DB=GCTRL
    volumes:
      - GCTRL-pgdata:/var/lib/postgresql/data
      - ./shared/db/migrations:/docker-entrypoint-initdb.d
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U GCTRL"]
      interval: 5s
      timeout: 5s
      retries: 5
    networks:
      - GCTRL
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    container_name: gctrl-redis
    ports:
      - "6380:6379"
    networks:
      - GCTRL
    restart: unless-stopped

  maildev:
    image: maildev/maildev
    container_name: gctrl-maildev
    ports:
      - "1081:1080"
      - "1026:1025"
    networks:
      - GCTRL
    restart: unless-stopped

volumes:
  GCTRL-pgdata:
  kex-models:

networks:
  GCTRL:
    driver: bridge
  ollama-net:
    external: true
    name: self-hosted-ai-starter-kit_demo