# FILE: infra/compose/docker-compose.local.yml # Traefik (with Authentik ForwardAuth), Authentik, Vault, MinIO, Qdrant, Neo4j, Postgres, Redis, Prometheus/Grafana, Loki, Unleash, all services networks: frontend: external: true name: ai-tax-agent-frontend backend: external: true name: ai-tax-agent-backend volumes: postgres_data: neo4j_data: neo4j_logs: qdrant_data: minio_data: vault_data: redis_data: nats_data: prometheus_data: grafana_data: loki_data: authentik_data: services: # Edge Gateway & Load Balancer aia-traefik: image: docker.io/library/traefik:v3.5.1 container_name: aia-traefik ports: - 80:80 - 443:443 # --> (Optional) Enable Dashboard, don't do in production - 8080:8080 # <-- volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - ../traefik/config/:/etc/traefik/:ro - ../traefik/certs/:/var/traefik/certs/:rw environment: [] env_file: - ../traefik/.provider.env # contains the GoDaddy API Key and Secret networks: - frontend - backend restart: unless-stopped # Identity & SSO aia-authentik-db: image: postgres:15-alpine container_name: aia-authentik-db restart: unless-stopped networks: - backend volumes: - authentik_data:/var/lib/postgresql/data environment: POSTGRES_DB: authentik POSTGRES_USER: authentik POSTGRES_PASSWORD: ${AUTHENTIK_DB_PASSWORD:-authentik} healthcheck: test: ["CMD-SHELL", "pg_isready -U authentik"] interval: 30s timeout: 10s retries: 3 aia-authentik-redis: image: redis:7-alpine container_name: aia-authentik-redis restart: unless-stopped networks: - backend command: --save 60 1 --loglevel warning healthcheck: test: ["CMD-SHELL", "redis-cli ping | grep PONG"] interval: 30s timeout: 10s retries: 3 aia-authentik-server: image: ghcr.io/goauthentik/server:2025.8.3 container_name: aia-authentik-server restart: unless-stopped networks: - backend - frontend command: server environment: AUTHENTIK_REDIS__HOST: aia-authentik-redis AUTHENTIK_POSTGRESQL__HOST: aia-authentik-db AUTHENTIK_POSTGRESQL__USER: authentik AUTHENTIK_POSTGRESQL__NAME: authentik AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_DB_PASSWORD:-authentik} AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:-changeme} AUTHENTIK_ERROR_REPORTING__ENABLED: false # Optional bootstrap for automated setup (create admin and API token) AUTHENTIK_BOOTSTRAP_EMAIL: ${AUTHENTIK_BOOTSTRAP_EMAIL:-admin@local.lan} AUTHENTIK_BOOTSTRAP_PASSWORD: ${AUTHENTIK_BOOTSTRAP_PASSWORD:-admin123} AUTHENTIK_BOOTSTRAP_TOKEN: ${AUTHENTIK_BOOTSTRAP_TOKEN:-} volumes: - ../authentik/media:/media - ../authentik/custom-templates:/templates - ../authentik/bootstrap.yaml:/blueprints/bootstrap.yaml depends_on: - aia-authentik-db - aia-authentik-redis labels: - "traefik.enable=true" - "traefik.http.routers.authentik.rule=Host(`auth.${DOMAIN:-local.lan}`)" - "traefik.http.routers.authentik.entrypoints=websecure" - "traefik.http.routers.authentik.tls=true" - "traefik.docker.network=ai-tax-agent-frontend" - "traefik.http.services.authentik.loadbalancer.server.port=9000" aia-authentik-worker: image: ghcr.io/goauthentik/server:2025.8.3 container_name: aia-authentik-worker restart: unless-stopped networks: - backend command: worker environment: AUTHENTIK_REDIS__HOST: aia-authentik-redis AUTHENTIK_POSTGRESQL__HOST: aia-authentik-db AUTHENTIK_POSTGRESQL__USER: authentik AUTHENTIK_POSTGRESQL__NAME: authentik AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_DB_PASSWORD:-authentik} AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:-changeme} AUTHENTIK_ERROR_REPORTING__ENABLED: false volumes: - ../authentik/media:/media - ../authentik/custom-templates:/templates depends_on: - aia-authentik-db - aia-authentik-redis aia-authentik-outpost: image: ghcr.io/goauthentik/proxy:2025.8.3 container_name: aia-authentik-outpost restart: unless-stopped networks: - backend - frontend environment: AUTHENTIK_HOST: http://aia-authentik-server:9000 AUTHENTIK_INSECURE: true AUTHENTIK_TOKEN: ${AUTHENTIK_OUTPOST_TOKEN:-changeme} AUTHENTIK_REDIS__HOST: aia-authentik-redis AUTHENTIK_REDIS__PORT: 6379 depends_on: - aia-authentik-server - aia-authentik-redis # Secrets Management aia-vault: image: hashicorp/vault:1.15 container_name: aia-vault restart: unless-stopped networks: - backend ports: - "8200:8200" volumes: - vault_data:/vault/data - ../vault/config:/vault/config:ro environment: VAULT_DEV_ROOT_TOKEN_ID: ${VAULT_DEV_ROOT_TOKEN_ID:-root} 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:-local.lan}`)" - "traefik.http.routers.vault.entrypoints=websecure" - "traefik.http.routers.vault.tls=true" - "traefik.http.routers.vault.middlewares=authentik-forwardauth@file" - "traefik.http.services.vault.loadbalancer.server.port=8200" # Object Storage aia-minio: image: minio/minio:RELEASE.2025-09-07T16-13-09Z container_name: aia-minio restart: unless-stopped networks: - backend ports: - "9092:9092" - "9093:9093" volumes: - minio_data:/data environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minio} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-miniopass} MINIO_BROWSER_REDIRECT_URL: https://minio.${DOMAIN:-local.lan} 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:-local.lan}`)" - "traefik.http.routers.minio-api.entrypoints=websecure" - "traefik.http.routers.minio-api.tls=true" - "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:-local.lan}`)" - "traefik.http.routers.minio-console.entrypoints=websecure" - "traefik.http.routers.minio-console.tls=true" - "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 aia-qdrant: image: qdrant/qdrant:v1.7.4 container_name: aia-qdrant restart: unless-stopped networks: - backend ports: - "6333:6333" - "6334:6334" 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:-local.lan}`)" - "traefik.http.routers.qdrant.entrypoints=websecure" - "traefik.http.routers.qdrant.tls=true" - "traefik.http.routers.qdrant.middlewares=authentik-forwardauth@file" - "traefik.http.services.qdrant.loadbalancer.server.port=6333" # Knowledge Graph Database aia-neo4j: image: neo4j:5.15-community container_name: aia-neo4j restart: unless-stopped networks: - backend ports: - "7474:7474" - "7687:7687" volumes: - neo4j_data:/data - neo4j_logs:/logs - ../neo4j/plugins:/plugins environment: NEO4J_AUTH: neo4j/${NEO4J_PASSWORD:-neo4jpass} NEO4J_PLUGINS: '["apoc", "graph-daia-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:-local.lan}`)" - "traefik.http.routers.neo4j.entrypoints=websecure" - "traefik.http.routers.neo4j.tls=true" - "traefik.http.routers.neo4j.middlewares=authentik-forwardauth@file" - "traefik.http.services.neo4j.loadbalancer.server.port=7474" # Secure Client Data Store aia-postgres: image: postgres:15-alpine container_name: aia-postgres restart: unless-stopped networks: - backend ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data - ../postgres/init:/docker-entrypoint-initdb.d environment: POSTGRES_DB: tax_system POSTGRES_USER: postgres POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres} 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 aia-redis: image: redis:7-alpine container_name: aia-redis restart: unless-stopped networks: - backend ports: - "6379:6379" 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 aia-nats: image: nats:2.10-alpine container_name: aia-nats restart: unless-stopped networks: - backend ports: - "4222:4222" # NATS client connections - "8222:8222" # HTTP monitoring - "6222:6222" # Cluster routing (for future clustering) 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:-local.lan}`)" - "traefik.http.routers.nats-monitor.entrypoints=websecure" - "traefik.http.routers.nats-monitor.tls=true" - "traefik.http.routers.nats-monitor.middlewares=authentik-forwardauth@file" - "traefik.http.services.nats-monitor.loadbalancer.server.port=8222" # Monitoring & Observability aia-prometheus: image: prom/prometheus:v2.48.1 container_name: aia-prometheus restart: unless-stopped networks: - backend ports: - "9090:9090" volumes: - prometheus_data:/prometheus command: - "--config.file=/etc/prometheus/prometheus.yml" - "--storage.tsdb.path=/prometheus" - "--web.console.libraries=/etc/prometheus/console_libraries" - "--web.console.templates=/etc/prometheus/consoles" - "--storage.tsdb.retention.time=30d" - "--web.enable-lifecycle" labels: - "traefik.enable=true" - "traefik.http.routers.prometheus.rule=Host(`prometheus.${DOMAIN:-local.lan}`)" - "traefik.http.routers.prometheus.entrypoints=websecure" - "traefik.http.routers.prometheus.tls=true" - "traefik.http.routers.prometheus.middlewares=authentik-forwardauth@file" - "traefik.http.services.prometheus.loadbalancer.server.port=9090" aia-grafana: image: grafana/grafana:10.2.3 container_name: aia-grafana restart: unless-stopped networks: - backend ports: - "3000:3000" volumes: - grafana_data:/var/lib/grafana - ./grafana/provisioning:/etc/grafana/provisioning:ro - ./grafana/dashboards:/var/lib/grafana/dashboards:ro environment: GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD:-admin} GF_USERS_ALLOW_SIGN_UP: false GF_USERS_AUTO_ASSIGN_ORG: true GF_USERS_AUTO_ASSIGN_ORG_ROLE: Viewer GF_AUTH_GENERIC_OAUTH_ENABLED: true GF_AUTH_GENERIC_OAUTH_NAME: Authentik GF_AUTH_GENERIC_OAUTH_CLIENT_ID: ${GRAFANA_OAUTH_CLIENT_ID:-grafana} GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET: ${GRAFANA_OAUTH_CLIENT_SECRET:-changeme-grafana-secret} GF_AUTH_GENERIC_OAUTH_SCOPES: openid profile email groups GF_AUTH_GENERIC_OAUTH_AUTH_URL: https://auth.${DOMAIN:-local.lan}/application/o/authorize/ GF_AUTH_GENERIC_OAUTH_TOKEN_URL: https://auth.${DOMAIN:-local.lan}/application/o/token/ GF_AUTH_GENERIC_OAUTH_API_URL: https://auth.${DOMAIN:-local.lan}/application/o/userinfo/ GF_AUTH_GENERIC_OAUTH_AUTO_LOGIN: false GF_AUTH_GENERIC_OAUTH_ALLOW_SIGN_UP: true GF_AUTH_GENERIC_OAUTH_ROLE_ATTRIBUTE_PATH: role GF_AUTH_GENERIC_OAUTH_ROLE_ATTRIBUTE_STRICT: false GF_AUTH_GENERIC_OAUTH_GROUPS_ATTRIBUTE_PATH: groups GF_AUTH_OAUTH_AUTO_LOGIN: false GF_AUTH_DISABLE_LOGIN_FORM: false # Cookie and security settings GF_SERVER_ROOT_URL: https://grafana.${DOMAIN:-local.lan} GF_SERVER_SERVE_FROM_SUB_PATH: false GF_SECURITY_COOKIE_SECURE: false GF_SECURITY_COOKIE_SAMESITE: lax GF_AUTH_GENERIC_OAUTH_USE_PKCE: true labels: - "traefik.enable=true" - "traefik.http.routers.grafana.rule=Host(`grafana.${DOMAIN:-local.lan}`)" - "traefik.http.routers.grafana.entrypoints=websecure" - "traefik.http.routers.grafana.tls=true" - "traefik.http.services.grafana.loadbalancer.server.port=3000" aia-loki: image: grafana/loki:2.9.4 container_name: aia-loki restart: unless-stopped networks: - backend ports: - "3100:3100" volumes: - loki_data:/loki labels: - "traefik.enable=true" - "traefik.http.routers.loki.rule=Host(`loki.${DOMAIN:-local.lan}`)" - "traefik.http.routers.loki.entrypoints=websecure" - "traefik.http.routers.loki.tls=true" - "traefik.http.routers.loki.middlewares=authentik-forwardauth@file" - "traefik.http.services.loki.loadbalancer.server.port=3100" # Feature Flags aia-unleash: image: unleashorg/unleash-server:5.7.3 container_name: aia-unleash restart: unless-stopped networks: - frontend - backend ports: - "4242:4242" environment: DATABASE_URL: postgres://postgres:${POSTGRES_PASSWORD:-postgres}@aia-postgres:5432/unleash DATABASE_SSL: false LOG_LEVEL: info depends_on: - aia-postgres labels: - "traefik.docker.network=ai-tax-agent-frontend" - "traefik.enable=true" - "traefik.http.routers.unleash.rule=Host(`unleash.${DOMAIN:-local.lan}`)" - "traefik.http.routers.unleash.entrypoints=websecure" - "traefik.http.routers.unleash.tls=true" - "traefik.http.routers.unleash.middlewares=authentik-forwardauth@file" - "traefik.http.services.unleash.loadbalancer.server.port=4242" # Application Services aia-svc-ingestion: build: context: ../../ dockerfile: apps/svc_ingestion/Dockerfile container_name: aia-svc-ingestion restart: unless-stopped networks: - backend environment: - VAULT_ADDR=http://aia-vault:8200 - VAULT_TOKEN=${VAULT_DEV_ROOT_TOKEN_ID:-root} - MINIO_ENDPOINT=aia-minio:9092 - POSTGRES_URL=postgresql://postgres:${POSTGRES_PASSWORD:-postgres}@aia-postgres:5432/tax_system - REDIS_URL=redis://aia-redis:6379 - EVENT_BUS_TYPE=${EVENT_BUS_TYPE:-memory} - NATS_SERVERS=${NATS_SERVERS:-nats://aia-nats:4222} - NATS_STREAM_NAME=${NATS_STREAM_NAME:-TAX_AGENT_EVENTS} - NATS_CONSUMER_GROUP=${NATS_CONSUMER_GROUP:-tax-agent} depends_on: - aia-vault - aia-minio - aia-postgres - aia-redis - aia-nats - aia-neo4j labels: - "traefik.enable=true" - "traefik.http.routers.svc-ingestion.rule=Host(`api.${DOMAIN:-local.lan}`) && PathPrefix(`/ingestion`)" - "traefik.http.routers.svc-ingestion.entrypoints=websecure" - "traefik.http.routers.svc-ingestion.tls=true" - "traefik.http.routers.svc-ingestion.middlewares=authentik-forwardauth@file,rate-limit@file" - "traefik.http.services.svc-ingestion.loadbalancer.server.port=8000" aia-svc-extract: build: context: ../../ dockerfile: apps/svc_extract/Dockerfile container_name: aia-svc-extract restart: unless-stopped networks: - backend environment: - VAULT_ADDR=http://aia-vault:8200 - VAULT_TOKEN=${VAULT_DEV_ROOT_TOKEN_ID:-root} - MINIO_ENDPOINT=aia-minio:9092 - POSTGRES_URL=postgresql://postgres:${POSTGRES_PASSWORD:-postgres}@aia-postgres:5432/tax_system - RAG_EMBEDDING_MODEL=${RAG_EMBEDDING_MODEL:-bge-small-en-v1.5} - EVENT_BUS_TYPE=${EVENT_BUS_TYPE:-memory} - NATS_SERVERS=${NATS_SERVERS:-nats://aia-nats:4222} - NATS_STREAM_NAME=${NATS_STREAM_NAME:-TAX_AGENT_EVENTS} - NATS_CONSUMER_GROUP=${NATS_CONSUMER_GROUP:-tax-agent} depends_on: - aia-vault - aia-minio - aia-postgres - aia-nats - aia-neo4j - aia-redis labels: - "traefik.enable=true" - "traefik.http.routers.svc-extract.rule=Host(`api.${DOMAIN:-local.lan}`) && PathPrefix(`/extract`)" - "traefik.http.routers.svc-extract.entrypoints=websecure" - "traefik.http.routers.svc-extract.tls=true" - "traefik.http.routers.svc-extract.middlewares=authentik-forwardauth@file,rate-limit@file" - "traefik.http.services.svc-extract.loadbalancer.server.port=8000" aia-svc-kg: build: context: ../../ dockerfile: apps/svc_kg/Dockerfile container_name: aia-svc-kg restart: unless-stopped networks: - backend environment: - VAULT_ADDR=http://aia-vault:8200 - VAULT_TOKEN=${VAULT_DEV_ROOT_TOKEN_ID:-root} - NEO4J_URI=bolt://aia-neo4j:7687 - NEO4J_USER=neo4j - NEO4J_PASSWORD=${NEO4J_PASSWORD:-neo4jpass} - EVENT_BUS_TYPE=${EVENT_BUS_TYPE:-memory} - NATS_SERVERS=${NATS_SERVERS:-nats://aia-nats:4222} - NATS_STREAM_NAME=${NATS_STREAM_NAME:-TAX_AGENT_EVENTS} - NATS_CONSUMER_GROUP=${NATS_CONSUMER_GROUP:-tax-agent} depends_on: - aia-vault - aia-neo4j - aia-nats labels: - "traefik.enable=true" - "traefik.http.routers.svc-kg.rule=Host(`api.${DOMAIN:-local.lan}`) && PathPrefix(`/kg`)" - "traefik.http.routers.svc-kg.entrypoints=websecure" - "traefik.http.routers.svc-kg.tls=true" - "traefik.http.routers.svc-kg.middlewares=authentik-forwardauth@file,rate-limit@file" - "traefik.http.services.svc-kg.loadbalancer.server.port=8000" aia-svc-rag-retriever: build: context: ../../ dockerfile: apps/svc_rag_retriever/Dockerfile container_name: aia-svc-rag-retriever restart: unless-stopped networks: - backend environment: - VAULT_ADDR=http://aia-vault:8200 - VAULT_TOKEN=${VAULT_DEV_ROOT_TOKEN_ID:-root} - QDRANT_URL=http://aia-qdrant:6333 - NEO4J_URI=bolt://aia-neo4j:7687 - NEO4J_USER=neo4j - NEO4J_PASSWORD=${NEO4J_PASSWORD:-neo4jpass} - RAG_EMBEDDING_MODEL=${RAG_EMBEDDING_MODEL:-bge-small-en-v1.5} - RAG_RERANKER_MODEL=${RAG_RERANKER_MODEL:-cross-encoder/ms-marco-MiniLM-L-6-v2} - EVENT_BUS_TYPE=${EVENT_BUS_TYPE:-memory} - NATS_SERVERS=${NATS_SERVERS:-nats://aia-nats:4222} - NATS_STREAM_NAME=${NATS_STREAM_NAME:-TAX_AGENT_EVENTS} - NATS_CONSUMER_GROUP=${NATS_CONSUMER_GROUP:-tax-agent} depends_on: - aia-vault - aia-qdrant - aia-neo4j - aia-nats labels: - "traefik.enable=true" - "traefik.http.routers.svc-rag-retriever.rule=Host(`api.${DOMAIN:-local.lan}`) && PathPrefix(`/rag`)" - "traefik.http.routers.svc-rag-retriever.entrypoints=websecure" - "traefik.http.routers.svc-rag-retriever.tls=true" - "traefik.http.routers.svc-rag-retriever.middlewares=authentik-forwardauth@file,rate-limit@file" - "traefik.http.services.svc-rag-retriever.loadbalancer.server.port=8000" aia-svc-coverage: build: context: ../../ dockerfile: apps/svc_coverage/Dockerfile container_name: aia-svc-coverage restart: unless-stopped networks: - backend volumes: - ../../config:/app/config:ro environment: - VAULT_ADDR=http://aia-vault:8200 - VAULT_TOKEN=${VAULT_DEV_ROOT_TOKEN_ID:-root} - NEO4J_URI=bolt://aia-neo4j:7687 - NEO4J_USER=neo4j - NEO4J_PASSWORD=${NEO4J_PASSWORD:-neo4jpass} - POSTGRES_URL=postgresql://postgres:${POSTGRES_PASSWORD:-postgres}@aia-postgres:5432/tax_system - RAG_SERVICE_URL=http://aia-svc-rag-retriever:8000 - EVENT_BUS_TYPE=${EVENT_BUS_TYPE:-memory} - NATS_SERVERS=${NATS_SERVERS:-nats://aia-nats:4222} - NATS_STREAM_NAME=${NATS_STREAM_NAME:-TAX_AGENT_EVENTS} - NATS_CONSUMER_GROUP=${NATS_CONSUMER_GROUP:-tax-agent} depends_on: - aia-vault - aia-neo4j - aia-postgres - aia-nats labels: - "traefik.enable=true" - "traefik.http.routers.svc-coverage.rule=Host(`api.${DOMAIN:-local.lan}`) && PathPrefix(`/coverage`)" - "traefik.http.routers.svc-coverage.entrypoints=websecure" - "traefik.http.routers.svc-coverage.tls=true" - "traefik.http.routers.svc-coverage.middlewares=authentik-forwardauth@file,rate-limit@file" - "traefik.http.services.svc-coverage.loadbalancer.server.port=8000" aia-svc-firm-connectors: build: context: ../../ dockerfile: apps/svc_firm_connectors/Dockerfile container_name: aia-svc-firm-connectors restart: unless-stopped networks: - backend volumes: - ../../config:/app/config:ro environment: - VAULT_ADDR=http://aia-vault:8200 - VAULT_TOKEN=${VAULT_DEV_ROOT_TOKEN_ID:-root} - POSTGRES_URL=postgresql://postgres:${POSTGRES_PASSWORD:-postgres}@aia-postgres:5432/tax_system - NEO4J_URL=bolt://aia-neo4j:7687 - NEO4J_USER=neo4j - NEO4J_PASSWORD=${NEO4J_PASSWORD:-password} - REDIS_URL=redis://aia-redis:6379 - MINIO_ENDPOINT=aia-minio:9092 - MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY:-minioadmin} - MINIO_SECRET_KEY=${MINIO_SECRET_KEY:-minioadmin} - QDRANT_URL=http://aia-qdrant:6333 - EVENT_BUS_TYPE=${EVENT_BUS_TYPE:-memory} - KAFKA_BOOTSTRAP_SERVERS=${KAFKA_BOOTSTRAP_SERVERS:-} - NATS_SERVERS=${NATS_SERVERS:-nats://aia-nats:4222} - NATS_STREAM_NAME=${NATS_STREAM_NAME:-TAX_AGENT_EVENTS} - NATS_CONSUMER_GROUP=${NATS_CONSUMER_GROUP:-tax-agent} depends_on: - aia-postgres - aia-neo4j - aia-minio - aia-qdrant - aia-nats - aia-traefik labels: - "traefik.enable=true" - "traefik.http.routers.svc-firm-connectors.rule=Host(`api.${DOMAIN:-local.lan}`) && PathPrefix(`/firm-connectors`)" - "traefik.http.routers.svc-firm-connectors.entrypoints=websecure" - "traefik.http.routers.svc-firm-connectors.tls=true" - "traefik.http.routers.svc-firm-connectors.middlewares=authentik-forwardauth@file,rate-limit@file" - "traefik.http.services.svc-firm-connectors.loadbalancer.server.port=8000" aia-svc-forms: build: context: ../../ dockerfile: apps/svc_forms/Dockerfile container_name: aia-svc-forms restart: unless-stopped networks: - backend volumes: - ../../config:/app/config:ro environment: - VAULT_ADDR=http://aia-vault:8200 - VAULT_TOKEN=${VAULT_DEV_ROOT_TOKEN_ID:-root} - POSTGRES_URL=postgresql://postgres:${POSTGRES_PASSWORD:-postgres}@aia-postgres:5432/tax_system - NEO4J_URL=bolt://aia-neo4j:7687 - NEO4J_USER=neo4j - NEO4J_PASSWORD=${NEO4J_PASSWORD:-password} - REDIS_URL=redis://aia-redis:6379 - MINIO_ENDPOINT=aia-minio:9092 - MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY:-minioadmin} - MINIO_SECRET_KEY=${MINIO_SECRET_KEY:-minioadmin} - QDRANT_URL=http://aia-qdrant:6333 - EVENT_BUS_TYPE=${EVENT_BUS_TYPE:-memory} - KAFKA_BOOTSTRAP_SERVERS=${KAFKA_BOOTSTRAP_SERVERS:-} - NATS_SERVERS=${NATS_SERVERS:-nats://aia-nats:4222} - NATS_STREAM_NAME=${NATS_STREAM_NAME:-TAX_AGENT_EVENTS} - NATS_CONSUMER_GROUP=${NATS_CONSUMER_GROUP:-tax-agent} depends_on: - aia-postgres - aia-neo4j - aia-minio - aia-qdrant - aia-nats - aia-traefik labels: - "traefik.enable=true" - "traefik.http.routers.svc-forms.rule=Host(`api.${DOMAIN:-local.lan}`) && PathPrefix(`/forms`)" - "traefik.http.routers.svc-forms.entrypoints=websecure" - "traefik.http.routers.svc-forms.tls=true" - "traefik.http.routers.svc-forms.middlewares=authentik-forwardauth@file,rate-limit@file" - "traefik.http.services.svc-forms.loadbalancer.server.port=8000" aia-svc-hmrc: build: context: ../../ dockerfile: apps/svc_hmrc/Dockerfile container_name: aia-svc-hmrc restart: unless-stopped networks: - backend volumes: - ../../config:/app/config:ro environment: - VAULT_ADDR=http://aia-vault:8200 - VAULT_TOKEN=${VAULT_DEV_ROOT_TOKEN_ID:-root} - POSTGRES_URL=postgresql://postgres:${POSTGRES_PASSWORD:-postgres}@aia-postgres:5432/tax_system - NEO4J_URL=bolt://aia-neo4j:7687 - NEO4J_USER=neo4j - NEO4J_PASSWORD=${NEO4J_PASSWORD:-password} - REDIS_URL=redis://aia-redis:6379 - MINIO_ENDPOINT=aia-minio:9092 - MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY:-minioadmin} - MINIO_SECRET_KEY=${MINIO_SECRET_KEY:-minioadmin} - QDRANT_URL=http://aia-qdrant:6333 - EVENT_BUS_TYPE=${EVENT_BUS_TYPE:-memory} - KAFKA_BOOTSTRAP_SERVERS=${KAFKA_BOOTSTRAP_SERVERS:-} - NATS_SERVERS=${NATS_SERVERS:-nats://aia-nats:4222} - NATS_STREAM_NAME=${NATS_STREAM_NAME:-TAX_AGENT_EVENTS} - NATS_CONSUMER_GROUP=${NATS_CONSUMER_GROUP:-tax-agent} depends_on: - aia-postgres - aia-neo4j - aia-minio - aia-qdrant - aia-nats - aia-traefik labels: - "traefik.enable=true" - "traefik.http.routers.svc-hmrc.rule=Host(`api.${DOMAIN:-local.lan}`) && PathPrefix(`/hmrc`)" - "traefik.http.routers.svc-hmrc.entrypoints=websecure" - "traefik.http.routers.svc-hmrc.tls=true" - "traefik.http.routers.svc-hmrc.middlewares=authentik-forwardauth@file,rate-limit@file" - "traefik.http.services.svc-hmrc.loadbalancer.server.port=8000" aia-svc-normalize-map: build: context: ../../ dockerfile: apps/svc_normalize_map/Dockerfile container_name: aia-svc-normalize-map restart: unless-stopped networks: - backend volumes: - ../../config:/app/config:ro environment: - VAULT_ADDR=http://aia-vault:8200 - VAULT_TOKEN=${VAULT_DEV_ROOT_TOKEN_ID:-root} - POSTGRES_URL=postgresql://postgres:${POSTGRES_PASSWORD:-postgres}@aia-postgres:5432/tax_system - NEO4J_URL=bolt://aia-neo4j:7687 - NEO4J_USER=neo4j - NEO4J_PASSWORD=${NEO4J_PASSWORD:-password} - REDIS_URL=redis://aia-redis:6379 - MINIO_ENDPOINT=aia-minio:9092 - MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY:-minioadmin} - MINIO_SECRET_KEY=${MINIO_SECRET_KEY:-minioadmin} - QDRANT_URL=http://aia-qdrant:6333 - EVENT_BUS_TYPE=${EVENT_BUS_TYPE:-memory} - KAFKA_BOOTSTRAP_SERVERS=${KAFKA_BOOTSTRAP_SERVERS:-} - NATS_SERVERS=${NATS_SERVERS:-nats://aia-nats:4222} - NATS_STREAM_NAME=${NATS_STREAM_NAME:-TAX_AGENT_EVENTS} - NATS_CONSUMER_GROUP=${NATS_CONSUMER_GROUP:-tax-agent} depends_on: - aia-postgres - aia-neo4j - aia-minio - aia-qdrant - aia-nats - aia-traefik labels: - "traefik.enable=true" - "traefik.http.routers.svc-normalize-map.rule=Host(`api.${DOMAIN:-local.lan}`) && PathPrefix(`/normalize-map`)" - "traefik.http.routers.svc-normalize-map.entrypoints=websecure" - "traefik.http.routers.svc-normalize-map.tls=true" - "traefik.http.routers.svc-normalize-map.middlewares=authentik-forwardauth@file,rate-limit@file" - "traefik.http.services.svc-normalize-map.loadbalancer.server.port=8000" aia-svc-ocr: build: context: ../../ dockerfile: apps/svc_ocr/Dockerfile container_name: aia-svc-ocr restart: unless-stopped networks: - backend volumes: - ../../config:/app/config:ro environment: - VAULT_ADDR=http://aia-vault:8200 - VAULT_TOKEN=${VAULT_DEV_ROOT_TOKEN_ID:-root} - POSTGRES_URL=postgresql://postgres:${POSTGRES_PASSWORD:-postgres}@aia-postgres:5432/tax_system - NEO4J_URL=bolt://aia-neo4j:7687 - NEO4J_USER=neo4j - NEO4J_PASSWORD=${NEO4J_PASSWORD:-password} - REDIS_URL=redis://aia-redis:6379 - MINIO_ENDPOINT=aia-minio:9092 - MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY:-minioadmin} - MINIO_SECRET_KEY=${MINIO_SECRET_KEY:-minioadmin} - QDRANT_URL=http://aia-qdrant:6333 - EVENT_BUS_TYPE=${EVENT_BUS_TYPE:-memory} - KAFKA_BOOTSTRAP_SERVERS=${KAFKA_BOOTSTRAP_SERVERS:-} - NATS_SERVERS=${NATS_SERVERS:-nats://aia-nats:4222} - NATS_STREAM_NAME=${NATS_STREAM_NAME:-TAX_AGENT_EVENTS} - NATS_CONSUMER_GROUP=${NATS_CONSUMER_GROUP:-tax-agent} depends_on: - aia-postgres - aia-neo4j - aia-minio - aia-qdrant - aia-nats - aia-traefik labels: - "traefik.enable=true" - "traefik.http.routers.svc-ocr.rule=Host(`api.${DOMAIN:-local.lan}`) && PathPrefix(`/ocr`)" - "traefik.http.routers.svc-ocr.entrypoints=websecure" - "traefik.http.routers.svc-ocr.tls=true" - "traefik.http.routers.svc-ocr.middlewares=authentik-forwardauth@file,rate-limit@file" - "traefik.http.services.svc-ocr.loadbalancer.server.port=8000" aia-svc-rag-indexer: build: context: ../../ dockerfile: apps/svc_rag_indexer/Dockerfile container_name: aia-svc-rag-indexer restart: unless-stopped networks: - backend volumes: - ../../config:/app/config:ro environment: - VAULT_ADDR=http://aia-vault:8200 - VAULT_TOKEN=${VAULT_DEV_ROOT_TOKEN_ID:-root} - POSTGRES_URL=postgresql://postgres:${POSTGRES_PASSWORD:-postgres}@aia-postgres:5432/tax_system - NEO4J_URL=bolt://aia-neo4j:7687 - NEO4J_USER=neo4j - NEO4J_PASSWORD=${NEO4J_PASSWORD:-password} - REDIS_URL=redis://aia-redis:6379 - MINIO_ENDPOINT=aia-minio:9092 - MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY:-minioadmin} - MINIO_SECRET_KEY=${MINIO_SECRET_KEY:-minioadmin} - QDRANT_URL=http://aia-qdrant:6333 - EVENT_BUS_TYPE=${EVENT_BUS_TYPE:-memory} - KAFKA_BOOTSTRAP_SERVERS=${KAFKA_BOOTSTRAP_SERVERS:-} - NATS_SERVERS=${NATS_SERVERS:-nats://aia-nats:4222} - NATS_STREAM_NAME=${NATS_STREAM_NAME:-TAX_AGENT_EVENTS} - NATS_CONSUMER_GROUP=${NATS_CONSUMER_GROUP:-tax-agent} depends_on: - aia-postgres - aia-neo4j - aia-minio - aia-qdrant - aia-nats - aia-traefik labels: - "traefik.enable=true" - "traefik.http.routers.svc-rag-indexer.rule=Host(`api.${DOMAIN:-.lan}`) && PathPrefix(`/rag-indexer`)" - "traefik.http.routers.svc-rag-indexer.entrypoints=websecure" - "traefik.http.routers.svc-rag-indexer.tls=true" - "traefik.http.routers.svc-rag-indexer.middlewares=authentik-forwardauth@file,rate-limit@file" - "traefik.http.services.svc-rag-indexer.loadbalancer.server.port=8000" aia-svc-reason: build: context: ../../ dockerfile: apps/svc_reason/Dockerfile container_name: aia-svc-reason restart: unless-stopped networks: - backend volumes: - ../../config:/app/config:ro environment: - VAULT_ADDR=http://aia-vault:8200 - VAULT_TOKEN=${VAULT_DEV_ROOT_TOKEN_ID:-root} - POSTGRES_URL=postgresql://postgres:${POSTGRES_PASSWORD:-postgres}@aia-postgres:5432/tax_system - NEO4J_URL=bolt://aia-neo4j:7687 - NEO4J_USER=neo4j - NEO4J_PASSWORD=${NEO4J_PASSWORD:-password} - REDIS_URL=redis://aia-redis:6379 - MINIO_ENDPOINT=aia-minio:9092 - MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY:-minioadmin} - MINIO_SECRET_KEY=${MINIO_SECRET_KEY:-minioadmin} - QDRANT_URL=http://aia-qdrant:6333 - EVENT_BUS_TYPE=${EVENT_BUS_TYPE:-memory} - KAFKA_BOOTSTRAP_SERVERS=${KAFKA_BOOTSTRAP_SERVERS:-} - NATS_SERVERS=${NATS_SERVERS:-nats://aia-nats:4222} - NATS_STREAM_NAME=${NATS_STREAM_NAME:-TAX_AGENT_EVENTS} - NATS_CONSUMER_GROUP=${NATS_CONSUMER_GROUP:-tax-agent} depends_on: - aia-postgres - aia-neo4j - aia-minio - aia-qdrant - aia-nats - aia-traefik labels: - "traefik.enable=true" - "traefik.http.routers.svc-reason.rule=Host(`api.${DOMAIN:-local.lan}`) && PathPrefix(`/reason`)" - "traefik.http.routers.svc-reason.entrypoints=websecure" - "traefik.http.routers.svc-reason.tls=true" - "traefik.http.routers.svc-reason.middlewares=authentik-forwardauth@file,rate-limit@file" - "traefik.http.services.svc-reason.loadbalancer.server.port=8000" aia-svc-rpa: build: context: ../../ dockerfile: apps/svc_rpa/Dockerfile container_name: aia-svc-rpa restart: unless-stopped networks: - backend volumes: - ../../config:/app/config:ro environment: - VAULT_ADDR=http://aia-vault:8200 - VAULT_TOKEN=${VAULT_DEV_ROOT_TOKEN_ID:-root} - POSTGRES_URL=postgresql://postgres:${POSTGRES_PASSWORD:-postgres}@aia-postgres:5432/tax_system - NEO4J_URL=bolt://aia-neo4j:7687 - NEO4J_USER=neo4j - NEO4J_PASSWORD=${NEO4J_PASSWORD:-password} - REDIS_URL=redis://aia-redis:6379 - MINIO_ENDPOINT=aia-minio:9092 - MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY:-minioadmin} - MINIO_SECRET_KEY=${MINIO_SECRET_KEY:-minioadmin} - QDRANT_URL=http://aia-qdrant:6333 - EVENT_BUS_TYPE=${EVENT_BUS_TYPE:-memory} - KAFKA_BOOTSTRAP_SERVERS=${KAFKA_BOOTSTRAP_SERVERS:-} - NATS_SERVERS=${NATS_SERVERS:-nats://aia-nats:4222} - NATS_STREAM_NAME=${NATS_STREAM_NAME:-TAX_AGENT_EVENTS} - NATS_CONSUMER_GROUP=${NATS_CONSUMER_GROUP:-tax-agent} depends_on: - aia-postgres - aia-neo4j - aia-minio - aia-qdrant - aia-nats - aia-traefik labels: - "traefik.enable=true" - "traefik.http.routers.svc-rpa.rule=Host(`api.${DOMAIN:-local.lan}`) && PathPrefix(`/rpa`)" - "traefik.http.routers.svc-rpa.entrypoints=websecure" - "traefik.http.routers.svc-rpa.tls=true" - "traefik.http.routers.svc-rpa.middlewares=authentik-forwardauth@file,rate-limit@file" - "traefik.http.services.svc-rpa.loadbalancer.server.port=8000" aia-ui-review: build: context: ../../ui-review dockerfile: Dockerfile container_name: aia-ui-review restart: unless-stopped networks: - frontend environment: - NEXTAUTH_URL=https://review.${DOMAIN:-local.lan} - NEXTAUTH_SECRET=${NEXTAUTH_SECRET:-changeme} - API_BASE_URL=https://api.${DOMAIN:-local.lan} depends_on: - aia-traefik labels: - "traefik.docker.network=ai-tax-agent-frontend" - "traefik.enable=true" - "traefik.http.routers.ui-review.rule=Host(`review.${DOMAIN:-local.lan}`)" - "traefik.http.routers.ui-review.entrypoints=websecure" - "traefik.http.routers.ui-review.tls=true" - "traefik.http.routers.ui-review.middlewares=authentik-forwardauth@file" - "traefik.http.services.ui-review.loadbalancer.server.port=3030"