Files
chlova/docs/deploy.md
T
Kantin-Petit 4e23828dae feat(infra): déploie gitea + n8n-chlova sur local, topologie mono-hôte (v0.33.0)
Stacks gitea (1.26.4, git.pogoo.app) et n8n-chlova (2.20.8,
n8n-chlova.pogoo.app) déployés via Portainer sur l'hôte local (réseau proxy),
versionnés dans infra/. docker-compose.prod.yml recâblé pour le tout-local
(MCP_N8N_URL n8n-chlova, PORTAINER_URL interne, sidecar sur proxy). Runbook
deploy.md réécrit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016w5jRe87MGdd6AMvXQcHNi
2026-06-23 11:40:24 +02:00

5.6 KiB

Déploiement CHLOVA (Phase 1 — lecture seule, GitOps Portainer)

Mise en production réelle sur le homelab. Tout sur l'hôte local (environnement Portainer endpoint 3), aux côtés du serveur Portainer et de Traefik. Pile dédiée à CHLOVA :

Stack État Rôle
gitea (endpoint 3) déployé dépôt git source du GitOps (git.pogoo.app)
n8n-chlova (endpoint 3) déployé n8n dédié à CHLOVA (n8n-chlova.pogoo.app)
chlova (endpoint 3) à déployer backend + ollama + sidecars (chlova.pogoo.app)

Modèle de risque. Phase 1 = lecture seule : CHLOVA_PHASE=1, PORTAINER_READ_ONLY=true, MCP read-only filtré. Aucune écriture branchée. Les secrets de CHLOVA ne transitent jamais par l'agent : ils sont saisis par l'opérateur dans les variables de stack Portainer (UI) — voir §4.

Réseau commun : proxy (external) — Traefik, Portainer, gitea, n8n-chlova et le backend CHLOVA y sont tous attachés, donc joignables en interne par nom de conteneur. Resolver TLS : letsencrypt. Entrypoint : websecure.

Compose de prod : infra/docker-compose.prod.yml. Build de l'image : par Portainer sur local (GitOps : clone du dépôt gitea

  • docker compose build). Contexte de build = racine du dépôt.

0. DNS (préalable)

Faire pointer vers l'IP de l'hôte local (la même que traefik.pogoo.app) : git.pogoo.app, n8n-chlova.pogoo.app, chlova.pogoo.app. Sans ça, Traefik ne peut pas émettre les certificats letsencrypt ni router.

1. Gitea — admin + dépôt (UI, une fois)

gitea est déployé, installeur ouvert (tu crées le 1er compte = admin).

  1. Ouvrir https://git.pogoo.app → compléter l'install (DB = SQLite déjà réglée) → créer le compte admin.
  2. New repository : chlova (privé).
  3. Settings → Applications → Generate token (scope write:repository) : sert à pousser le code (§2) et au clone GitOps par Portainer (§4).

L'enregistrement public est désactivé (DISABLE_REGISTRATION=true) : seul l'admin existe.

2. Pousser le dépôt CHLOVA dans gitea

Le code est sur le poste de build. Ajouter le remote gitea et pousser main :

git remote add gitea https://git.pogoo.app/<admin>/chlova.git
git push gitea main          # auth : <admin> + token de l'étape 1.3

3. Users restreints chlova (UI)

Le MCP Portainer n'expose pas la gestion users/tokens : étapes UI. Principe : CHLOVA n'accède qu'à ses ressources, tokens à portée minimale.

3a. Portainer — user chlova + token

  1. Users → Add user : chlova, non-admin.
  2. Environments → local → Access : rôle le plus bas suffisant. (CE = RBAC par environnement, pas par stack ; le vrai verrou Phase 1 reste PORTAINER_READ_ONLY=true.)
  3. Connecté en chlovaMy account → Access tokens → Add tokenPORTAINER_MCP_AUTH_TOKEN.

3b. n8n-chlova — MCP token

  1. https://n8n-chlova.pogoo.app → créer le compte propriétaire.
  2. Activer le serveur MCP natif, générer le MCP Access TokenMCP_N8N_AUTH_TOKEN. Endpoint interne : http://n8n-chlova:5678/mcp-server/http.

4. Secrets login UI (générés, jamais commités)

cd orchestrator
npm run provision-auth -- <admin_user> '<mot_de_passe_fort>'

CHLOVA_ADMIN_PASSWORD_HASH, CHLOVA_TOTP_SECRET, CHLOVA_JWT_SECRET + otpauth://… (scanner dans l'app TOTP). À saisir dans les variables de stack (§5).

5. Déploiement du stack chlova

infra/docker-compose.prod.yml n'a aucun env_file : toutes les variables sont des variables de stack Portainer (les secrets y sont saisis par l'opérateur, jamais par l'agent).

Variable Valeur Secret ?
CHLOVA_DOMAIN chlova.pogoo.app non
CHLOVA_PHASE 1 non
PORTAINER_READ_ONLY true non
PORTAINER_URL http://portainer:9000 (défaut, interne) non
OLLAMA_API_KEY clé Ollama cloud oui
OLLAMA_MODEL qwen3:cloud non
MCP_N8N_AUTH_TOKEN token MCP n8n-chlova (§3b) oui
PORTAINER_MCP_AUTH_TOKEN token user chlova (§3a) oui
CHLOVA_ADMIN_USER ex. kantin non
CHLOVA_ADMIN_PASSWORD_HASH (§4) oui
CHLOVA_TOTP_SECRET (§4) oui
CHLOVA_JWT_SECRET (§4) oui

Stacks → Add stack → Git repository :

  • Repository URL = http://gitea:3000/<admin>/chlova.git (clone interne) ou https://git.pogoo.app/<admin>/chlova.git.
  • Authentication = user gitea + token (§1.3).
  • Reference = refs/heads/main ; Compose path = infra/docker-compose.prod.yml.
  • Environment variables = tableau ci-dessus.
  • Deploy. Portainer clone, build l'image et lance le stack.

6. Vérification

  1. Stack chlova running ; conteneurs backend, ollama, mcp-portainer, socket-proxy up.
  2. Logs backend : API/UI activée (auth configurée) + healthcheck interne prêt. Pas d'erreur fail-closed.
  3. https://chlova.pogoo.app → page login (mot de passe + TOTP).
  4. Connexion → Chat répond ; outils MCP read-only (n8n + Portainer) listés.

7. Rollback

GitOps : revert du commit compose + redeploy, ou Stacks → chlova → Stop/Remove. Volume chlova-data (SQLite) persiste ; le supprimer pour repartir de zéro.

8. Passage Phase 2 (plus tard)

Écriture sous gatekeeper + need-review : CHLOVA_PHASE=2 et PORTAINER_READ_ONLY=false (mutations alors filtrées par gatekeeper + paliers de risque). Uniquement après validation du cerveau en lecture seule. Voir docs/need-review.md.