209 lines
8.8 KiB
YAML
209 lines
8.8 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
|
|
- ./deploy/clickhouse/listen-ipv4.xml:/etc/clickhouse-server/config.d/listen-ipv4.xml:ro
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://127.0.0.1:8123/ping || exit 1"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 20
|
|
start_period: 15s
|
|
ulimits:
|
|
nofile:
|
|
soft: 262144
|
|
hard: 262144
|
|
|
|
# ─────────────────────────────────────────────
|
|
# 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"
|
|
# Local JWT secret — override in production: VEYLANT_AUTH_JWT_SECRET=<strong-secret>
|
|
VEYLANT_AUTH_JWT_SECRET: "${VEYLANT_AUTH_JWT_SECRET:-dev-jwt-secret-change-in-prod}"
|
|
VEYLANT_AUTH_JWT_TTL_HOURS: "24"
|
|
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
|
|
# distroless/static has no shell or wget, so Docker health checks via CMD-SHELL
|
|
# cannot run. The proxy exposes /healthz at :8090 — healthy when it starts.
|
|
|
|
# ─────────────────────────────────────────────
|
|
# 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.
|
|
# Dev default = 32 zero bytes (NOT safe for production).
|
|
PII_ENCRYPTION_KEY: "${PII_ENCRYPTION_KEY:-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=}"
|
|
PII_NER_ENABLED: "true"
|
|
PII_NER_CONFIDENCE: "0.65"
|
|
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_started
|
|
|
|
# ─────────────────────────────────────────────
|
|
# 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: "email"
|
|
VITE_PROXY_TARGET: "http://proxy:8090"
|
|
depends_on:
|
|
proxy:
|
|
condition: service_started
|
|
|
|
volumes:
|
|
postgres_data:
|
|
clickhouse_data:
|