- Remove Funk/ from .gitignore (repo is private) - Add HOMELAB.md and agent configs for Hermes context - Update hermes TUI doc: must run as hermes user from /srv/data/hermes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
34 KiB
Homelab IA — Architecture et plan de déploiement
Document de référence consolidé pour le déploiement d'un homelab IA combinant un cluster Kubernetes (Talos) pour les services applicatifs et deux hôtes Linux dédiés pour l'inférence LLM (LM Studio) et l'agent autonome (Hermes Agent). Stack IaC complète : Ansible + talhelper + ArgoCD, GitOps de bout en bout. À utiliser comme contexte pour Claude Code.
1. Objectifs
- Faire tourner Hermes Agent (Nous Research) comme agent autonome auto-amélioré, alimenté par LM Studio comme serveur d'inférence local.
- Apprendre Kubernetes en environnement réaliste (cluster multi-nœuds, GitOps) pour les services applicatifs (Open WebUI, n8n, monitoring...).
- Apprendre Talos Linux (OS immuable, API-only, pensé pour Kubernetes).
- Maximiser l'utilisation du GPU AMD RX 6700XT pour l'inférence LLM.
- Tout gérer en Infrastructure as Code (versionné dans Git).
2. Priorités (par ordre)
- Facilité d'administration
- Apprentissage / montée en compétences
- Performance brute (utiliser le 6700XT au max)
- Haute disponibilité / résilience
3. Vision long terme
- Cible : ~10 machines à 2-3 ans, mix Talos (cluster k8s) + AlmaLinux (services natifs)
- Tout doit être reproductible depuis Git (réinstall complète possible en quelques heures)
- BlueBanquise reste une option à reconsidérer si on dépasse 25+ hôtes Linux classiques ou si on ajoute du HPC/Slurm
4. Inventaire matériel
| Machine | CPU | RAM | Stockage | Réseau | Rôle |
|---|---|---|---|---|---|
| storage-01 | AMD Ryzen 3 3200G (Zen+, 2019) | 32 GB DDR4 | 1× SSD OS + 4×1 TB RAID5 (2.7 TB exploitables) | 1× Gigabit | Hors cluster — passerelle + admin + stockage + Hermes Agent |
| compute-01 | AMD A10-9700E (Excavator, 2016) | 16 GB DDR3 | SSD SATA | 1× Gigabit (r8169) | k8s control-plane (Talos) |
| compute-02 | AMD A10-9700E | 8 GB DDR3 | SSD SATA | 1× Gigabit (r8169) | k8s worker (Talos) |
| compute-03 | AMD A10-9700E | 8 GB DDR3 | SSD SATA | 1× Gigabit (r8169) | k8s worker (Talos) |
| gpu-01 | AMD Ryzen 9 5950X (16 cœurs) | 32 GB DDR4 | NVMe 1 TB | 1× Gigabit | Hors cluster — hôte LM Studio dédié — RX 6700XT 12 GB |
| switch | Netgear GS308EV4 (8 ports Gigabit, managé Plus, VLAN 802.1Q) | — | — | — | Switch principal |
Validation Talos déjà effectuée : compute-01 boote correctement avec Talos v1.13.0 en mode maintenance, IP DHCP obtenue, chipset r8169 reconnu nativement.
5. Architecture réseau
5.1. Topologie physique
Internet
│
┌───────────┐
│ Freebox │ 192.168.1.254 (gateway + DHCP LAN domestique)
└─────┬─────┘
│
│ VLAN 1 (port 1)
│
┌─────┴────────────────────────────────────────┐
│ Switch Netgear GS308EV4 │
│ P1 P2 P3 P4 P5 P6 P7 P8 │
│ V1 V1 V10 V10 V10 V10 V10 V1 │
└──┬───┬───┬───┬───┬───┬───┬───┬──────────────┘
│ │ │ │ │ │ │ └── PC perso (192.168.1.x)
│ │ │ │ │ │ └────── storage-01 NIC2 (192.168.10.1) ← LAN cluster
│ │ │ │ │ └────────── compute-03 (.10.13)
│ │ │ │ └────────────── compute-02 (.10.12)
│ │ │ └────────────────── compute-01 (.10.11)
│ │ └────────────────────── gpu-01 (.10.20)
│ └────────────────────────── storage-01 NIC1 (192.168.1.200) ← WAN
└────────────────────────────── Freebox
┌──────────────────────────────┐
│ storage-01 (AlmaLinux 9.7) │
│ - NIC1 (port 2) : 192.168.1.200 ← WAN / LAN domestique
│ - NIC2 (port 7) : 192.168.10.1 ← LAN cluster + gateway + NAT
└─────┬────────────────────────┘
│ (routage + NAT entre les deux interfaces)
│
┌────┴────┬──────────┬──────────┐
│ │ │ │
compute-01 compute-02 compute-03 gpu-01
.10.11 .10.12 .10.13 .10.20
(Talos) (Talos) (Talos) (AlmaLinux + LM Studio)
5.2. Vue logique des composants IA
┌──────────────────────────────────────────────────────────────────────┐
│ Cluster Kubernetes (Talos) │
│ 3 nœuds : compute-01/02/03 │
│ │
│ • Open WebUI • Traefik (ingress) │
│ • LiteLLM (proxy) • MetalLB (LB L2) │
│ • n8n (workflows) • cert-manager │
│ • Prometheus/Grafana • ArgoCD (GitOps) │
└──────────────────┬─────────────────────────┬─────────────────────────┘
│ │
│ NFS / S3 / DB │ HTTP /v1/chat/completions
▼ ▼
┌──────────────────────────────┐ ┌──────────────────────────────────┐
│ storage-01 (AlmaLinux 9.7) │ │ gpu-01 (AlmaLinux 9.7) │
│ 192.168.10.1 HORS CLUSTER │ │ 192.168.10.20 HORS CLUSTER │
│ │ │ │
│ Données : │ │ • LM Studio (mode serveur) │
│ • NFS (/srv/nfs/k8s) │ │ écoute sur :1234 │
│ • PostgreSQL │ │ • API OpenAI-compatible │
│ • Qdrant (vectoriel) │ │ • RX 6700XT via ROCm/Vulkan │
│ • MinIO (S3) │ │ • CLI `lms` pour pilotage │
│ │ │ │
│ Agent IA : │ │ │
│ • Hermes Agent ★ │◄──┤ Hermes appelle LM Studio │
│ (service systemd) │ │ via http://192.168.10.20:1234 │
│ │ │ │
│ Infra : │ │ │
│ • Passerelle / NAT │ │ │
│ • dnsmasq (lab.local) │ │ │
│ • Bastion admin │ │ │
└──────────────────────────────┘ └──────────────────────────────────┘
5.3. Plan d'adressage IP
LAN domestique (existant, géré par la Freebox) — 192.168.1.0/24
| IP | Hôte | Notes |
|---|---|---|
192.168.1.254 |
Freebox | Gateway internet + DHCP |
192.168.1.10 |
Machine 9950x3d (poste perso) | Déjà occupé |
192.168.1.200 |
storage-01 (interface WAN cluster) | IP statique réservée |
LAN cluster (nouveau, isolé) — 192.168.10.0/24
| IP | Hostname | Rôle |
|---|---|---|
192.168.10.1 |
storage-01 | Gateway + admin + stockage + Hermes Agent (hors cluster k8s) |
192.168.10.11 |
compute-01 | k8s control-plane (Talos, 16 GB) |
192.168.10.12 |
compute-02 | k8s worker (Talos, 8 GB) |
192.168.10.13 |
compute-03 | k8s worker (Talos, 8 GB) |
192.168.10.20 |
gpu-01 | Hôte LM Studio dédié (AlmaLinux, hors cluster k8s) |
192.168.10.200-230 |
(pool) | MetalLB — IP virtuelles des services k8s exposés |
Ports applicatifs notables
| Hôte | Port | Service | Notes |
|---|---|---|---|
| gpu-01 | 1234 | LM Studio API (OpenAI-compatible) | http://192.168.10.20:1234/v1 |
| storage-01 | 22 | SSH (bastion + cible Ansible) | |
| storage-01 | 53 | dnsmasq | Résolution *.lab.local |
| storage-01 | 2049 | NFS | Export /srv/nfs/k8s |
| storage-01 | 5432 | PostgreSQL | |
| storage-01 | 6333 | Qdrant HTTP | |
| storage-01 | 9000 | MinIO S3 | |
| storage-01 | 9001 | MinIO Console | |
| MetalLB | 80/443 | Traefik | Tous les Ingress du cluster |
| MetalLB | 8080 | ArgoCD UI | argocd.lab.local |
Réseaux internes Kubernetes (ne pas modifier sauf raison spécifique)
- Pods (Flannel) :
10.42.0.0/16 - Services :
10.43.0.0/16
5.4. Câblage du switch GS308EV4
Tous les ports en mode Access (pas de trunk). storage-01 utilise deux NICs physiques — une par VLAN.
| Port | Connecté à | VLAN | Mode |
|---|---|---|---|
| 1 | Freebox | 1 - Default | Access |
| 2 | storage-01 NIC1 (WAN, 192.168.1.200) | 1 - Default | Access |
| 3 | gpu-01 (192.168.10.20) | 10 - cluster-funk | Access |
| 4 | compute-01 (192.168.10.11) | 10 - cluster-funk | Access |
| 5 | compute-02 (192.168.10.12) | 10 - cluster-funk | Access |
| 6 | compute-03 (192.168.10.13) | 10 - cluster-funk | Access |
| 7 | storage-01 NIC2 (LAN cluster, 192.168.10.1) | 10 - cluster-funk | Access |
| 8 | PC perso (192.168.1.x) | 1 - Default | Access |
Avantage vs trunk : pas de subinterface eno1.10 à configurer — deux interfaces physiques classiques dans NetworkManager. Plus simple, moins de risque d'erreur au démarrage.
5.5. Route statique sur la Freebox
À configurer dans Paramètres Freebox > Mode avancé > Configuration de routage :
Réseau de destination : 192.168.10.0
Masque : 255.255.255.0
Passerelle : 192.168.1.200
Cela permet à toutes les machines du LAN domestique de joindre directement le LAN cluster.
6. Choix d'OS
| Machine | OS | Justification |
|---|---|---|
| storage-01 | AlmaLinux 9.7 minimal | Stack RHEL maîtrisée, stabilité, support sécurité jusqu'en 2032, doc abondante NFS/nftables/MinIO/Postgres |
| compute-01 | Talos Linux v1.13+ | Choix d'apprentissage assumé, validation matérielle OK |
| compute-02 | Talos Linux v1.13+ | idem |
| compute-03 | Talos Linux v1.13+ | idem |
| gpu-01 | AlmaLinux 9.7 minimal | Cohérence RHEL avec storage-01, ROCm via repo officiel AMD pour RHEL 9 |
Note sur AlmaLinux + ROCm pour gpu-01 : la majorité de la doc communautaire
ROCm + RX 6700XT vise Ubuntu. Sur AlmaLinux 9, utiliser le repo officiel AMD
pour RHEL 9 (https://repo.radeon.com/rocm/). Adapter les commandes dnf au
lieu d'apt. En cas de blocage ROCm, Vulkan reste un fallback fonctionnel pour LM Studio.
7. Architecture applicative
7.1. Topologie cluster Kubernetes
- Control-plane : single (compute-01 uniquement)
- Workers : compute-02, compute-03
- storage-01 et gpu-01 sont HORS du cluster
7.2. Découpage des responsabilités
gpu-01 — Hôte d'inférence LLM (hors cluster)
- LM Studio en mode serveur headless
- API OpenAI-compatible exposée sur
:1234
storage-01 — Bastion admin + données + agent (hors cluster)
- Passerelle réseau (NAT, routage VLAN)
- Bastion :
talosctl,kubectl,helm,argocdCLI,ansible - Services données : NFS, PostgreSQL, Qdrant, MinIO
- Hermes Agent en service systemd
- dnsmasq pour la résolution
*.lab.local
Cluster Kubernetes (Talos, 3 nœuds)
- Couche infra : MetalLB, Traefik, cert-manager, Longhorn, nfs-subdir-external-provisioner
- Couche observabilité : kube-prometheus-stack, Loki
- Couche applicative IA : Open WebUI, LiteLLM, n8n
- GitOps via ArgoCD
7.3. Flux principal Hermes ↔ LM Studio
Utilisateur → CLI Hermes / Telegram / autre interface
(sur storage-01)
│
▼
Hermes Agent (skills, mémoire, tools)
[storage-01 :daemon systemd]
│
│ HTTP POST /v1/chat/completions
▼
LM Studio (modèle chargé en VRAM 6700XT)
[gpu-01 :1234]
│
│ Réponse streaming
▼
Hermes Agent (parsing tool calls, exécution)
│
▼
Utilisateur
7.4. Deux setups IA — poste perso vs cluster Funk
Setup 1 — Poste perso (9950X3D) — dev local
Matériel : Ryzen 9 9950X3D · 32 GB DDR5 · RX 9070 XT 16 GB VRAM
| Composant | Config |
|---|---|
| LM Studio | http://127.0.0.1:1234/v1 (bind localhost par défaut) |
| Ollama | http://127.0.0.1:11434 (aussi installé) |
| Hermes Agent | config base_url: http://127.0.0.1:1234/v1 |
| Goose agents | Funk/Funk-infra/agents/ → pointent sur http://localhost:1234/v1 |
Démarrage LM Studio :
# Charger le modèle avec un context suffisant (système Hermes ≈ 15 000 tokens)
lms load <modele> --context-length 16384
lms server start --port 1234
Config Hermes (~/.hermes/config.yaml) :
model:
default: <nom-modele>
provider: lmstudio
base_url: http://127.0.0.1:1234/v1
context_length: 16384
Goose agents :
cd Funk/Funk-infra/agents/<nom-agent>
goose session --config goose-config.yaml
| Agent Goose | Modèle cible | Usage |
|---|---|---|
global |
qwen2.5-14b | Raisonnement général |
infra |
qwen2.5-coder-14b | k8s, Talos, Helm, ArgoCD |
sysadmin |
qwen2.5-7b | Admin système, diagnostics |
monitoring |
llama3.2-3b | Logs, métriques |
data |
qwen2.5-14b | Analyse de données |
Setup 2 — Cluster Funk (production)
Matériel GPU : gpu-01, Ryzen 9 5950X · 32 GB DDR4 · RX 6700XT 12 GB VRAM
| Composant | Config |
|---|---|
| LM Studio | http://192.168.10.20:1234/v1 (bind 0.0.0.0) |
| Hermes Agent | service systemd sur storage-01 |
Hermes base_url |
http://192.168.10.20:1234/v1 |
Démarrage LM Studio sur gpu-01 :
HSA_OVERRIDE_GFX_VERSION=10.3.0 lms load <modele> --context-length 16384
lms server start --port 1234 --host 0.0.0.0
Config Hermes sur storage-01 (~/.hermes/config.yaml) :
model:
default: <nom-modele>
provider: lmstudio
base_url: http://192.168.10.20:1234/v1
context_length: 16384
Différence clé avec setup 1 : HSA_OVERRIDE_GFX_VERSION=10.3.0 obligatoire pour la RX 6700XT (gfx1031 non officiellement supporté par ROCm). Sur la RX 9070 XT du poste perso, cette variable n'est pas nécessaire.
8. Stack IaC / Automatisation
8.1. Principe : un seul repo Git, trois flux de déploiement
Toute l'infrastructure est gérée en GitOps depuis un repo Git unique. Trois outils se partagent les responsabilités selon la cible :
┌──────────────────────────────────────────────────────────────────┐
│ Repo Git du lab (sur poste admin + remote Gitea/GitHub privé) │
│ │
│ lab-infra/ │
│ ├── ansible/ ← gère storage-01 + gpu-01 │
│ │ ├── inventory.yml │
│ │ ├── playbooks/ │
│ │ ├── roles/ │
│ │ └── group_vars/ │
│ ├── talos/ ← configs Talos via talhelper │
│ │ ├── talconfig.yaml │
│ │ ├── talsecret.sops.yaml │
│ │ └── clusterconfig/ (généré par talhelper) │
│ ├── k8s/ ← manifests / Helm values │
│ │ ├── apps/ ← apps déployées par ArgoCD │
│ │ ├── infra/ ← MetalLB, Traefik, cert-manager... │
│ │ └── argocd-bootstrap/ ← Application of Applications │
│ └── docs/ │
│ └── HOMELAB.md ← ce document │
└────────┬─────────────────────────┬────────────────────┬──────────┘
│ │ │
│ ansible-playbook │ talosctl │ git push
│ (push manuel SSH) │ apply-config │ → ArgoCD
│ │ (push manuel) │ pull auto
▼ ▼ ▼
storage-01, compute-01/02/03 Workloads dans
gpu-01 (Talos) le cluster k8s
(AlmaLinux)
8.2. Outil 1 — Ansible (vanilla) pour les hôtes Linux classiques
Cible : storage-01 et gpu-01 (et futures machines AlmaLinux/Debian).
Choix : Ansible vanilla, rôles écrits from scratch. Pas de framework type BlueBanquise — surdimensionné pour 5-10 hôtes Linux à terme. À reconsidérer si on dépasse 25+ hôtes ou si on ajoute du HPC/Slurm.
Structure des rôles prévus :
ansible/
├── ansible.cfg
├── inventory.yml
├── group_vars/
│ ├── all.yml # variables communes (DNS, NTP, users)
│ ├── gateway.yml # variables passerelle
│ └── gpu_hosts.yml # variables hôtes GPU
├── host_vars/
│ ├── storage-01.yml
│ └── gpu-01.yml
├── playbooks/
│ ├── site.yml # playbook racine
│ ├── storage-01.yml
│ └── gpu-01.yml
└── roles/
├── common/ # paquets de base, sshd, sudoers, motd
├── gateway/ # NetworkManager VLAN, IP forwarding, nftables, NAT
├── dnsmasq/ # DNS local *.lab.local
├── nfs_server/ # NFS server + exports
├── postgresql/ # Postgres + DB init
├── qdrant/ # Qdrant via Podman
├── minio/ # MinIO via Podman
├── rocm/ # repo AMD + drivers + HSA_OVERRIDE
├── lm_studio/ # install + service systemd
└── hermes_agent/ # install + config + systemd unit
Inventaire :
# ansible/inventory.yml
all:
children:
gateway:
hosts:
storage-01:
ansible_host: 192.168.10.1
gpu_hosts:
hosts:
gpu-01:
ansible_host: 192.168.10.20
almalinux:
children:
gateway:
gpu_hosts:
Lancement type :
cd ansible/
ansible-playbook -i inventory.yml playbooks/site.yml --check # dry-run
ansible-playbook -i inventory.yml playbooks/site.yml # apply
ansible-playbook -i inventory.yml playbooks/site.yml --tags rocm # cibler 1 rôle
Bonnes pratiques :
- Tous les rôles idempotents (peuvent être ré-exécutés sans casse).
- Variables sensibles dans Ansible Vault (mot de passe Postgres, clés API).
- Un playbook = une machine ou un groupe, pas de "playbook fourre-tout".
- Tags systématiques pour cibler un rôle spécifique.
8.3. Outil 2 — talhelper pour les nœuds Talos
Cible : compute-01, compute-02, compute-03.
Pourquoi talhelper : talosctl gen config brut produit des configs longues
et difficiles à maintenir. talhelper lit un seul fichier talconfig.yaml
clair et génère les configs YAML par nœud, avec gestion des secrets (chiffrement
SOPS) et patches par nœud.
Structure :
talos/
├── talconfig.yaml # config déclarative (lue par talhelper)
├── talsecret.sops.yaml # secrets chiffrés (token bootstrap, certs CA)
├── talenv.yaml # version Talos, version k8s
├── patches/ # patches YAML par nœud ou groupe
│ ├── compute-01.yaml
│ └── all-controlplane.yaml
└── clusterconfig/ # généré : ne PAS commit (au .gitignore)
├── lab-compute-01.yaml
├── lab-compute-02.yaml
└── lab-compute-03.yaml
Workflow :
cd talos/
# 1. Éditer talconfig.yaml (ajout d'un nœud, changement de version k8s, etc.)
vim talconfig.yaml
# 2. Régénérer les configs nœud
talhelper genconfig
# 3. Appliquer sur un nœud spécifique
talhelper gencommand apply --node compute-02 | bash
# 4. Bootstrap (uniquement la première fois, sur le control-plane)
talhelper gencommand bootstrap --node compute-01 | bash
# 5. Récupérer le kubeconfig
talhelper gencommand kubeconfig | bash
Avantage GitOps : le talconfig.yaml est ta source de vérité. N'importe qui
(toi dans 6 mois) peut lire ce fichier et comprendre l'état du cluster Talos
sans avoir à inspecter les nœuds.
8.4. Outil 3 — ArgoCD pour les workloads Kubernetes
Cible : tout ce qui tourne dans le cluster k8s (apps + infra k8s).
Principe : ArgoCD surveille en continu un dossier Git et garantit que l'état réel du cluster correspond à ce qui est déclaré dans Git.
Pattern recommandé : "App of Apps"
k8s/
├── argocd-bootstrap/ # bootstrap ArgoCD lui-même
│ └── argocd-install.yaml
├── apps-of-apps/
│ └── root.yaml # une Application qui pointe sur apps/
├── infra/ # déployé d'abord
│ ├── metallb/
│ │ ├── application.yaml
│ │ └── values.yaml
│ ├── traefik/
│ ├── cert-manager/
│ ├── longhorn/
│ └── nfs-provisioner/
└── apps/ # déployé ensuite
├── litellm/
│ ├── application.yaml
│ ├── deployment.yaml
│ ├── service.yaml
│ └── ingress.yaml
├── open-webui/
├── n8n/
├── monitoring/ # kube-prometheus-stack
└── external-services/ # ExternalName vers storage-01
├── postgresql-external.yaml
├── qdrant-external.yaml
└── lm-studio-external.yaml # ExternalName vers gpu-01:1234
Workflow d'utilisation :
# 1. Modifier un manifest
vim k8s/apps/open-webui/deployment.yaml
# 2. Commit + push
git add k8s/apps/open-webui/
git commit -m "open-webui: bump to v0.4.0, add OIDC config"
git push
# 3. ArgoCD détecte le changement (poll par défaut toutes les 3 min)
# → applique automatiquement dans le cluster
# → visible dans l'UI argocd.lab.local
Bénéfices :
- Source de vérité unique (Git)
- Historique complet via
git log - Rollback en
git revert+ push - Recréation totale du cluster en cas de désastre : install Talos via talhelper, install ArgoCD via le bootstrap, ArgoCD redéploie tout le reste tout seul
8.5. Récapitulatif des responsabilités
| Outil | Cible | Mode de déploiement | Stockage source |
|---|---|---|---|
| Ansible | Hôtes Linux classiques (storage-01, gpu-01, futures Alma) | Push manuel (ansible-playbook) |
lab-infra/ansible/ |
| talhelper | Nœuds Talos (compute-01/02/03) | Push manuel (talosctl apply-config) |
lab-infra/talos/ |
| ArgoCD | Workloads Kubernetes (apps + infra k8s) | Pull automatique depuis Git | lab-infra/k8s/ |
8.6. Repo Git : où l'héberger ?
Court terme : repo local sur ton poste + remote sur GitHub (privé) ou GitLab (privé) → simple et fiable.
Moyen terme (recommandé) : héberger un Gitea ou Forgejo sur storage-01 (rôle Ansible dédié) + miroir GitHub pour backup. Avantages :
- Indépendance totale (pas besoin d'Internet pour déployer)
- Apprentissage de l'auto-hébergement Git
- ArgoCD pointe sur
git.lab.local/admin/lab-infra.git
8.7. Gestion des secrets
Pas de secrets en clair dans Git, jamais. Trois mécanismes selon la couche :
- Ansible : Ansible Vault pour les secrets (
ansible-vault encrypt_string) - Talos : SOPS + age (intégré nativement à talhelper)
- Kubernetes : Sealed Secrets (Bitnami) ou External Secrets Operator pointant sur un Vault — pour démarrer, Sealed Secrets est plus simple
9. Feuille de route par phases
Chaque phase est validable indépendamment. Ne passer à la suivante que quand la précédente fonctionne.
Phase 0 — Préparation
- Validation matérielle Talos sur 1 ThinkCentre (compute-01) ✅ effectué
- Vérifier que tous les ThinkCentre ont des SSD SATA opérationnels
- Préparer 1 clé USB pour Talos + 1 clé USB pour AlmaLinux
- Initialiser le repo Git
lab-infra/sur le poste admin
Phase 1 — Infra réseau (storage-01 manuel + bootstrap Ansible)
- Installation AlmaLinux sur storage-01 ✅
- Configuration IP de base — storage-01 joignable (192.168.10.1 LAN cluster) ✅
- IP WAN storage-01 fixée à 192.168.1.200 ✅
- Configuration VLAN sur le GS308EV4 ✅ — tous ports Access, storage-01 sur deux NICs physiques
- Initialiser
lab-infra/ansible/avec inventory + rôlecommon+ rôlegateway - Premier
ansible-playbookqui configure VLAN/nftables/NAT/IP forwarding - Route statique sur la Freebox
- Rôle
dnsmasqpour résolution*.lab.local - Validation : ping bidirectionnel LAN domestique ↔ LAN cluster
Phase 2 — Hôte gpu-01 + LM Studio (Ansible)
- Installation AlmaLinux sur gpu-01 ✅ — ping OK depuis storage-01
- Ajout de gpu-01 à l'inventaire Ansible
- Rôle
rocm: repo AMD + drivers +HSA_OVERRIDE_GFX_VERSION=10.3.0 - Validation ROCm :
rocminfodoit lister la RX 6700XT - Rôle
lm_studio: install + service systemd avec bind0.0.0.0:1234 - Téléchargement d'un modèle test (Hermes 4, Qwen 2.5 7B...)
- Validation :
curl http://192.168.10.20:1234/v1/modelsdepuis storage-01
Phase 3 — Hermes Agent sur storage-01 (Ansible)
- Rôle
hermes_agent: install via script officiel - Configuration provider custom endpoint (LM Studio gpu-01)
- Premier
hermes chatinteractif - (Optionnel) Service systemd pour daemon background
- Données persistantes (
~/.hermes/) sur le RAID5
Phase 4 — Stack données sur storage-01 (Ansible)
- Rôle
nfs_server: export/srv/nfs/k8svers192.168.10.0/24 - Rôle
postgresql: install + DB init - Rôle
qdrant: Podman + service systemd - Rôle
minio: Podman + service systemd - Validation : tous les services accessibles depuis le LAN cluster
Phase 5 — Cluster Talos (talhelper)
- Génération image Talos via factory.talos.dev (extensions
iscsi-tools) - Init
lab-infra/talos/avectalconfig.yaml(3 nœuds) talhelper genconfig- Apply sur compute-01 (control-plane) puis bootstrap etcd
- Apply sur compute-02 et compute-03 (workers)
- Validation :
kubectl get nodesmontre 3 nœuds Ready
Phase 6 — Bootstrap ArgoCD + infra k8s (GitOps)
- Install ArgoCD manuel via Helm (une seule fois, l'install ArgoCD reste manuelle)
- Init
lab-infra/k8s/avec App of Apps pattern - Création des Applications ArgoCD pour : MetalLB, Traefik, cert-manager
- Validation : pod nginx test exposé via Ingress, accessible depuis le LAN
Phase 7 — Stockage k8s (ArgoCD)
- Application ArgoCD :
nfs-subdir-external-provisionerpointant sur storage-01 - Application ArgoCD : Longhorn (avec
iscsi-toolsextension Talos) - Validation : 1 PVC NFS + 1 PVC Longhorn créés et montés
Phase 8 — Apps IA (ArgoCD)
- Applications ArgoCD : ExternalName vers Postgres, Qdrant, LM Studio
- Application ArgoCD : LiteLLM (proxy vers LM Studio)
- Application ArgoCD : Open WebUI (front, pointe sur LiteLLM)
- Application ArgoCD : n8n
- Application ArgoCD : kube-prometheus-stack + Loki
- Validation finale : workflow n8n → Open WebUI → LiteLLM → LM Studio
Phase 9 — Optionnel : Gitea local + miroir
- Rôle Ansible
giteasur storage-01 - Migration du repo
lab-infravers Gitea local - Reconfiguration ArgoCD pour pointer sur
git.lab.local - Miroir push vers GitHub privé (sauvegarde)
10. Points d'attention spécifiques
10.1. RX 6700XT et ROCm sur AlmaLinux 9
- gfx1031 non officiellement supporté par ROCm
- Variable obligatoire :
HSA_OVERRIDE_GFX_VERSION=10.3.0 - ROCm s'exécute directement sur l'OS hôte (gpu-01), pas dans des conteneurs
- Fallback Vulkan possible dans LM Studio si ROCm coince
- Doc ROCm pour RHEL 9 : https://rocm.docs.amd.com/projects/install-on-linux/
10.2. LM Studio en mode serveur
- Par défaut LM Studio bind sur
127.0.0.1→ inaccessible depuis le réseau - Forcer
0.0.0.0via CLI :lms server start --port 1234 --host 0.0.0.0 - LM Studio CLI :
lms ls,lms load <model>,lms unload,lms server status
10.3. Hermes Agent
- Daemon : possible via systemd unit
- Mémoire/skills stockés dans
~/.hermes/→ à mettre sur le RAID5 - Variables
.envdans~/.hermes/.env
10.4. RAM serrée sur ThinkCentre 8 GB
- Réserver système+kubelet :
system-reserved=cpu=500m,memory=1Gi,kube-reserved=cpu=500m,memory=1Gi - Toujours définir
resources.requests/limitssur les pods - Sinon risque OOM-killer sur le nœud entier
10.5. Single control-plane
- Si compute-01 tombe, plus de
kubectl applymais les workloads continuent - Snapshots etcd réguliers :
talosctl etcd snapshotvers storage-01 (cron Ansible)
10.6. RAID5 sur storage-01
- 4×1 TB = 2.7 TB exploitables
- Sauvegarder : configs k8s (Git), bases de données (dump périodique
vers MinIO ou NAS externe), mémoire/skills Hermes (
~/.hermes/) - Pas les modèles LM Studio (re-téléchargeables)
10.7. Sécurité passerelle = bastion admin
- storage-01 cumule passerelle + bastion + Hermes + données → SPOF assumé
- gpu-01 sans rôle réseau critique : si tombe, perte inférence uniquement
10.8. Bootstrap : ce qui reste manuel
GitOps ne peut pas faire le bootstrap absolu. Restent toujours manuels :
- Installation OS sur chaque machine (AlmaLinux ou Talos depuis USB)
- Configuration IP/SSH minimale pour qu'Ansible puisse se connecter
- Premier déploiement ArgoCD via Helm
- Tout le reste est ensuite géré par Ansible / talhelper / ArgoCD
11. Outils à installer sur storage-01 (bastion admin)
# Outils Kubernetes / Talos
- talosctl (admin Talos)
- talhelper (génération configs Talos)
- kubectl (admin Kubernetes)
- helm (charts)
- argocd CLI
- k9s (TUI Kubernetes)
# Outils IaC
- ansible-core
- sops + age (secrets Talos)
# Outils IA
- hermes (Hermes Agent)
- curl/jq (debug API LM Studio)
# Outils système
- nftables, dnsmasq, nfs-utils, postgresql-server, podman
- minio, qdrant (binaires ou conteneurs Podman)
# Optionnel
- gitea ou forgejo (Git local)
- restic ou borgbackup (sauvegardes)
Tous installés via les rôles Ansible — pas de installation manuelle au-delà du bootstrap initial.
12. Conventions et nommage
- Hostnames :
storage-01,compute-01,compute-02,compute-03,gpu-01 - Domaine local :
lab.local - Services exposés via cluster :
<service>.lab.local→ IP MetalLB de Traefik - Endpoint LM Studio :
http://192.168.10.20:1234/v1(oulms.lab.local) - Namespaces k8s :
argocd(ArgoCD lui-même)infra(MetalLB, Traefik, cert-manager, monitoring)storage(Longhorn, NFS provisioner)external(ExternalName vers services storage-01/gpu-01)ai(Open WebUI, LiteLLM)workflows(n8n)
- Git :
- Branches :
main(= prod),feature/*(changements en cours) - Commits : conventional commits (
feat:,fix:,chore:,docs:)
- Branches :
13. État actuel (2026-05-09)
- ✅ Architecture validée
- ✅ Test Talos sur compute-01 effectué (boot OK, IP DHCP, talosctl répond)
- ✅ Stack IaC choisie : Ansible vanilla + talhelper + ArgoCD
- ✅ Hermes Agent configuré sur le poste perso (Setup 1 — 9950X3D + LM Studio local)
- ✅ AlmaLinux installé sur storage-01 — ping OK (
192.168.1.200WAN,192.168.10.1LAN cluster) - ✅ AlmaLinux installé sur gpu-01 — ping OK depuis storage-01 (
192.168.10.20) - ✅ Connectivité LAN cluster (VLAN 10) : storage-01 ↔ gpu-01 fonctionnelle
- ⏳ Phase 1 en cours : Ansible + rôles + dnsmasq + NAT à configurer
- ⏳ Phase 2 en cours : ROCm + LM Studio sur gpu-01 à installer
- ❌ Ansible pas encore exécuté (repo
lab-infra/à initialiser) - ❌ VLAN switch GS308EV4 à confirmer / finaliser
- ❌ Route statique Freebox à configurer
- ❌ Aucun cluster k8s monté
- ❌ LM Studio pas encore installé sur gpu-01
- ❌ Hermes Agent pas encore installé sur storage-01
14. Annexes — Liens utiles
Infrastructure
- Talos Linux : https://www.talos.dev/
- Image Factory Talos : https://factory.talos.dev/
- talhelper : https://github.com/budimanjojo/talhelper
- AlmaLinux 9 : https://almalinux.org/
- ROCm install (RHEL 9) : https://rocm.docs.amd.com/projects/install-on-linux/
Kubernetes / GitOps
- ArgoCD : https://argo-cd.readthedocs.io/
- ArgoCD App of Apps pattern : https://argo-cd.readthedocs.io/en/stable/operator-manual/cluster-bootstrapping/
- Sealed Secrets : https://github.com/bitnami-labs/sealed-secrets
- Longhorn : https://longhorn.io/
- MetalLB : https://metallb.universe.tf/
IaC
- Ansible docs : https://docs.ansible.com/
- Ansible Vault : https://docs.ansible.com/ansible/latest/vault_guide/index.html
- SOPS : https://github.com/getsops/sops
IA
- LM Studio : https://lmstudio.ai/
- LM Studio CLI : https://lmstudio.ai/docs/cli
- Hermes Agent : https://github.com/NousResearch/hermes-agent
- LiteLLM : https://docs.litellm.ai/
- Open WebUI : https://docs.openwebui.com/