networks: r2r-network: driver: bridge attachable: true labels: - "com.docker.compose.recreate=always" volumes: hatchet_certs: name: ${VOLUME_HATCHET_CERTS:-hatchet_certs} hatchet_config: name: ${VOLUME_HATCHET_CONFIG:-hatchet_config} hatchet_api_key: name: ${VOLUME_HATCHET_API_KEY:-hatchet_api_key} postgres_data: name: ${VOLUME_POSTGRES_DATA:-postgres_data} hatchet_rabbitmq_data: name: ${VOLUME_HATCHET_RABBITMQ_DATA:-hatchet_rabbitmq_data} hatchet_rabbitmq_conf: name: ${VOLUME_HATCHET_RABBITMQ_CONF:-hatchet_rabbitmq_conf} hatchet_postgres_data: name: ${VOLUME_HATCHET_POSTGRES_DATA:-hatchet_postgres_data} services: postgres: image: pgvector/pgvector:pg16 profiles: [postgres] environment: - POSTGRES_USER=${R2R_POSTGRES_USER:-postgres} - POSTGRES_PASSWORD=${R2R_POSTGRES_PASSWORD:-postgres} - POSTGRES_HOST=${R2R_POSTGRES_HOST:-postgres} - POSTGRES_PORT=${R2R_POSTGRES_PORT:-5432} - POSTGRES_MAX_CONNECTIONS=${R2R_POSTGRES_MAX_CONNECTIONS:-1024} - PGPORT=${R2R_POSTGRES_PORT:-5432} volumes: - postgres_data:/var/lib/postgresql/data networks: - r2r-network ports: - "${R2R_POSTGRES_PORT:-5432}:${R2R_POSTGRES_PORT:-5432}" healthcheck: test: ["CMD-SHELL", "pg_isready -U ${R2R_POSTGRES_USER:-postgres}"] interval: 10s timeout: 5s retries: 5 restart: on-failure command: > postgres -c max_connections=${R2R_POSTGRES_MAX_CONNECTIONS:-1024} hatchet-postgres: image: postgres:latest environment: POSTGRES_DB: ${HATCHET_POSTGRES_DBNAME:-hatchet} POSTGRES_USER: ${HATCHET_POSTGRES_USER:-hatchet_user} POSTGRES_PASSWORD: ${HATCHET_POSTGRES_PASSWORD:-hatchet_password} volumes: - hatchet_postgres_data:/var/lib/postgresql/data networks: - r2r-network healthcheck: test: ["CMD-SHELL", "pg_isready -U ${HATCHET_POSTGRES_USER:-hatchet_user} -d ${HATCHET_POSTGRES_DBNAME:-hatchet}"] interval: 10s timeout: 5s retries: 5 hatchet-rabbitmq: image: "rabbitmq:3-management" hostname: "hatchet-rabbitmq" ports: - "${R2R_RABBITMQ_PORT:-5673}:5672" - "${R2R_RABBITMQ_MGMT_PORT:-15673}:15672" environment: RABBITMQ_DEFAULT_USER: "user" RABBITMQ_DEFAULT_PASS: "password" volumes: - hatchet_rabbitmq_data:/var/lib/rabbitmq - hatchet_rabbitmq_conf:/etc/rabbitmq/rabbitmq.conf healthcheck: test: ["CMD", "rabbitmqctl", "status"] interval: 10s timeout: 10s retries: 5 networks: - r2r-network hatchet-create-db: image: postgres:latest command: > sh -c " set -e echo 'Waiting for PostgreSQL to be ready...' while ! pg_isready -h hatchet-postgres -p 5432 -U ${HATCHET_POSTGRES_USER:-hatchet_user}; do sleep 1 done echo 'PostgreSQL is ready, checking if database exists...' if ! PGPASSWORD=${HATCHET_POSTGRES_PASSWORD:-hatchet_password} psql -h hatchet-postgres -p 5432 -U ${HATCHET_POSTGRES_USER:-hatchet_user} -lqt | grep -qw ${HATCHET_POSTGRES_DBNAME:-hatchet}; then echo 'Database does not exist, creating it...' PGPASSWORD=${HATCHET_POSTGRES_PASSWORD:-hatchet_password} createdb -h hatchet-postgres -p 5432 -U ${HATCHET_POSTGRES_USER:-hatchet_user} -w ${HATCHET_POSTGRES_DBNAME:-hatchet} else echo 'Database already exists, skipping creation.' fi " environment: DATABASE_URL: "postgres://${HATCHET_POSTGRES_USER:-hatchet_user}:${HATCHET_POSTGRES_PASSWORD:-hatchet_password}@hatchet-postgres:5432/${HATCHET_POSTGRES_DBNAME:-hatchet}?sslmode=disable" networks: - r2r-network hatchet-migration: image: ghcr.io/hatchet-dev/hatchet/hatchet-migrate:latest environment: DATABASE_URL: "postgres://${HATCHET_POSTGRES_USER:-hatchet_user}:${HATCHET_POSTGRES_PASSWORD:-hatchet_password}@hatchet-postgres:5432/${HATCHET_POSTGRES_DBNAME:-hatchet}?sslmode=disable" depends_on: hatchet-create-db: condition: service_completed_successfully networks: - r2r-network hatchet-setup-config: image: ghcr.io/hatchet-dev/hatchet/hatchet-admin:latest command: /hatchet/hatchet-admin quickstart --skip certs --generated-config-dir /hatchet/config --overwrite=false environment: DATABASE_URL: "postgres://${HATCHET_POSTGRES_USER:-hatchet_user}:${HATCHET_POSTGRES_PASSWORD:-hatchet_password}@hatchet-postgres:5432/${HATCHET_POSTGRES_DBNAME:-hatchet}?sslmode=disable" HATCHET_CLIENT_GRPC_MAX_RECV_MESSAGE_LENGTH: "${HATCHET_CLIENT_GRPC_MAX_RECV_MESSAGE_LENGTH:-134217728}" HATCHET_CLIENT_GRPC_MAX_SEND_MESSAGE_LENGTH: "${HATCHET_CLIENT_GRPC_MAX_SEND_MESSAGE_LENGTH:-134217728}" DATABASE_POSTGRES_PORT: "5432" DATABASE_POSTGRES_HOST: hatchet-postgres DATABASE_POSTGRES_USERNAME: "${HATCHET_POSTGRES_USER:-hatchet_user}" DATABASE_POSTGRES_PASSWORD: "${HATCHET_POSTGRES_PASSWORD:-hatchet_password}" HATCHET_DATABASE_POSTGRES_DB_NAME: "${HATCHET_POSTGRES_DBNAME:-hatchet}" SERVER_TASKQUEUE_RABBITMQ_URL: amqp://user:password@hatchet-rabbitmq:5672/ SERVER_AUTH_COOKIE_DOMAIN: "http://host.docker.internal:${R2R_HATCHET_DASHBOARD_PORT:-7274}" SERVER_URL: "http://host.docker.internal:${R2R_HATCHET_DASHBOARD_PORT:-7274}" SERVER_AUTH_COOKIE_INSECURE: "t" SERVER_GRPC_BIND_ADDRESS: "0.0.0.0" SERVER_GRPC_INSECURE: "t" SERVER_GRPC_BROADCAST_ADDRESS: "hatchet-engine:7077" SERVER_GRPC_MAX_MSG_SIZE: 134217728 volumes: - hatchet_certs:/hatchet/certs - hatchet_config:/hatchet/config depends_on: hatchet-migration: condition: service_completed_successfully hatchet-rabbitmq: condition: service_healthy networks: - r2r-network hatchet-engine: image: ghcr.io/hatchet-dev/hatchet/hatchet-engine:latest command: /hatchet/hatchet-engine --config /hatchet/config restart: on-failure depends_on: hatchet-setup-config: condition: service_completed_successfully ports: - "${R2R_HATCHET_ENGINE_PORT:-7077}:7077" environment: DATABASE_URL: "postgres://${HATCHET_POSTGRES_USER:-hatchet_user}:${HATCHET_POSTGRES_PASSWORD:-hatchet_password}@hatchet-postgres:5432/${HATCHET_POSTGRES_DBNAME:-hatchet}?sslmode=disable" SERVER_GRPC_BROADCAST_ADDRESS: "hatchet-engine:7077" SERVER_GRPC_BIND_ADDRESS: "0.0.0.0" SERVER_GRPC_PORT: "7077" SERVER_GRPC_INSECURE: "t" SERVER_GRPC_MAX_MSG_SIZE: 134217728 volumes: - hatchet_certs:/hatchet/certs - hatchet_config:/hatchet/config networks: - r2r-network healthcheck: test: ["CMD", "wget", "-q", "-O", "-", "http://localhost:8733/live"] interval: 10s timeout: 5s retries: 5 hatchet-dashboard: image: ghcr.io/hatchet-dev/hatchet/hatchet-dashboard:latest command: sh ./entrypoint.sh --config /hatchet/config restart: on-failure depends_on: hatchet-setup-config: condition: service_completed_successfully environment: DATABASE_URL: "postgres://${HATCHET_POSTGRES_USER:-hatchet_user}:${HATCHET_POSTGRES_PASSWORD:-hatchet_password}@hatchet-postgres:5432/${HATCHET_POSTGRES_DBNAME:-hatchet}?sslmode=disable" volumes: - hatchet_certs:/hatchet/certs - hatchet_config:/hatchet/config networks: - r2r-network ports: - "${R2R_HATCHET_DASHBOARD_PORT:-7274}:80" setup-token: image: ghcr.io/hatchet-dev/hatchet/hatchet-admin:latest command: > sh -c " set -e echo 'Starting token creation process...' # Attempt to create token and capture both stdout and stderr TOKEN_OUTPUT=$$(/hatchet/hatchet-admin token create --config /hatchet/config --tenant-id 707d0855-80ab-4e1f-a156-f1c4546cbf52 2>&1) # Extract the token (assuming it's the only part that looks like a JWT) TOKEN=$$(echo \"$$TOKEN_OUTPUT\" | grep -Eo 'eyJ[A-Za-z0-9_-]*\.eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9_-]*') if [ -z \"$$TOKEN\" ]; then echo 'Error: Failed to extract token. Full command output:' >&2 echo \"$$TOKEN_OUTPUT\" >&2 exit 1 fi echo \"$$TOKEN\" > /tmp/hatchet_api_key echo 'Token created and saved to /tmp/hatchet_api_key' # Copy token to final destination echo -n \"$$TOKEN\" > /hatchet_api_key/api_key.txt echo 'Token copied to /hatchet_api_key/api_key.txt' # Verify token was copied correctly if [ \"$$(cat /tmp/hatchet_api_key)\" != \"$(cat /hatchet_api_key/api_key.txt)\" ]; then echo 'Error: Token copy failed, files do not match' >&2 echo 'Content of /tmp/hatchet_api_key:' cat /tmp/hatchet_api_key echo 'Content of /hatchet_api_key/api_key.txt:' cat /hatchet_api_key/api_key.txt exit 1 fi echo 'Hatchet API key has been saved successfully' echo 'Token length:' $${#TOKEN} echo 'Token (first 20 chars):' $${TOKEN:0:20} echo 'Token structure:' $$(echo $$TOKEN | awk -F. '{print NF-1}') 'parts' # Check each part of the token for i in 1 2 3; do PART=$$(echo $$TOKEN | cut -d. -f$$i) echo 'Part' $$i 'length:' $${#PART} echo 'Part' $$i 'base64 check:' $$(echo $$PART | base64 -d >/dev/null 2>&1 && echo 'Valid' || echo 'Invalid') done # Final validation attempt if ! echo $$TOKEN | awk -F. '{print $$2}' | base64 -d 2>/dev/null | jq . >/dev/null 2>&1; then echo 'Warning: Token payload is not valid JSON when base64 decoded' >&2 else echo 'Token payload appears to be valid JSON' fi " networks: - r2r-network volumes: - hatchet_certs:/hatchet/certs - hatchet_config:/hatchet/config - hatchet_api_key:/hatchet_api_key depends_on: hatchet-setup-config: condition: service_completed_successfully unstructured: image: ${UNSTRUCTURED_IMAGE:-ragtoriches/unst-prod} networks: - r2r-network healthcheck: test: ["CMD", "curl", "-f", "http://localhost:7275/health"] interval: 10s timeout: 5s retries: 5 graph_clustering: image: ${GRAPH_CLUSTERING_IMAGE:-ragtoriches/cluster-prod} ports: - "${R2R_GRAPH_CLUSTERING_PORT:-7276}:7276" networks: - r2r-network healthcheck: test: ["CMD", "curl", "-f", "http://localhost:7276/health"] interval: 10s timeout: 5s retries: 5 r2r: image: ${R2R_IMAGE:-ragtoriches/prod:latest} build: context: . args: PORT: ${R2R_PORT:-7272} R2R_PORT: ${R2R_PORT:-7272} HOST: ${R2R_HOST:-0.0.0.0} R2R_HOST: ${R2R_HOST:-0.0.0.0} environment: - PYTHONUNBUFFERED=1 - R2R_PORT=${R2R_PORT:-7272} - R2R_HOST=${R2R_HOST:-0.0.0.0} # R2R - R2R_CONFIG_NAME=${R2R_CONFIG_NAME:-} - R2R_CONFIG_PATH=${R2R_CONFIG_PATH:-} - R2R_PROJECT_NAME=${R2R_PROJECT_NAME:-r2r_default} # Postgres - R2R_POSTGRES_USER=${R2R_POSTGRES_USER:-postgres} - R2R_POSTGRES_PASSWORD=${R2R_POSTGRES_PASSWORD:-postgres} - R2R_POSTGRES_HOST=${R2R_POSTGRES_HOST:-postgres} - R2R_POSTGRES_PORT=${R2R_POSTGRES_PORT:-5432} - R2R_POSTGRES_DBNAME=${R2R_POSTGRES_DBNAME:-postgres} - R2R_POSTGRES_PROJECT_NAME=${R2R_POSTGRES_PROJECT_NAME:-r2r_default} - R2R_POSTGRES_MAX_CONNECTIONS=${R2R_POSTGRES_MAX_CONNECTIONS:-1024} - R2R_POSTGRES_STATEMENT_CACHE_SIZE=${R2R_POSTGRES_STATEMENT_CACHE_SIZE:-100} # OpenAI - OPENAI_API_KEY=${OPENAI_API_KEY:-} - OPENAI_API_BASE=${OPENAI_API_BASE:-} # Anthropic - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-} # Azure - AZURE_API_KEY=${AZURE_API_KEY:-} - AZURE_API_BASE=${AZURE_API_BASE:-} - AZURE_API_VERSION=${AZURE_API_VERSION:-} # Google Vertex AI - GOOGLE_APPLICATION_CREDENTIALS=${GOOGLE_APPLICATION_CREDENTIALS:-} - VERTEX_PROJECT=${VERTEX_PROJECT:-} - VERTEX_LOCATION=${VERTEX_LOCATION:-} # AWS Bedrock - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:-} - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:-} - AWS_REGION_NAME=${AWS_REGION_NAME:-} # Groq - GROQ_API_KEY=${GROQ_API_KEY:-} # Cohere - COHERE_API_KEY=${COHERE_API_KEY:-} # Anyscale - ANYSCALE_API_KEY=${ANYSCALE_API_KEY:-} # Ollama - OLLAMA_API_BASE=${OLLAMA_API_BASE:-http://host.docker.internal:11434} # Huggingface - HUGGINGFACE_API_BASE=${HUGGINGFACE_API_BASE:-http://host.docker.internal:8080} - HUGGINGFACE_API_KEY=${HUGGINGFACE_API_KEY} # Unstructured - UNSTRUCTURED_API_KEY=${UNSTRUCTURED_API_KEY:-} - UNSTRUCTURED_API_URL=${UNSTRUCTURED_API_URL:-https://api.unstructured.io/general/v0/general} - UNSTRUCTURED_SERVICE_URL=${UNSTRUCTURED_SERVICE_URL:-http://unstructured:7275} - UNSTRUCTURED_NUM_WORKERS=${UNSTRUCTURED_NUM_WORKERS:-10} # Hatchet - HATCHET_CLIENT_TLS_STRATEGY=none - HATCHET_CLIENT_GRPC_MAX_RECV_MESSAGE_LENGTH=${HATCHET_CLIENT_GRPC_MAX_RECV_MESSAGE_LENGTH:-134217728} - HATCHET_CLIENT_GRPC_MAX_SEND_MESSAGE_LENGTH=${HATCHET_CLIENT_GRPC_MAX_SEND_MESSAGE_LENGTH:-134217728} # Graphologic - CLUSTERING_SERVICE_URL=http://graph_clustering:7276 command: > sh -c ' if [ -z "$${HATCHET_CLIENT_TOKEN}" ]; then export HATCHET_CLIENT_TOKEN=$$(cat /hatchet_api_key/api_key.txt) fi exec uvicorn core.main.app_entry:app --host $${R2R_HOST} --port $${R2R_PORT} ' networks: - r2r-network healthcheck: test: ["CMD", "curl", "-f", "http://localhost:${R2R_PORT:-7272}/v3/health"] interval: 6s timeout: 5s retries: 5 restart: on-failure volumes: - ${R2R_CONFIG_PATH:-/}:${R2R_CONFIG_PATH:-/app/config} - hatchet_api_key:/hatchet_api_key:ro extra_hosts: - host.docker.internal:host-gateway depends_on: setup-token: condition: service_completed_successfully unstructured: condition: service_healthy r2r-dashboard: image: emrgntcmplxty/r2r-dashboard:latest environment: - NEXT_PUBLIC_R2R_DEPLOYMENT_URL=${R2R_DEPLOYMENT_URL:-http://localhost:7272} - NEXT_PUBLIC_HATCHET_DASHBOARD_URL=${HATCHET_DASHBOARD_URL:-http://localhost:${R2R_HATCHET_DASHBOARD_PORT:-7274}} networks: - r2r-network ports: - "${R2R_DASHBOARD_PORT:-7273}:3000" nginx: image: nginx:latest ports: - "${R2R_NGINX_PORT:-7280}:80" volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro depends_on: r2r: condition: service_healthy networks: - r2r-network deploy: resources: limits: cpus: '0.5' memory: 512M healthcheck: test: ["CMD", "curl", "-f", "http://localhost/health"] interval: 10s timeout: 5s retries: 3