x-appks-env: &appks-env RUST_LOG: info APP_HTTP_HOST: 0.0.0.0 APP_HTTP_PORT: 8000 APP_HTTP_WORKERS: 2 APP_HTTP_JSON_LIMIT_BYTES: 10485760 APP_URL: http://localhost:8000 APP_MAIN_DOMAIN: localhost APP_SESSION_SECRET: TC5uuvxDNHLNm-BjZVhHtObtdF1oLL6bPmYlmwbNaGWe00mpWiT2uBJbeFrNYumi4UGI7sVBn83mLTIeKxfHEg APP_SESSION_COOKIE_NAME: sid APP_SESSION_COOKIE_SECURE: "false" APP_SESSION_COOKIE_HTTP_ONLY: "true" APP_SESSION_COOKIE_SAME_SITE: Lax APP_SESSION_COOKIE_PATH: / APP_SESSION_TTL_SECS: 86400 APP_SESSION_MAX_AGE_SECS: 86400 # Postgres APP_DATABASE_URL: postgres://appks:appks@postgres:5432/appks DATABASE_URL: postgres://appks:appks@postgres:5432/appks APP_DATABASE_MAX_CONNECTIONS: 10 APP_DATABASE_MIN_CONNECTIONS: 2 APP_DATABASE_IDLE_TIMEOUT: 600 APP_DATABASE_MAX_LIFETIME: 3600 APP_DATABASE_CONNECTION_TIMEOUT: 8 APP_DATABASE_SCHEMA_SEARCH_PATH: public APP_DATABASE_READ_WRITE_SPLIT: "false" APP_DATABASE_RETRY_ATTEMPTS: 3 APP_DATABASE_RETRY_DELAY: 5 # Redis (cluster mode) APP_REDIS_CLUSTER_ENABLED: "true" APP_REDIS_CLUSTER_NODES: redis://redis-node-0:6379,redis://redis-node-1:6379,redis://redis-node-2:6379,redis://redis-node-3:6379,redis://redis-node-4:6379,redis://redis-node-5:6379 APP_REDIS_READ_FROM_REPLICAS: "false" APP_REDIS_PASSWORD: "" APP_REDIS_MAX_CONNECTIONS: 20 APP_REDIS_MIN_CONNECTIONS: 2 APP_REDIS_IDLE_TIMEOUT: 300 APP_REDIS_CONNECTION_TIMEOUT: 5 APP_REDIS_MAX_RETRIES: 3 APP_REDIS_RETRY_DELAY_MS: 100 APP_REDIS_TLS_ENABLED: "false" APP_REDIS_KEY_PREFIX: "appks:" # etcd APP_ETCD_ENDPOINTS: http://etcd:2379 APP_ETCD_KEY_PREFIX: /appks/ APP_ETCD_CONNECT_TIMEOUT: 5 APP_ETCD_REQUEST_TIMEOUT: 10 APP_ETCD_KEEP_ALIVE_INTERVAL: 10 APP_ETCD_LEASE_TTL: 15 APP_ETCD_MAX_RETRIES: 3 APP_ETCD_REGISTER_SELF: "true" # NATS APP_NATS_URL: nats://nats:4222 APP_NATS_CONNECTION_TIMEOUT: 5 APP_NATS_PING_INTERVAL: 20 APP_NATS_RECONNECT_DELAY: 2 APP_NATS_MAX_RECONNECTS: 60 APP_NATS_STREAM_PREFIX: APPKS APP_NATS_ACK_WAIT_SECS: 30 APP_NATS_MAX_DELIVER: 5 # S3 / MinIO APP_S3_ENDPOINT: http://minio:9000 APP_S3_REGION: us-east-1 APP_S3_ACCESS_KEY: admin APP_S3_SECRET_KEY: mysecret123 APP_S3_BUCKET: appks APP_S3_PATH_STYLE: "true" APP_S3_FORCE_PATH_STYLE: "true" APP_S3_PUBLIC_URL: http://localhost:9000/appks APP_S3_MAX_CONNECTIONS: 50 APP_S3_IDLE_TIMEOUT: 90 APP_S3_CONNECTION_TIMEOUT: 10 APP_S3_MAX_RETRIES: 3 APP_S3_UPLOAD_PART_SIZE: 8388608 APP_S3_MAX_UPLOAD_SIZE: 104857600 APP_S3_PRESIGNED_URL_EXPIRY: 3600 # LRU cache APP_LRU_DEFAULT_CAPACITY: 1000 APP_LRU_DEFAULT_TTL_SECS: 300 APP_LRU_CLEANUP_INTERVAL_SECS: 60 # gRPC APP_RPC_SELF_HOST: 0.0.0.0 APP_RPC_SELF_PORT: 50049 APP_RPC_SELF_REFLECTION: "false" APP_RPC_SELF_SERVICE_NAME: appks APP_RPC_DEFAULT_TIMEOUT_SECS: 10 # AI (disabled by default in compose — set externally) APP_AI_PROVIDER_API_KEY: "" APP_AI_PROVIDER_URL: "" # Qdrant APP_QDRANT_URL: http://qdrant:6334 APP_QDRANT_COLLECTION: appks_embeddings APP_QDRANT_VECTOR_SIZE: 1536 APP_QDRANT_DISTANCE: Cosine APP_QDRANT_MAX_CONNECTIONS: 10 APP_QDRANT_IDLE_TIMEOUT: 300 APP_QDRANT_CONNECTION_TIMEOUT: 10 APP_QDRANT_MAX_RETRIES: 3 APP_QDRANT_TLS_ENABLED: "false" APP_QDRANT_SEARCH_LIMIT: 10 APP_QDRANT_SCORE_THRESHOLD: 0.7 services: # AppKS appks: image: appks restart: unless-stopped ports: - "8000:8000" - "50049:50049" environment: <<: *appks-env depends_on: postgres: condition: service_healthy etcd: condition: service_started nats: condition: service_started minio: condition: service_healthy qdrant: condition: service_started networks: - appks-net # PostgreSQL postgres: image: postgres:17-alpine restart: unless-stopped environment: POSTGRES_USER: appks POSTGRES_PASSWORD: appks POSTGRES_DB: appks ports: - "5432:5432" volumes: - pg_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U appks -d appks"] interval: 5s timeout: 5s retries: 5 networks: - appks-net # Redis Cluster (6 nodes) redis-node-0: image: redis:7-alpine command: redis-server --port 6379 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes restart: unless-stopped ports: - "6379:6379" volumes: - redis_data_0:/data networks: - appks-net redis-node-1: image: redis:7-alpine command: redis-server --port 6379 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes restart: unless-stopped ports: - "6380:6379" volumes: - redis_data_1:/data networks: - appks-net redis-node-2: image: redis:7-alpine command: redis-server --port 6379 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes restart: unless-stopped ports: - "6381:6379" volumes: - redis_data_2:/data networks: - appks-net redis-node-3: image: redis:7-alpine command: redis-server --port 6379 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes restart: unless-stopped ports: - "6382:6379" volumes: - redis_data_3:/data networks: - appks-net redis-node-4: image: redis:7-alpine command: redis-server --port 6379 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes restart: unless-stopped ports: - "6383:6379" volumes: - redis_data_4:/data networks: - appks-net redis-node-5: image: redis:7-alpine command: redis-server --port 6379 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes restart: unless-stopped ports: - "6384:6379" volumes: - redis_data_5:/data networks: - appks-net redis-cluster-init: image: redis:7-alpine depends_on: - redis-node-0 - redis-node-1 - redis-node-2 - redis-node-3 - redis-node-4 - redis-node-5 entrypoint: > sh -c ' echo "Waiting for all Redis nodes to be ready..."; sleep 5; echo "Creating Redis cluster..."; redis-cli --cluster create redis-node-0:6379 redis-node-1:6379 redis-node-2:6379 redis-node-3:6379 redis-node-4:6379 redis-node-5:6379 --cluster-replicas 1 --cluster-yes ' networks: - appks-net # etcd etcd: image: quay.io/coreos/etcd:v3.5 restart: unless-stopped command: > etcd --name etcd --data-dir /etcd-data --listen-client-urls http://0.0.0.0:2379 --advertise-client-urls http://etcd:2379 --listen-peer-urls http://0.0.0.0:2380 --initial-advertise-peer-urls http://etcd:2380 --initial-cluster etcd=http://etcd:2380 --initial-cluster-token appks-etcd --initial-cluster-state new ports: - "2379:2379" - "2380:2380" volumes: - etcd_data:/etcd-data networks: - appks-net # NATS nats: image: nats:2-alpine restart: unless-stopped command: --js --store_dir /data/nats ports: - "4222:4222" - "8222:8222" volumes: - nats_data:/data/nats networks: - appks-net # MinIO (S3-compatible storage) minio: image: minio/minio:latest restart: unless-stopped command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: admin MINIO_ROOT_PASSWORD: mysecret123 ports: - "9000:9000" - "9001:9001" volumes: - minio_data:/data healthcheck: test: ["CMD-SHELL", "mc ready local || exit 1"] interval: 5s timeout: 5s retries: 5 networks: - appks-net # MinIO bucket auto-creation minio-init: image: minio/mc:latest depends_on: minio: condition: service_healthy entrypoint: > sh -c ' mc alias set local http://minio:9000 admin mysecret123; mc mb --ignore-existing local/appks; echo "MinIO bucket appks ready"; exit 0 ' networks: - appks-net # Qdrant (vector database) qdrant: image: qdrant/qdrant:latest restart: unless-stopped ports: - "6333:6333" - "6334:6334" volumes: - qdrant_data:/qdrant/storage networks: - appks-net volumes: pg_data: redis_data_0: redis_data_1: redis_data_2: redis_data_3: redis_data_4: redis_data_5: etcd_data: nats_data: minio_data: qdrant_data: networks: appks-net: driver: bridge