52980837a9
docs/need-review.md (cycle complet : états, sursis, gatekeeper, cron, review, rollback). CHLOVA_PHASE dans .env.example + compose (défaut 1). risk-tiers + README : application par phase. Compose revalidé, 45 tests, 0 vuln. Palier de risque : n/a (doc + config). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
119 lines
4.5 KiB
YAML
119 lines
4.5 KiB
YAML
# CHLOVA — stack d'orchestration.
|
|
# Règles : une seule surface exposée (backend), tout le reste interne, images
|
|
# épinglées (jamais :latest), secrets par référence (voir ../.env.example).
|
|
#
|
|
# ⚠️ Les tags ci-dessous sont des points d'épinglage à CONFIRMER avant tout
|
|
# déploiement réel : `docker pull <image>:<tag>` puis remplacer par
|
|
# `<image>:<tag>@sha256:<digest>` pour une immuabilité complète (docs/versioning.md).
|
|
# Aucun déploiement réel n'est lancé depuis ce dépôt sans validation explicite.
|
|
|
|
name: chlova
|
|
|
|
services:
|
|
# ── Ollama : proxy authentifié vers les modèles cloud (ollama.com) ──────
|
|
ollama:
|
|
image: ollama/ollama:0.6.8 # TODO épingler le digest
|
|
restart: unless-stopped
|
|
environment:
|
|
# Clé du proxy cloud — injectée depuis .env, jamais en dur.
|
|
OLLAMA_API_KEY: ${OLLAMA_API_KEY:?OLLAMA_API_KEY requis}
|
|
OLLAMA_HOST: 0.0.0.0:11434
|
|
volumes:
|
|
- ollama-data:/root/.ollama
|
|
networks:
|
|
- chlova-internal # joignable par le backend
|
|
- chlova-egress # seul service autorisé à sortir
|
|
# AUCUN port publié : Ollama n'a pas d'auth native, jamais exposé.
|
|
|
|
# ── socket-proxy : accès Docker filtré (voir socket-proxy/README.md) ────
|
|
socket-proxy:
|
|
image: tecnativa/docker-socket-proxy:0.3.0 # TODO épingler le digest
|
|
restart: unless-stopped
|
|
environment:
|
|
# Phase 1 — LECTURE SEULE : lecture autorisée, mutation refusée.
|
|
CONTAINERS: 1
|
|
IMAGES: 1
|
|
NETWORKS: 1
|
|
VOLUMES: 1
|
|
SERVICES: 1
|
|
TASKS: 1
|
|
NODES: 1
|
|
INFO: 1
|
|
VERSION: 1
|
|
POST: 0 # refuse toute mutation
|
|
EXEC: 0 # refuse exec dans un conteneur
|
|
AUTH: 0
|
|
SECRETS: 0
|
|
CONFIGS: 0
|
|
BUILD: 0
|
|
COMMIT: 0
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock:ro # seul à monter le socket
|
|
networks:
|
|
- chlova-internal
|
|
# AUCUN port publié.
|
|
|
|
# ── MCP n8n (czlonkowski/n8n-mcp) — read-only en Phase 1 ────────────────
|
|
mcp-n8n:
|
|
image: ghcr.io/czlonkowski/n8n-mcp:2.18.3 # TODO confirmer tag + épingler digest
|
|
restart: unless-stopped
|
|
environment:
|
|
MCP_MODE: http # transport HTTP (backend distant via réseau)
|
|
MCP_AUTH_TOKEN: ${MCP_N8N_AUTH_TOKEN:?requis}
|
|
N8N_API_URL: ${N8N_API_URL} # instance n8n existante (interne)
|
|
N8N_API_KEY: ${N8N_API_KEY:?requis} # token n8n à portée RESTREINTE (lecture P1)
|
|
networks:
|
|
- chlova-internal
|
|
# AUCUN port publié.
|
|
|
|
# ── MCP Portainer (portainer/portainer-mcp) — read-only en Phase 1 ──────
|
|
mcp-portainer:
|
|
image: portainer/portainer-mcp:0.6.0 # TODO confirmer tag/transport + épingler digest
|
|
restart: unless-stopped
|
|
environment:
|
|
PORTAINER_URL: ${PORTAINER_URL}
|
|
PORTAINER_MCP_AUTH_TOKEN: ${PORTAINER_MCP_AUTH_TOKEN:?requis}
|
|
PORTAINER_READ_ONLY: ${PORTAINER_READ_ONLY:-true} # P1 : NE PAS passer à false
|
|
# Docker via socket-proxy uniquement, jamais le socket brut.
|
|
DOCKER_HOST: tcp://socket-proxy:2375
|
|
depends_on:
|
|
- socket-proxy
|
|
networks:
|
|
- chlova-internal
|
|
# AUCUN port publié.
|
|
|
|
# ── Backend CHLOVA : SEULE surface, cerveau (boucle agent) ──────────────
|
|
backend:
|
|
build:
|
|
context: ../orchestrator # Dockerfile ajouté en Phase 1
|
|
image: chlova/backend:0.1.0 # tag versionné local
|
|
restart: unless-stopped
|
|
env_file: ../.env
|
|
environment:
|
|
CHLOVA_ENV: ${CHLOVA_ENV:-production}
|
|
CHLOVA_PHASE: ${CHLOVA_PHASE:-1} # 1 = lecture seule (défaut) ; 2 = écriture sous review
|
|
OLLAMA_BASE_URL: ${OLLAMA_BASE_URL:-http://ollama:11434}
|
|
MCP_N8N_URL: ${MCP_N8N_URL:-http://mcp-n8n:3000}
|
|
MCP_PORTAINER_URL: ${MCP_PORTAINER_URL:-http://mcp-portainer:3000}
|
|
volumes:
|
|
- chlova-data:/app/data # SQLite (table assets, P2+)
|
|
depends_on:
|
|
- ollama
|
|
- mcp-n8n
|
|
- mcp-portainer
|
|
networks:
|
|
- chlova-internal
|
|
# Phase 1 : surface Telegram en long-polling → AUCUN port publié.
|
|
# Phases ultérieures (API/UI) : exposer UNIQUEMENT ce service derrière
|
|
# Traefik + TLS et/ou VPN mesh. Voir infra/networks.md.
|
|
|
|
networks:
|
|
chlova-internal:
|
|
internal: true # aucune route vers l'extérieur
|
|
chlova-egress:
|
|
driver: bridge # sortie contrôlée (Ollama → ollama.com), egress filtré côté hôte
|
|
|
|
volumes:
|
|
ollama-data:
|
|
chlova-data:
|