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
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).
- Ouvrir
https://git.pogoo.app→ compléter l'install (DB = SQLite déjà réglée) → créer le compte admin. - New repository :
chlova(privé). - 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
- Users → Add user :
chlova, non-admin. - 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.) - Connecté en
chlova→ My account → Access tokens → Add token →PORTAINER_MCP_AUTH_TOKEN.
3b. n8n-chlova — MCP token
https://n8n-chlova.pogoo.app→ créer le compte propriétaire.- Activer le serveur MCP natif, générer le MCP Access Token →
MCP_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) ouhttps://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
- Stack
chlovarunning ; conteneursbackend,ollama,mcp-portainer,socket-proxyup. - Logs
backend:API/UI activée (auth configurée)+healthcheck interne prêt. Pas d'erreur fail-closed. https://chlova.pogoo.app→ page login (mot de passe + TOTP).- 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.