feat: docker-compose stack CHLOVA (v0.4.0) — fin Phase 0
Stack complète : Ollama (proxy cloud, interne+egress, aucun port), socket-proxy (endpoints lecture seule), MCP n8n + Portainer (read-only), backend = seule surface (aucun port publié en P1, Telegram long-polling). Réseaux internal/egress, images épinglées (digests à confirmer), secrets par référence. `docker compose config` valide. Palier de risque : privilégié (déploiement infra) — non déployé, validation requise avant tout `up`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,14 @@ incompatibles. Chaque ligne renvoie à un commit dédié (un artefact = un commi
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.4.0] — 2026-06-23 — fin Phase 0 (socle)
|
||||||
|
### Added
|
||||||
|
- `infra/docker-compose.yml` : stack CHLOVA — Ollama (proxy cloud, interne +
|
||||||
|
egress, aucun port publié), socket-proxy (lecture seule), MCP n8n + MCP
|
||||||
|
Portainer (read-only), backend (seule surface, aucun port publié en P1).
|
||||||
|
Images à tags épinglés (digests à confirmer avant déploiement réel), réseaux
|
||||||
|
`chlova-internal` (internal) / `chlova-egress`. Config validée (`compose config`).
|
||||||
|
|
||||||
## [0.3.0] — 2026-06-23
|
## [0.3.0] — 2026-06-23
|
||||||
### Added
|
### Added
|
||||||
- Socle sécurité : `docs/security.md` (modèle de menace prompt-injection +
|
- Socle sécurité : `docs/security.md` (modèle de menace prompt-injection +
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
# 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}
|
||||||
|
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:
|
||||||
Reference in New Issue
Block a user