Commit graph

35 commits

Author SHA1 Message Date
alkatrazz
4e0b683cbd fix(auto-improve): corriger chemin src Ansible (playbook_dir remonte 2 niveaux) 2026-06-02 23:59:38 +02:00
alkatrazz
4a7a5ac9fc feat(auto-improve): workflow Hermes d'analyse et amélioration de la doc
Pipeline complet dans feature/hermes-auto-improve :
- auto-improve.py : analyse admin/ avec hermes --profile funk-ai, applique
  les améliorations, committe dans la branche, ré-ingère dans Qdrant
- trigger-server.py : HTTP 9095 (POST /trigger, /trigger/all, /trigger/subdir,
  /trigger/dry-run) pour déclenchement depuis n8n ou manuellement
- Ansible role hermes_auto_improve : déploie scripts + service systemd sur s01
- n8n workflow "Hermes Auto-Improve" (ID: CX72UUOempE1YtNL) : schedule
  hebdo dimanche 09h + webhook manuel → analyse → résumé LLM → email

Tout reste dans cette branche — rien ne touche main avant review.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 23:53:53 +02:00
alkatrazz
91e648f55e feat(monitoring): métriques conso électrique CPU+GPU (RAPL + ROCm power)
- node_exporter : activer --collector.rapl (CPU power package, storage-01 + gpu-01 + nœuds k8s)
- rocm_scraper : ajouter rocm_gpu_power_watts + rocm_gpu_power_cap_watts via sysfs hwmon
- gpu-01 : activer rocm_exporter_enabled
- kube-prometheus-stack : propager --collector.rapl aux DaemonSet Talos via prometheus-node-exporter.extraArgs

