# FILE: infra/base/infrastructure.yaml # Infrastructure Services for AI Tax Agent # Environment-agnostic - use with environment-specific .env files # Deploy with: ./infra/scripts/deploy.sh infrastructure networks: frontend: external: true name: frontend backend: external: true name: backend volumes: postgres_data: neo4j_data: neo4j_logs: qdrant_data: minio_data: vault_data: redis_data: nats_data: services: # Secrets Management vault: image: hashicorp/vault:1.15 container_name: vault restart: unless-stopped networks: - backend - frontend volumes: - vault_data:/vault/data environment: VAULT_DEV_ROOT_TOKEN_ID: ${VAULT_DEV_ROOT_TOKEN_ID} VAULT_DEV_LISTEN_ADDRESS: 0.0.0.0:8200 command: vault server -dev -dev-listen-address=0.0.0.0:8200 cap_add: - IPC_LOCK labels: - "traefik.enable=true" - "traefik.http.routers.vault.rule=Host(`vault.${DOMAIN}`)" - "traefik.http.routers.vault.entrypoints=websecure" - "traefik.http.routers.vault.tls=true" - "traefik.http.routers.vault.tls.certresolver=godaddy" - "traefik.http.routers.vault.middlewares=authentik-forwardauth@file" - "traefik.http.services.vault.loadbalancer.server.port=8200" # Object Storage minio: image: minio/minio:RELEASE.2025-09-07T16-13-09Z container_name: minio restart: unless-stopped networks: - backend - frontend volumes: - minio_data:/data environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD} MINIO_BROWSER_REDIRECT_URL: https://minio.${DOMAIN} command: server /data --address ":9092" --console-address ":9093" healthcheck: test: ["CMD", "mc", "--version"] interval: 30s timeout: 20s retries: 3 labels: - "traefik.enable=true" - "traefik.http.routers.minio-api.rule=Host(`minio-api.${DOMAIN}`)" - "traefik.http.routers.minio-api.entrypoints=websecure" - "traefik.http.routers.minio-api.tls=true" - "traefik.http.routers.minio-api.tls.certresolver=godaddy" - "traefik.http.routers.minio-api.middlewares=authentik-forwardauth@file" - "traefik.http.routers.minio-api.service=minio-api" - "traefik.http.services.minio-api.loadbalancer.server.port=9092" - "traefik.http.routers.minio-console.rule=Host(`minio.${DOMAIN}`)" - "traefik.http.routers.minio-console.entrypoints=websecure" - "traefik.http.routers.minio-console.tls=true" - "traefik.http.routers.minio-console.tls.certresolver=godaddy" - "traefik.http.routers.minio-console.middlewares=authentik-forwardauth@file" - "traefik.http.routers.minio-console.service=minio-console" - "traefik.http.services.minio-console.loadbalancer.server.port=9093" # Vector Database qdrant: image: qdrant/qdrant:v1.7.4 container_name: qdrant restart: unless-stopped networks: - backend - frontend volumes: - qdrant_data:/qdrant/storage environment: QDRANT__SERVICE__GRPC_PORT: ${QDRANT__SERVICE__GRPC_PORT:-6334} QDRANT__SERVICE__HTTP_PORT: 6333 QDRANT__LOG_LEVEL: INFO labels: - "traefik.enable=true" - "traefik.http.routers.qdrant.rule=Host(`qdrant.${DOMAIN}`)" - "traefik.http.routers.qdrant.entrypoints=websecure" - "traefik.http.routers.qdrant.tls=true" - "traefik.http.routers.qdrant.tls.certresolver=godaddy" - "traefik.http.routers.qdrant.middlewares=authentik-forwardauth@file" - "traefik.http.services.qdrant.loadbalancer.server.port=6333" # Knowledge Graph Database neo4j: image: neo4j:5.15-community container_name: neo4j restart: unless-stopped networks: - backend - frontend volumes: - neo4j_data:/data - neo4j_logs:/logs environment: NEO4J_AUTH: neo4j/${NEO4J_PASSWORD} NEO4J_PLUGINS: '["apoc", "graph-data-science"]' NEO4J_dbms_security_procedures_unrestricted: gds.*,apoc.* NEO4J_dbms_security_procedures_allowlist: gds.*,apoc.* NEO4J_apoc_export_file_enabled: true NEO4J_apoc_import_file_enabled: true NEO4J_apoc_import_file_use__neo4j__config: true labels: - "traefik.enable=true" - "traefik.http.routers.neo4j.rule=Host(`neo4j.${DOMAIN}`)" - "traefik.http.routers.neo4j.entrypoints=websecure" - "traefik.http.routers.neo4j.tls=true" - "traefik.http.routers.neo4j.tls.certresolver=godaddy" - "traefik.http.routers.neo4j.middlewares=authentik-forwardauth@file" - "traefik.http.services.neo4j.loadbalancer.server.port=7474" # Secure Client Data Store postgres: image: postgres:15-alpine container_name: postgres restart: unless-stopped networks: - backend volumes: - postgres_data:/var/lib/postgresql/data environment: POSTGRES_DB: tax_system POSTGRES_USER: postgres POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_INITDB_ARGS: "--auth-host=scram-sha-256" command: > postgres -c shared_preload_libraries=pg_stat_statements -c pg_stat_statements.track=all -c max_connections=200 -c shared_buffers=256MB -c effective_cache_size=1GB -c maintenance_work_mem=64MB -c checkpoint_completion_target=0.9 -c wal_buffers=16MB -c default_statistics_target=100 -c random_page_cost=1.1 -c effective_io_concurrency=200 healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 30s timeout: 10s retries: 3 # Cache & Session Store redis: image: redis:7-alpine container_name: redis restart: unless-stopped networks: - backend volumes: - redis_data:/data command: > redis-server --appendonly yes --appendfsync everysec --maxmemory 512mb --maxmemory-policy allkeys-lru healthcheck: test: ["CMD-SHELL", "redis-cli ping | grep PONG"] interval: 30s timeout: 10s retries: 3 # Message Broker & Event Streaming nats: image: nats:2.10-alpine container_name: nats restart: unless-stopped networks: - backend - frontend volumes: - nats_data:/data command: > --jetstream --store_dir=/data --http_port=8222 environment: NATS_LOG_LEVEL: ${NATS_LOG_LEVEL:-info} healthcheck: test: [ "CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8222/healthz", ] interval: 30s timeout: 10s retries: 3 labels: - "traefik.enable=true" - "traefik.http.routers.nats-monitor.rule=Host(`nats.${DOMAIN}`)" - "traefik.http.routers.nats-monitor.entrypoints=websecure" - "traefik.http.routers.nats-monitor.tls=true" - "traefik.http.routers.nats-monitor.tls.certresolver=godaddy" - "traefik.http.routers.nats-monitor.middlewares=authentik-forwardauth@file" - "traefik.http.services.nats-monitor.loadbalancer.server.port=8222"