services: postgres: image: pgvector/pgvector:pg17 restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER:-twisted} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-twisted} POSTGRES_DB: ${POSTGRES_DB:-twisted} volumes: - twisted-postgres:/var/lib/postgresql/data healthcheck: test: [ "CMD-SHELL", "pg_isready -h localhost -p 5432 -U ${POSTGRES_USER:-twisted} -d ${POSTGRES_DB:-twisted}", ] interval: 10s timeout: 5s retries: 5 expose: - "5432" migrate: image: ${TWISTER_IMAGE:-twisted-api:latest} command: ["twister", "migrate"] restart: "no" environment: DATABASE_URL: ${DATABASE_URL:-postgresql://${POSTGRES_USER:-twisted}:${POSTGRES_PASSWORD:-twisted}@postgres:5432/${POSTGRES_DB:-twisted}?sslmode=disable} LOG_LEVEL: ${LOG_LEVEL:-info} LOG_FORMAT: ${LOG_FORMAT:-json} depends_on: postgres: condition: service_healthy api: image: ${TWISTER_IMAGE:-twisted-api:latest} build: context: ./packages/api dockerfile: Dockerfile command: ["twister", "api"] restart: unless-stopped environment: DATABASE_URL: ${DATABASE_URL:-postgresql://${POSTGRES_USER:-twisted}:${POSTGRES_PASSWORD:-twisted}@postgres:5432/${POSTGRES_DB:-twisted}?sslmode=disable} HTTP_BIND_ADDR: ${HTTP_BIND_ADDR:-:8080} LOG_LEVEL: ${LOG_LEVEL:-info} LOG_FORMAT: ${LOG_FORMAT:-json} SEARCH_DEFAULT_LIMIT: ${SEARCH_DEFAULT_LIMIT:-20} SEARCH_MAX_LIMIT: ${SEARCH_MAX_LIMIT:-100} SEARCH_DEFAULT_MODE: ${SEARCH_DEFAULT_MODE:-keyword} READ_THROUGH_MODE: ${READ_THROUGH_MODE:-missing} READ_THROUGH_COLLECTIONS: ${READ_THROUGH_COLLECTIONS:-} READ_THROUGH_MAX_ATTEMPTS: ${READ_THROUGH_MAX_ATTEMPTS:-5} INDEXED_COLLECTIONS: ${INDEXED_COLLECTIONS:-} ENABLE_ADMIN_ENDPOINTS: ${ENABLE_ADMIN_ENDPOINTS:-false} ADMIN_AUTH_TOKEN: ${ADMIN_AUTH_TOKEN:-} OAUTH_CLIENT_ID: ${OAUTH_CLIENT_ID:-} OAUTH_REDIRECT_URIS: ${OAUTH_REDIRECT_URIS:-} depends_on: migrate: condition: service_completed_successfully expose: - "8080" indexer: image: ${TWISTER_IMAGE:-twisted-api:latest} command: ["twister", "indexer"] restart: unless-stopped environment: DATABASE_URL: ${DATABASE_URL:-postgresql://${POSTGRES_USER:-twisted}:${POSTGRES_PASSWORD:-twisted}@postgres:5432/${POSTGRES_DB:-twisted}?sslmode=disable} INDEXER_HEALTH_ADDR: ${INDEXER_HEALTH_ADDR:-:9090} LOG_LEVEL: ${LOG_LEVEL:-info} LOG_FORMAT: ${LOG_FORMAT:-json} TAP_URL: ${TAP_URL:-ws://tap:2480/channel} TAP_AUTH_PASSWORD: ${TAP_AUTH_PASSWORD:?TAP_AUTH_PASSWORD is required} INDEXED_COLLECTIONS: ${INDEXED_COLLECTIONS:?INDEXED_COLLECTIONS is required} ENABLE_INGEST_ENRICHMENT: ${ENABLE_INGEST_ENRICHMENT:-true} depends_on: migrate: condition: service_completed_successfully tap: condition: service_started expose: - "9090" tap: image: ghcr.io/bluesky-social/indigo/tap:sha-4f47add43060c27e8a37d9d76482ecddf001fcd8 restart: unless-stopped environment: TAP_BIND: :2480 TAP_DATABASE_URL: ${TAP_DATABASE_URL:-sqlite:///data/tap.db} TAP_ADMIN_PASSWORD: ${TAP_AUTH_PASSWORD:?TAP_AUTH_PASSWORD is required} TAP_LOG_LEVEL: ${TAP_LOG_LEVEL:-info} TAP_COLLECTION_FILTERS: ${TAP_COLLECTION_FILTERS:-} volumes: - tap-data:/data expose: - "2480" llama-embeddings: image: ghcr.io/ggml-org/llama.cpp:server restart: unless-stopped environment: HF_HOME: /models/hf-cache LLAMA_CACHE: /models command: - --hf-repo - ${LLAMA_MODEL_REPO:-nomic-ai/nomic-embed-text-v1.5-GGUF} - --hf-file - ${LLAMA_MODEL_FILE:-nomic-embed-text-v1.5.Q8_0.gguf} - --embeddings - --pooling - mean - --ctx-size - ${LLAMA_CONTEXT_SIZE:-2048} - --host - 0.0.0.0 - --port - "8080" volumes: - twisted-llama:/models expose: - "8080" volumes: twisted-postgres: tap-data: twisted-llama: