236 lines
9.7 KiB
YAML
236 lines
9.7 KiB
YAML
services:
|
|
|
|
# ─────────────────────────────────────────────
|
|
# PostgreSQL 16 — primary datastore
|
|
# ─────────────────────────────────────────────
|
|
postgres:
|
|
image: postgres:16-alpine
|
|
environment:
|
|
POSTGRES_DB: veylant
|
|
POSTGRES_USER: veylant
|
|
POSTGRES_PASSWORD: veylant_dev
|
|
ports:
|
|
- "5432:5432"
|
|
volumes:
|
|
- postgres_data:/var/lib/postgresql/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U veylant -d veylant"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 10
|
|
start_period: 10s
|
|
|
|
# ─────────────────────────────────────────────
|
|
# Redis 7 — sessions, rate limiting, PII pseudonymization mappings
|
|
# No persistence in dev (AOF/RDB disabled for fast startup)
|
|
# ─────────────────────────────────────────────
|
|
redis:
|
|
image: redis:7-alpine
|
|
command: redis-server --save "" --appendonly no
|
|
ports:
|
|
- "6379:6379"
|
|
healthcheck:
|
|
test: ["CMD", "redis-cli", "ping"]
|
|
interval: 5s
|
|
timeout: 3s
|
|
retries: 10
|
|
|
|
# ─────────────────────────────────────────────
|
|
# ClickHouse 24.3 LTS — append-only audit logs and analytics
|
|
# Pinned to LTS for stability
|
|
# ─────────────────────────────────────────────
|
|
clickhouse:
|
|
image: clickhouse/clickhouse-server:24.3-alpine
|
|
environment:
|
|
CLICKHOUSE_DB: veylant_logs
|
|
CLICKHOUSE_USER: veylant
|
|
CLICKHOUSE_PASSWORD: veylant_dev
|
|
CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1
|
|
ports:
|
|
- "8123:8123" # HTTP interface (used for health check and dashboard queries)
|
|
- "9000:9000" # Native TCP (used by Go driver)
|
|
volumes:
|
|
- clickhouse_data:/var/lib/clickhouse
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:8123/ping || exit 1"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 20
|
|
start_period: 15s
|
|
ulimits:
|
|
nofile:
|
|
soft: 262144
|
|
hard: 262144
|
|
|
|
# ─────────────────────────────────────────────
|
|
# Keycloak 24 — IAM, OIDC, SAML 2.0
|
|
# start-dev: in-memory DB, no TLS — development only
|
|
# Realm is auto-imported from deploy/keycloak/realm-export.json
|
|
# ─────────────────────────────────────────────
|
|
keycloak:
|
|
image: quay.io/keycloak/keycloak:24.0
|
|
command: ["start-dev", "--import-realm"]
|
|
environment:
|
|
KC_BOOTSTRAP_ADMIN_USERNAME: admin
|
|
KC_BOOTSTRAP_ADMIN_PASSWORD: admin
|
|
KC_DB: dev-mem
|
|
KC_HEALTH_ENABLED: "true"
|
|
ports:
|
|
- "8080:8080"
|
|
volumes:
|
|
- ./deploy/keycloak:/opt/keycloak/data/import:ro
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "curl -sf http://localhost:8080/health/ready || exit 1"]
|
|
interval: 10s
|
|
timeout: 10s
|
|
retries: 20
|
|
start_period: 30s # Keycloak takes ~20s to start in dev mode
|
|
|
|
# ─────────────────────────────────────────────
|
|
# Veylant proxy — Go application
|
|
# ─────────────────────────────────────────────
|
|
proxy:
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile
|
|
ports:
|
|
- "8090:8090"
|
|
environment:
|
|
VEYLANT_SERVER_PORT: "8090"
|
|
VEYLANT_SERVER_ENV: "development"
|
|
VEYLANT_DATABASE_URL: "postgres://veylant:veylant_dev@postgres:5432/veylant?sslmode=disable"
|
|
VEYLANT_REDIS_URL: "redis://redis:6379"
|
|
VEYLANT_KEYCLOAK_BASE_URL: "http://keycloak:8080"
|
|
VEYLANT_KEYCLOAK_REALM: "veylant"
|
|
VEYLANT_KEYCLOAK_CLIENT_ID: "veylant-proxy"
|
|
VEYLANT_PII_ENABLED: "true"
|
|
VEYLANT_PII_SERVICE_ADDR: "pii:50051"
|
|
VEYLANT_PII_TIMEOUT_MS: "100"
|
|
VEYLANT_PII_FAIL_OPEN: "true"
|
|
VEYLANT_LOG_FORMAT: "console"
|
|
VEYLANT_LOG_LEVEL: "debug"
|
|
# Provider API keys — set via a .env file or shell environment.
|
|
# Only providers with an API key set will be enabled at runtime.
|
|
VEYLANT_PROVIDERS_OPENAI_API_KEY: "${OPENAI_API_KEY:-}"
|
|
VEYLANT_PROVIDERS_ANTHROPIC_API_KEY: "${ANTHROPIC_API_KEY:-}"
|
|
VEYLANT_PROVIDERS_MISTRAL_API_KEY: "${MISTRAL_API_KEY:-}"
|
|
# Azure OpenAI requires resource name + deployment ID + API key.
|
|
VEYLANT_PROVIDERS_AZURE_API_KEY: "${AZURE_OPENAI_API_KEY:-}"
|
|
VEYLANT_PROVIDERS_AZURE_RESOURCE_NAME: "${AZURE_OPENAI_RESOURCE_NAME:-}"
|
|
VEYLANT_PROVIDERS_AZURE_DEPLOYMENT_ID: "${AZURE_OPENAI_DEPLOYMENT_ID:-}"
|
|
# Ollama — defaults to localhost:11434 (use host.docker.internal in Docker Desktop).
|
|
VEYLANT_PROVIDERS_OLLAMA_BASE_URL: "${OLLAMA_BASE_URL:-http://host.docker.internal:11434/v1}"
|
|
VEYLANT_METRICS_ENABLED: "true"
|
|
# ClickHouse audit log (Sprint 6).
|
|
VEYLANT_CLICKHOUSE_DSN: "clickhouse://veylant:veylant_dev@clickhouse:9000/veylant_logs"
|
|
# AES-256-GCM key for prompt encryption — generate: openssl rand -base64 32
|
|
# In production, inject via Vault or secret manager. Leave empty to disable.
|
|
VEYLANT_CRYPTO_AES_KEY_BASE64: "${VEYLANT_CRYPTO_AES_KEY_BASE64:-}"
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
redis:
|
|
condition: service_healthy
|
|
clickhouse:
|
|
condition: service_healthy
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:8090/healthz || exit 1"]
|
|
interval: 5s
|
|
timeout: 3s
|
|
retries: 10
|
|
start_period: 5s
|
|
|
|
# ─────────────────────────────────────────────
|
|
# PII detection service — Python (Sprint 3: full pipeline)
|
|
# Layer 1: regex (IBAN/email/phone/SSN/CB)
|
|
# Layer 2: Presidio + spaCy NER (PERSON/LOC/ORG)
|
|
# Pseudonymization: AES-256-GCM in Redis
|
|
# ─────────────────────────────────────────────
|
|
pii:
|
|
build:
|
|
context: ./services/pii
|
|
dockerfile: Dockerfile
|
|
ports:
|
|
- "50051:50051" # gRPC
|
|
- "8000:8000" # HTTP health
|
|
environment:
|
|
PII_GRPC_PORT: "50051"
|
|
PII_HTTP_PORT: "8000"
|
|
PII_REDIS_URL: "redis://redis:6379"
|
|
# PII_ENCRYPTION_KEY must be set to a 32-byte base64-encoded key in production.
|
|
# The default dev key is used if unset (NOT safe for production).
|
|
PII_ENCRYPTION_KEY: "${PII_ENCRYPTION_KEY:-}"
|
|
PII_NER_ENABLED: "true"
|
|
PII_NER_CONFIDENCE: "0.85"
|
|
PII_TTL_SECONDS: "3600"
|
|
depends_on:
|
|
redis:
|
|
condition: service_healthy
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:8000/healthz || exit 1"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 10
|
|
start_period: 60s # spaCy fr_core_news_lg model load takes ~30s on first start
|
|
|
|
# ─────────────────────────────────────────────
|
|
# Prometheus — metrics collection
|
|
# Scrapes the proxy /metrics endpoint every 15s
|
|
# ─────────────────────────────────────────────
|
|
prometheus:
|
|
image: prom/prometheus:v2.53.0
|
|
ports:
|
|
- "9090:9090"
|
|
volumes:
|
|
- ./deploy/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
|
|
command:
|
|
- "--config.file=/etc/prometheus/prometheus.yml"
|
|
- "--storage.tsdb.path=/prometheus"
|
|
- "--web.console.libraries=/etc/prometheus/console_libraries"
|
|
- "--web.console.templates=/etc/prometheus/consoles"
|
|
depends_on:
|
|
proxy:
|
|
condition: service_healthy
|
|
|
|
# ─────────────────────────────────────────────
|
|
# Grafana — metrics visualisation
|
|
# Auto-provisioned datasource (Prometheus) + Veylant dashboard
|
|
# Default credentials: admin / admin
|
|
# ─────────────────────────────────────────────
|
|
grafana:
|
|
image: grafana/grafana:11.3.0
|
|
ports:
|
|
- "3001:3000"
|
|
environment:
|
|
GF_SECURITY_ADMIN_PASSWORD: admin
|
|
GF_USERS_ALLOW_SIGN_UP: "false"
|
|
volumes:
|
|
- ./deploy/grafana/provisioning:/etc/grafana/provisioning:ro
|
|
- ./deploy/grafana/dashboards:/var/lib/grafana/dashboards:ro
|
|
depends_on:
|
|
- prometheus
|
|
|
|
# ─────────────────────────────────────────────
|
|
# Veylant Dashboard — React SPA (Sprint 7)
|
|
# Dev server only — production uses dist/ served by nginx
|
|
# ─────────────────────────────────────────────
|
|
web:
|
|
image: node:20-alpine
|
|
working_dir: /app
|
|
command: sh -c "npm install && npm run dev -- --host"
|
|
ports:
|
|
- "3000:3000"
|
|
volumes:
|
|
- ./web:/app
|
|
- /app/node_modules
|
|
environment:
|
|
VITE_AUTH_MODE: "dev"
|
|
VITE_KEYCLOAK_URL: "http://localhost:8080/realms/veylant"
|
|
depends_on:
|
|
proxy:
|
|
condition: service_healthy
|
|
|
|
volumes:
|
|
postgres_data:
|
|
clickhouse_data:
|