Déployé sur storage-01 et gpu-01. ArgoCD prend en charge les nœuds Talos.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 22:54:51 +02:00
alkatrazz
a3ba3089e2 feat(voice): améliorer hermes-voice + fix hermes-agent
hermes-voice :
- mode SSH : appel `hermes -z` via storage-01 (soul + skills + RAG + mémoire)
- mode litellm : fallback avec historique de session (10 échanges)
- Whisper large-v3 : meilleure reconnaissance FR (distil-large-v3 dérivait vers l'anglais)
- forcer français dans les requêtes SSH
- historique conversationnel + reset vocal ("oublie tout")

hermes-agent :
- fix boucle de redémarrage (510 restarts) : ajouter --replace à ExecStart

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 16:24:21 +02:00
alkatrazz
6fc5b5984e feat(voice): ajouter client vocal Hermes (hermes-voice)
- tools/hermes-voice/ : pipeline VAD → faster-whisper → LiteLLM → piper TTS
- mot-clé "hermes" détecté dans la transcription Whisper (pas de wake word model)
- modes : VAD continu + push-to-talk + --no-tts pour debug
- nftables : ouvrir port 4000 LiteLLM vers LAN domestique (192.168.1.0/24)
- admin/ia/hermes-voice.md : documentation installation et utilisation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 15:12:44 +02:00
alkatrazz
e644c1ae1b fix(nftables): ouvrir port 25 SMTP pour pods k8s (10.42/16)
n8n tourne dans un pod k8s — le port 25 de postfix n'était ouvert
que pour 192.168.10.0/24 (nœuds cluster), pas pour 10.42.0.0/16
(pods). Connexion ETIMEDOUT au nœud Send Email du workflow alertes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 17:27:08 +02:00
alkatrazz
8c94936467 fix(postfix): basculer relay de Brevo vers Gmail SMTP
Brevo rejetait les mails envoyés depuis aliyesilkaya93@gmail.com
(domaine non vérifié côté Brevo). Gmail SMTP signe lui-même les mails
→ livraison garantie vers le compte Gmail destinataire.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 17:13:24 +02:00
alkatrazz
ad49b129a1 fix(litellm): exposer port 4000 au cluster k8s
LiteLLM écoutait sur 127.0.0.1 uniquement — les pods k8s (10.42.x.x)
ne pouvaient pas atteindre 192.168.10.1:4000, Open WebUI affichait
"Aucun modèle disponible". Binding changé en 0.0.0.0 + nftables ouvert
pour 192.168.10.0/24 et 10.42.0.0/16.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 16:15:37 +02:00
alkatrazz
f9609e48dd fix(k8s/open-webui): memory 1Gi→2Gi (OOMKill HuggingFace download au boot)
fix(ansible/postgresql): GRANT ALL ON SCHEMA public (PostgreSQL 15+ default)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 15:42:54 +02:00
alkatrazz
bdd36d7188 fix(ansible/postgresql): no_log sur Grant + alias db déprécié → database
- Grant user privileges : ajout no_log:true (mot de passe visible en clair
  dans les logs Ansible en cas d'échec via item loop)
- Alias 'db' déprécié par community.postgresql → renommé 'database'
- litellm DB recrée manuellement (corruption pg_attribute copiée depuis RAID)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 15:25:42 +02:00
alkatrazz
77c4fe99c2 fix(ansible/nfs_server): supprimer le montage RAID — /srv/data est NVMe bind-mount
La tâche "Mount RAID5 array (fstab + immediate)" écrasait l'entrée fstab
bind-mount (/home/data → /srv/data) et remontait le RAID à chaque apply.

- Suppression de ansible.posix.mount state=mounted pour le RAID
- La tâche mdadm.conf devient conditionnelle (when: stdout non vide)
  et failed_when: false pour ne pas bloquer si le RAID n'est pas assemblé
- Ajout d'un sanity-check : vérifie que /srv/data est un répertoire
- Commentaires explicatifs dans tasks/ et defaults/ pour prévenir toute
  régression future

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 15:21:26 +02:00
alkatrazz
bc137d13b4 feat(k8s): déployer Open WebUI + n8n sur namespace ai via ArgoCD
Open WebUI (openwebui.lab.local) :
- Connecté à LiteLLM (192.168.10.1:4000/v1) comme backend OpenAI-compatible
- PostgreSQL via storage-01 pour l'historique des conversations
- PVC 5Gi NFS pour les uploads, Traefik IngressRoute

n8n (n8n.lab.local) :
- PostgreSQL via storage-01, chiffrement des credentials
- PVC 2Gi NFS, Traefik IngressRoute
- Webhook URL interne : http://n8n.lab.local

Ansible : ajoute openwebui et n8n dans postgresql_databases/users
(vault_pg_openwebui_password + vault_pg_n8n_password à ajouter au vault)

Prérequis avant 1er déploiement :
  make vault-edit   # ajouter les 2 passwords
  make apply-storage --tags postgresql
  kubectl create secret generic open-webui-secret -n ai ...
  kubectl create secret generic n8n-secret -n ai ...

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 15:08:41 +02:00
alkatrazz
8da92cb721 feat(postfix): relay SMTP Gmail + suppression règles Conan nftables
- postfix_relay: switch Brevo → Gmail SMTP (smtp.gmail.com:587, App Password)
- smtp_generic_maps: réécriture expéditeur root@lab.localaliyesilkaya93@gmail.com
- nftables: suppression DNAT/NAT Conan Exiles (ports 7777/7778/27015)
- gateway handler: reloaded → restarted (flush complet des règles nft)
- hermes_agent: pip → uv pour installation qdrant-client (venv sans pip binaire)
- CLAUDE.md: corrections funk-cluster, hermes-switch, RAID5, postfix
- docs: admin/infra/email.md — procédure complète relay Gmail

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 16:46:42 +02:00
alkatrazz
eae6e76645 feat(rag): RAG Hermes — Qdrant + rag-ingest/rag-query + skill funk-ai
Indexation de admin/ (284 chunks) dans Qdrant via embeddings Qwen3-8B.
rag-query utilisable en CLI et depuis le profil funk-ai de Hermes.
Note: modèle d'embedding générique — qualité limitée, voir admin/ia/rag.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 22:16:06 +02:00
alkatrazz
3a013834aa fix(webhook): réponse HTTP 200 immédiate + ask-agent asynchrone
BrokenPipeError corrigé : send_response(200) envoyé avant subprocess.
ask-agent lancé en threading.Thread daemon — AlertManager n'attend plus.
NO_COLOR=1 + TERM=dumb pour éviter les codes ANSI dans les logs.

docs: alertmanager-webhook.md — architecture, flux, test, dépannage

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 21:58:39 +02:00
alkatrazz
c97e895b87 fix(nftables): ouvre port 9093 pour AlertManager webhook → Hermes monitor
Les pods AlertManager (10.42.0.0/16) ne pouvaient pas joindre le webhook
sur storage-01:9093 — alertes Prometheus reçues mais jamais transmises à
ask-agent monitor. Port 9093 ajouté pour pods k8s + nœuds cluster.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 21:37:48 +02:00
alkatrazz
0498d770f2 fix(monitoring): dashboard infra nodata — nftables pod CIDR + mountpoint
nftables.conf.j2 :
  - Ajoute 10.42.0.0/16 (CIDR pods k8s) pour port 9100 (node_exporter)
    et port 8080 (hermes webhook AlertManager)
  - Appliqué live sur storage-01 + persisté dans /etc/sysconfig/nftables.conf
  - storage-01 était up=0 (timeout) car pods Prometheus ne pouvaient pas
    l'atteindre malgré node_exporter actif

dashboard-infrastructure.yaml :
  - Corrige mountpoint /srv → /srv/data (RAID5 monté sur /srv/data)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 18:42:11 +02:00
alkatrazz
f937c2589d fix(funk-cluster): grep -c bug + uncordon automatique au démarrage
- check_k8s_pods : grep -c retournait "0\n0" (|| echo 0 inutile quand
  grep-c affiche 0 même en cas d'absence de match) — utilise un cache
  intermédiaire pods_output + running=$(grep -c) || running=0
- cmd_start : uncordon automatique si nœuds SchedulingDisabled détectés
  (séquelle d'un funk-stop --k8s), suivi d'une attente pod infra avant
  le check — évite de devoir passer --k8s juste pour débloquer le cluster

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 17:57:12 +02:00
alkatrazz
494184b025 feat(funk-cluster): check k8s pod health in funk-start et funk-status
Ajoute check_k8s_pods / check_k8s_workloads (argocd, infra, monitoring).
funk-start vérifie désormais les pods k8s si les nœuds sont joignables,
même sans --k8s. En mode --k8s : attente ArgoCD + infra avant le check.
funk-status montre aussi l'état des pods si cluster up.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 17:54:18 +02:00
alkatrazz
a4a5fb2383 fix(funk-cluster): SIGKILL process fils hermes avant umount /srv/data
hermes-agent spawne des process Python qui survivent hors du cgroup
systemd après stop_service. Ils gardent des file descriptors ouverts sur
/srv/data (logs, state.db-shm) et bloquent le umount.

Ajout d'un lsof + kill -9 sur tous les process tenant /srv/data avant
sync + umount — garantit un démontage propre sans dépendre de systemd.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 01:09:53 +02:00
alkatrazz
0c37635802 fix(funk-cluster): umount propre /srv/data avant extinction storage-01
Avant, shutdown -h now était appelé directement après stop qdrant/postgresql.
systemd démontait /srv/data pendant la séquence d'extinction sans garantie
que tous les buffers aient été flushés.

Séquence ajoutée avant shutdown :
  1. stop nfs-server (était oublié dans le script)
  2. sync — flush tous les buffers disque
  3. umount /srv/data — démontage explicite du RAID5
  Si umount échoue, lsof affiche le processus bloquant avant d'abandonner.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 01:06:53 +02:00
alkatrazz
83c10feae7 fix: monitoring — collecte métriques externes (nftables, llama --metrics, ROCm via 9100)
- nftables storage-01 : ports 9100 (node_exporter) + 9093 (webhook) ouverts pour 192.168.10.0/24
- llama-server : ajout --metrics pour exposer /metrics sur les 3 instances
- values.yaml : suppression job gpu-01-rocm:9101 inexistant (ROCm passe par node_exporter 9100 textfile_collector)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 22:41:19 +02:00
alkatrazz
c9fd0d2812 feat: funk-cluster start --k8s — uncordon + attente ArgoCD
Après funk-stop --k8s, les nœuds reviennent Ready mais SchedulingDisabled
(cordon stocké dans etcd). Sans uncordon, tous les pods restent Pending.

Ajouts dans funk-start --k8s :
- kubectl uncordon sur les nœuds SchedulingDisabled uniquement (idempotent)
- Attente ArgoCD Running (jusqu'à 3 min) — confirme que le GitOps est opérationnel

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 22:22:12 +02:00
alkatrazz
a631a4ab6c feat: funk-cluster — arrêt k8s propre avec drain + vérification NFS
Remplace le talosctl shutdown immédiat par une séquence en 6 étapes :
1. kubectl cordon tous les nœuds (empêche rescheduling)
2. kubectl drain compute-02/03 (SIGTERM pods, 30s grace, PVCs NFS libérés)
3. kubectl drain compute-01 (ArgoCD, system pods)
4. Vérification NFS : ss confirme plus de sessions :2049 actives
5. talosctl shutdown (halt propre, plus rien ne tourne)
6. Attente extinction ping

Prometheus et Grafana ont 30s pour flusher WAL/SQLite avant terminaison.
storage-01 (NFS server) est éteint en dernier une fois la vérification passée.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 22:20:14 +02:00
alkatrazz
92a882aa94 feat: monitoring — node_exporter + ROCm sysfs collector + alertmanager webhook
Ansible roles:
- node_exporter : déploie node_exporter v1.9.1 sur storage-01 et gpu-01
  avec textfile collector + services systemd. ROCm activé sur gpu-01 uniquement
  via group_vars. Collecte métriques GPU via sysfs (temp, VRAM, utilisation)
  — pas de dépendance rocm-smi (remplacé dans ROCm 7.x)
- alertmanager_webhook : service Python sur storage-01 (:9093/webhook)
  reçoit alertes AlertManager et les route vers ask-agent monitor → Hermes

Playbooks: node_exporter + alertmanager_webhook ajoutés à storage-01 et gpu-01

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 21:01:03 +02:00
alkatrazz
00d10234f9 feat: amélioration routing ask-agent + identité SOUL.md profils
- SOUL.md funk-ai : tableaux détaillés system vs monitor (quand appeler
  chaque agent avec exemples concrets), section delegate_task vs ask-agent
- SOUL.md system : rôle clarifié (traitement texte, PAS analyse santé),
  format de réponse explicite (verdict direct, pas de préambule)
- hermes-agent.service : SupplementaryGroups=systemd-journal pour que
  journalctl fonctionne sans sudo depuis le Terminal de Hermes
- Ansible common : admin_user (alkatrazz) ajouté au groupe systemd-journal
- admin/hermes.md : section SOUL.md complète (déploiement, contenu, profils)
- admin/ask-agent.md : distinction system vs monitor documentée avec
  tableau et exemples, note /no_think, monitor réservé supervision

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 18:59:48 +02:00
alkatrazz
5e93c1d3d7 fix: ask-agent /no_think + SKILL.md renforcé + tests 10/10
- ask-agent : ajout /no_think pour agents system et monitor
  (Qwen3-1.7B en mode thinking consommait tous les tokens sur
  le raisonnement interne, laissant content: "" vide)
- SKILL.md v1.1.0 : règles OBLIGATOIRES de délégation, distinction
  ask-agent vs delegate_task, exemples concrets, syntaxe exacte
- test.sh : suite 10 tests end-to-end — CLI disponible, LiteLLM,
  system/monitor/brain, données réelles, skill présence/activation,
  Hermes funk-ai appelle Terminal: ask-agent

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 17:26:25 +02:00
alkatrazz
6be2a89480 feat: rôle hermes_user + ask-agent + skills délégation
- Nouveau rôle hermes_user : création user/group UID 1002 sur storage-01
  et gpu-01, sudoers limités par host, clé SSH ed25519 générée sur
  storage-01 et distribuée vers gpu-01, ssh_config + known_hosts
- Kubeconfig copié depuis ansible vers hermes sur storage-01
- ask-agent : script bash LiteLLM pour déléguer aux agents
  system/monitor/brain/funk-ai
- hermes-skills/funk/agent-delegation : skill Hermes pour les
  inter-profile calls avec pattern Terminal: ask-agent
- Playbooks storage-01 et gpu-01 : ajout du rôle hermes_user

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 16:03:43 +02:00
alkatrazz
763b29495e docs: incident EXT4 2026-05-13 + hermes-agent nouvelle archi SSD
- incidents.md : incident corruption EXT4 après arrêt brutal (655 erreurs,
  e2fsck, réinstall hermes-agent, nouveau chemin /opt/hermes/.hermes/)
- hermes.md : arborescence mise à jour (code SSD vs données RAID5),
  chemins pip/venv/frontend corrigés
- Ansible role hermes_agent : venv path et wrapper mis à jour
  (hermes_home/.hermes/hermes-agent/venv/ au lieu de hermes_data_dir/)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 14:49:53 +02:00
alkatrazz
a1826fe339 docs: gestion cluster + script funk-cluster mis à jour
- admin/cluster.md : nouveau guide démarrage/arrêt (funk-start/stop/--k8s)
- admin/README.md : lien vers cluster.md
- admin/systeme.md : services llama-server mis à jour (GPU + 2 CPU)
- ansible/roles/litellm/files/funk-cluster : script versionné
  (talosctl fix, storage-01 shutdown, --k8s optionnel, stop timeout)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 02:11:21 +02:00
alkatrazz
c8a1faa632 feat: MetalLB + Traefik + wildcard DNS lab.local
- MetalLB pool 192.168.10.200-230 (L2 mode)
- Traefik LoadBalancer sur 192.168.10.200 (HTTP/HTTPS)
- dnsmasq wildcard *.lab.local → 192.168.10.200
- Fix Flannel CrashLoopBackOff : ClusterRoleBinding corrigée (kube-flannel → kube-system)
- Doc talos.md : procédure complète MetalLB + Traefik + pièges Flannel

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 22:45:06 +02:00
alkatrazz
bb72145365 feat(talos): bootstrap Kubernetes cluster funk (3 nodes, v1.33.1)
- Add talconfig.yaml with compute-01/02/03 (nvme0n1, Flannel CNI)
- Add SOPS/age encryption for talsecret.sops.yaml
- Add patches: NTP/DNS → storage-01, kubelet reserved for 8GB workers
- Fix nftables: open DHCP port 67 for cluster LAN
- Add dnsmasq DHCP with static leases for all 3 compute nodes
- Add admin/talos.md: full install procedure + admin commands
- Install kubectl + talosctl on storage-01

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 22:11:38 +02:00
alkatrazz
dca71144d6 docs(admin): add ops documentation and fix hermes dashboard service
- Remove admin/ from .gitignore (repo is now private)
- Add --tui flag to hermes-dashboard.service template
- Document hermes-tui wrapper, dashboard access, TUI usage

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 18:50:43 +02:00
alkatrazz
572e949ce4 ajout de linterface hermes + route 2026-05-12 18:01:50 +02:00
alkatrazz
b3fce8af5d feat: initial commit — Ansible roles storage-01/gpu-01 opérationnels 2026-05-12 17:17:03 +02:00