Solution française • Hébergement souverain • Conformité européenne Blog IA souveraine

Private AI Stack — assembler sa pile IA souveraine open source en 2026

L'IA souveraine ne doit pas se réduire à choisir un modèle. Elle implique d'assembler une pile complète de composants open source qui fonctionnent ensemble, qui sont maintenables, et qui ne créent pas de dépendance à un éditeur. Ce guide présente la stack de référence recommandée par Intelligence Privée, tier par tier, avec les alternatives évaluées et le coût infrastructure réel pour 100 utilisateurs.

Vue d'ensemble de la Private AI Stack

La stack recommandée s'organise en 10 tiers fonctionnels. Chaque tier est découplé et peut être remplacé indépendamment — principe fondamental pour éviter le vendor lock-in, même avec des composants open source.

┌─────────────────────────────────────────────────────────────┐
│  TIER 5 : UI / CHAT          Open WebUI 0.4               │
├─────────────────────────────────────────────────────────────┤
│  TIER 9 : API GATEWAY        Kong OSS 3.6                 │
├───────────────────────┬─────────────────────────────────────┤
│  TIER 3 : ORCHESTRAT. │  TIER 6 : AUTH                    │
│  LangChain 0.2        │  Keycloak 24                      │
│  LlamaIndex 0.10      │                                   │
├───────────────────────┼─────────────────────────────────────┤
│  TIER 2 : SERVING     │  TIER 4 : VECTORDB                │
│  vLLM 0.4.3           │  Qdrant 1.9                       │
├───────────────────────┼─────────────────────────────────────┤
│  TIER 1 : MODÈLES LLM │  TIER 8 : OBJECT STORAGE          │
│  ELODIE 32B           │  MinIO RELEASE.2024-03            │
│  KEVINA 32B           │                                   │
│  Llama 3.3 70B        │                                   │
├───────────────────────┴─────────────────────────────────────┤
│  TIER 7 : MONITORING  Prometheus + Grafana + DCGM          │
├─────────────────────────────────────────────────────────────┤
│  TIER 10 : IaC        Terraform + Helm + Ubuntu 22.04 LTS  │
└─────────────────────────────────────────────────────────────┘
10tiers fonctionnels
100%open source (licences libres)
0€de licence logicielle
~8 500€coût infra/mois pour 100 users

Tier 1 : Modèles LLM

Le choix du modèle est la décision la plus visible — mais elle est réversible, contrairement aux choix d'infrastructure. Les modèles peuvent être changés sans toucher à la stack.

ModèleParamsVRAM requiseLicenceForces
ELODIE 32B32B64 GB (BF16)Propriétaire IPFrançais natif, souverain, optimisé entreprise
KEVINA 32B32B64 GB (BF16)Propriétaire IPCode, analyse technique, raisonnement structuré
Mistral Small 3.124B48 GB (BF16)Apache 2.0Multimodal, très bon rapport perf/taille
Llama 3.3 70B Instruct70B140 GB (BF16)Llama 3.3 LicenseRaisonnement complexe, benchmark SOTA open
Qwen2.5 72B Instruct72B144 GB (BF16)Apache 2.0*Code, multilingual, très compétitif
DeepSeek-R1 32B32B64 GB (BF16)MITRaisonnement, math, chain-of-thought
# Téléchargement modèle depuis Hugging Face Hub
pip install huggingface_hub

# Télécharger Llama 3.3 70B (accès HF requis)
huggingface-cli download meta-llama/Llama-3.3-70B-Instruct \
  --local-dir /models/llama-3.3-70b \
  --local-dir-use-symlinks False \
  --token hf_YOUR_TOKEN

# Vérifier l'intégrité (sha256 des shards)
cd /models/llama-3.3-70b
sha256sum -c checksums.sha256 2>&1 | grep -v OK
# Si output vide : tous les fichiers sont intègres

# Taille du modèle téléchargé
du -sh /models/llama-3.3-70b
# 141G    llama-3.3-70b

Tier 2 : Serving LLM — vLLM 0.4

vLLM est le moteur de référence pour l'inférence LLM en production. Ses fonctionnalités clés : PagedAttention (gestion KV cache), continuous batching, compatibilité API OpenAI, et support multi-GPU natif.

vLLM vs alternatives

SolutionBackendMulti-GPUAPI OpenAIPerf. relativeCas d'usage
vLLM 0.4Python + CUDAOui (TP+PP)Oui (native)100% (référence)Production, haute charge
Ollama 0.3Go + llama.cppPartielOui (compatible)~40-60%Dev local, poste unique
llama.cpp serverC++ + CUDAPartielOui~50-70%CPU/GPU hybride
TGI (HF)Rust + PythonOuiPartiel~85-95%Fine-tuning + serving
LiteLLM ProxyPythonVia backendOui (proxy)Dépend backendMulti-provider routing
# Installation vLLM 0.4.3 en environnement isolé
python3 -m venv /opt/vllm-env
source /opt/vllm-env/bin/activate

pip install vllm==0.4.3 \
  --extra-index-url https://download.pytorch.org/whl/cu124

# Test rapide : modèle 7B pour validation
python -m vllm.entrypoints.openai.api_server \
  --model mistralai/Mistral-7B-Instruct-v0.3 \
  --port 8000 &

# Test de l'API
curl http://localhost:8000/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{"model":"mistralai/Mistral-7B-Instruct-v0.3",
       "messages":[{"role":"user","content":"Bonjour !"}]}'

# Sortie attendue :
# {"choices":[{"message":{"content":"Bonjour ! Comment puis-je vous aider ?"...}}]}

Tier 3 : Orchestration LLM — LangChain vs LlamaIndex

CritèreLangChain 0.2LlamaIndex 0.10
Spécialité principaleAgents, chains, outilsRAG, indexation documents
Intégrations700+ (vaste écosystème)200+ (axé données)
RAG out-of-the-boxBon (via chains)Excellent (core feature)
Agents multi-étapesExcellent (LangGraph)Bon (QueryPipeline)
Performance streamingBonneTrès bonne
Courbe apprentissageÉlevée (abstractions nombreuses)Moyenne
LicenceMITMIT

Recommandation : Utilisez LlamaIndex pour les pipelines RAG purs (ingestion, indexation, retrieval). Utilisez LangChain/LangGraph pour les agents complexes multi-outils. Les deux s'intègrent nativement avec vLLM via l'API OpenAI compatible.

# llama_index_rag.py — Pipeline RAG complet avec LlamaIndex + vLLM + Qdrant
from llama_index.core import VectorStoreIndex, Settings
from llama_index.llms.openai_like import OpenAILike
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.vector_stores.qdrant import QdrantVectorStore
from llama_index.core.node_parser import SentenceSplitter
import qdrant_client

# Configuration LLM : vLLM compatible OpenAI
Settings.llm = OpenAILike(
    model="elodie-32b",
    api_base="http://vllm-service:8000/v1",
    api_key="your-vllm-api-key",
    is_chat_model=True,
    context_window=16384,
    max_tokens=2048,
)

# Modèle d'embedding (local, souverain)
Settings.embed_model = HuggingFaceEmbedding(
    model_name="BAAI/bge-m3",  # Multilingue FR/EN, 1024 dims
    device="cuda",
)

Settings.node_parser = SentenceSplitter(
    chunk_size=512,
    chunk_overlap=64,
)

# Connexion Qdrant
qdrant = qdrant_client.QdrantClient("http://qdrant:6333")
vector_store = QdrantVectorStore(
    client=qdrant,
    collection_name="knowledge-base",
)

# Créer l'index
index = VectorStoreIndex.from_vector_store(vector_store)

# Query engine avec reranking
from llama_index.postprocessor.colbert_rerank import ColbertRerank
query_engine = index.as_query_engine(
    similarity_top_k=10,  # Récupérer 10 candidats
    node_postprocessors=[
        ColbertRerank(top_n=3)  # Reranker → garder les 3 meilleurs
    ],
    streaming=True
)

response = query_engine.query(
    "Quelle est notre politique de confidentialité des données clients ?"
)
for token in response.response_gen:
    print(token, end="", flush=True)

Tier 4 : VectorDB — Qdrant recommandé

Qdrant est notre recommandation principale pour la Private AI Stack 2026. Écrit en Rust, il combine performance native, facilité de déploiement (binaire unique ou Docker), et filtrage de métadonnées avancé — sans la complexité opérationnelle de Milvus (qui requiert etcd + MinIO comme dépendances).

# docker-compose-qdrant.yaml — Qdrant HA avec réplication
version: '3.8'
services:
  qdrant-node1:
    image: qdrant/qdrant:v1.9.2
    command: qdrant --uri http://qdrant-node1:6335
    ports:
      - "6333:6333"  # HTTP API
      - "6334:6334"  # gRPC API
      - "6335:6335"  # Internal cluster port
    volumes:
      - qdrant-storage-1:/qdrant/storage
    environment:
      QDRANT__LOG_LEVEL: INFO
      QDRANT__STORAGE__PERFORMANCE__MAX_SEARCH_THREADS: 8

  qdrant-node2:
    image: qdrant/qdrant:v1.9.2
    command: qdrant --uri http://qdrant-node2:6335
    ports:
      - "6343:6333"
      - "6344:6334"
      - "6345:6335"
    volumes:
      - qdrant-storage-2:/qdrant/storage

volumes:
  qdrant-storage-1:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /nvme/qdrant/node1
  qdrant-storage-2:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /nvme/qdrant/node2
# qdrant_setup.py — Création collection avec configuration optimisée
from qdrant_client import QdrantClient
from qdrant_client.models import (
    VectorParams, Distance, HnswConfigDiff,
    OptimizersConfigDiff, QuantizationConfig, ScalarQuantization
)

client = QdrantClient("http://qdrant:6333")

# Créer une collection avec HNSW + quantization scalaire
client.create_collection(
    collection_name="knowledge-base",
    vectors_config=VectorParams(
        size=1024,           # BGE-M3 embedding size
        distance=Distance.COSINE,
    ),
    hnsw_config=HnswConfigDiff(
        m=16,                # Nombre de connexions par nœud HNSW
        ef_construct=200,    # Qualité de construction de l'index
        full_scan_threshold=10000,
    ),
    optimizers_config=OptimizersConfigDiff(
        deleted_threshold=0.2,
        vacuum_min_vector_number=1000,
        memmap_threshold=50000,  # Basculer en mmap au-delà de 50k vecteurs
    ),
    quantization_config=QuantizationConfig(
        scalar=ScalarQuantization(
            type="int8",
            quantile=0.99,
            always_ram=True   # Garder les quantized vecteurs en RAM
        )
    ),
    replication_factor=2,  # Réplication sur 2 nœuds
    write_consistency_factor=1,
)

print(f"Collection créée avec {client.get_collection('knowledge-base').vectors_count} vecteurs")

Tier 5 : UI et Chat — Open WebUI

Open WebUI (anciennement Ollama WebUI) est l'interface chat la plus complète de l'écosystème open source. Elle supporte nativement l'API OpenAI (donc vLLM), gère les utilisateurs, les conversations, les documents RAG, et s'authentifie via OAuth2/OIDC Keycloak.

# open-webui-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: open-webui
  namespace: llm-apps
spec:
  replicas: 2
  selector:
    matchLabels:
      app: open-webui
  template:
    spec:
      containers:
      - name: open-webui
        image: ghcr.io/open-webui/open-webui:v0.4.5
        ports:
        - containerPort: 8080
        env:
        # Backend LLM : pointer vers vLLM
        - name: OPENAI_API_BASE_URL
          value: "http://kong-gateway/v1"
        - name: OPENAI_API_KEY
          valueFrom:
            secretKeyRef:
              name: llm-secrets
              key: api-key
        # Auth OAuth2 Keycloak
        - name: OAUTH_CLIENT_ID
          value: "open-webui"
        - name: OAUTH_CLIENT_SECRET
          valueFrom:
            secretKeyRef:
              name: keycloak-secrets
              key: client-secret
        - name: OPENID_PROVIDER_URL
          value: "https://keycloak.interne/realms/intelligence-privee/.well-known/openid-configuration"
        - name: OAUTH_SCOPES
          value: "openid email profile"
        # Configuration UX
        - name: DEFAULT_MODELS
          value: "elodie-32b"
        - name: DEFAULT_USER_ROLE
          value: "user"
        - name: ENABLE_SIGNUP
          value: "false"  # Inscription uniquement via Keycloak
        - name: WEBUI_NAME
          value: "Intelligence Privée — Assistant IA"
        - name: WEBUI_URL
          value: "https://ai.entreprise.fr"
        volumeMounts:
        - name: webui-data
          mountPath: /app/backend/data
      volumes:
      - name: webui-data
        persistentVolumeClaim:
          claimName: open-webui-pvc

Tier 6 : Authentification — Keycloak 24

# Installation Keycloak 24 via Helm
helm repo add bitnami https://charts.bitnami.com/bitnami

cat > keycloak-values.yaml << 'EOF'
authentication:
  adminUser: admin
  adminPassword: "${KEYCLOAK_ADMIN_PASSWORD}"

postgresql:
  enabled: true
  auth:
    database: keycloak
    username: keycloak
    password: "${PG_PASSWORD}"

extraEnvVars:
  - name: KC_HOSTNAME
    value: keycloak.interne
  - name: KC_PROXY
    value: edge
  - name: KC_HTTP_RELATIVE_PATH
    value: /

replicaCount: 2

resources:
  requests:
    cpu: 2
    memory: 2Gi
  limits:
    cpu: 4
    memory: 4Gi
EOF

helm install keycloak bitnami/keycloak \
  -f keycloak-values.yaml \
  --namespace auth \
  --create-namespace \
  --version 22.0.0

# Vérification
kubectl get pods -n auth
# keycloak-0   1/1   Running   0   2m
# keycloak-1   1/1   Running   0   1m

Tier 7 : Monitoring — Prometheus + Grafana + DCGM

# Installation stack monitoring complète en une commande
helm install kube-prometheus-stack \
  prometheus-community/kube-prometheus-stack \
  --namespace monitoring \
  --create-namespace \
  --set prometheus.prometheusSpec.retention=30d \
  --set prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.resources.requests.storage=200Gi \
  --set grafana.adminPassword="${GRAFANA_PASSWORD}" \
  --set alertmanager.enabled=true

# DCGM Exporter (métriques GPU)
helm install dcgm-exporter nvdp/dcgm-exporter \
  --namespace monitoring \
  --set serviceMonitor.enabled=true

# Import dashboards Grafana (IDs publics)
curl -X POST http://admin:${GRAFANA_PASSWORD}@grafana:3000/api/dashboards/import \
  -H 'Content-Type: application/json' \
  -d '{"id":12239,"overwrite":true,"folderId":0}'  # NVIDIA DCGM dashboard

curl -X POST http://admin:${GRAFANA_PASSWORD}@grafana:3000/api/dashboards/import \
  -H 'Content-Type: application/json' \
  -d '{"id":315,"overwrite":true,"folderId":0}'    # Kubernetes cluster dashboard

Tier 8 : Stockage objets — MinIO

# Installation MinIO Operator + Tenant via Helm
helm install minio-operator \
  minio/operator \
  --namespace minio-operator \
  --create-namespace

# Créer un tenant MinIO (4 nœuds, erasure coding)
cat > minio-tenant.yaml << 'EOF'
apiVersion: minio.min.io/v2
kind: Tenant
metadata:
  name: llm-storage
  namespace: minio
spec:
  image: minio/minio:RELEASE.2024-03-15T01-07-19Z
  pools:
  - servers: 4
    volumesPerServer: 2
    volumeClaimTemplate:
      spec:
        storageClassName: fast-nvme
        resources:
          requests:
            storage: 2Ti  # 2 TB par volume = 16 TB total, 8 TB utiles (EC:4+2)
  mountPath: /data
  requestAutoCert: true
  features:
    bucketDNS: true
  buckets:
  - name: llm-models
  - name: llm-documents
  - name: llm-backups
EOF
kubectl apply -f minio-tenant.yaml

Tier 9 : API Gateway — Kong OSS

# Installation Kong OSS en mode DB-less (recommandé pour K8s)
helm repo add kong https://charts.konghq.com

cat > kong-values.yaml << 'EOF'
env:
  database: "off"  # DB-less mode
  router_flavor: expressions
  log_level: notice

ingressController:
  enabled: true
  ingressClass: kong

proxy:
  type: LoadBalancer
  tls:
    enabled: true
    servicePort: 443

resources:
  requests:
    cpu: 2
    memory: 2Gi
  limits:
    cpu: 4
    memory: 4Gi

replicaCount: 2

serviceMonitor:
  enabled: true  # Metrics Prometheus
EOF

helm install kong kong/kong \
  -f kong-values.yaml \
  --namespace kong \
  --create-namespace \
  --version 2.38.0

Tier 10 : Infrastructure as Code — Terraform + Helm

# Structure du repo IaC recommandée
tree /infra/
# infra/
# ├── terraform/
# │   ├── environments/
# │   │   ├── production/
# │   │   │   ├── main.tf
# │   │   │   ├── variables.tf
# │   │   │   └── terraform.tfvars
# │   │   └── staging/
# │   └── modules/
# │       ├── k8s-cluster/
# │       ├── gpu-nodes/
# │       └── networking/
# └── helm/
#     ├── environments/
#     │   ├── production.yaml
#     │   └── staging.yaml
#     └── helmfile.yaml  ← orchestration des charts
# helmfile.yaml — Déploiement orchestré de toute la stack
repositories:
- name: prometheus-community
  url: https://prometheus-community.github.io/helm-charts
- name: nvdp
  url: https://nvidia.github.io/k8s-device-plugin
- name: kong
  url: https://charts.konghq.com
- name: bitnami
  url: https://charts.bitnami.com/bitnami
- name: minio
  url: https://charts.min.io

releases:
# Ordre 1 : Infrastructure de base
- name: nvidia-device-plugin
  namespace: kube-system
  chart: nvdp/nvidia-device-plugin
  version: 0.15.0

# Ordre 2 : Stockage et bases de données
- name: minio-operator
  namespace: minio-operator
  chart: minio/operator
  needs: [kube-system/nvidia-device-plugin]

# Ordre 3 : Authentification
- name: keycloak
  namespace: auth
  chart: bitnami/keycloak
  version: 22.0.0
  valuesFiles: [helm/environments/{{`{{.Environment.Name}}`}}.yaml]
  needs: [minio-operator/minio-operator]

# Ordre 4 : Monitoring
- name: kube-prometheus-stack
  namespace: monitoring
  chart: prometheus-community/kube-prometheus-stack
  version: 57.2.0
  needs: [kube-system/nvidia-device-plugin]

# Ordre 5 : API Gateway
- name: kong
  namespace: kong
  chart: kong/kong
  version: 2.38.0
  needs: [auth/keycloak]

# Ordre 6 : Applications LLM (déploiement custom)
- name: vllm
  namespace: llm-production
  chart: ./charts/vllm
  needs: [kong/kong, monitoring/kube-prometheus-stack]

# Ordre 7 : UI
- name: open-webui
  namespace: llm-apps
  chart: ./charts/open-webui
  needs: [llm-production/vllm, auth/keycloak]

Ordre d'installation et dépendances

# Script d'installation complète (ordre critique)
#!/bin/bash
set -euo pipefail

echo "[1/7] Préparation nœuds GPU (drivers NVIDIA + containerd)"
ansible-playbook -i inventory/production gpu-nodes-setup.yaml

echo "[2/7] Provisioning cluster Kubernetes (k3s ou kubeadm)"
helmfile apply --file infra/helm/helmfile.yaml \
  --selector name=nvidia-device-plugin
kubectl wait --for=condition=Ready node --all --timeout=300s

echo "[3/7] Déploiement stockage MinIO"
helmfile apply --selector name=minio-operator
kubectl apply -f infra/k8s/minio-tenant.yaml
kubectl wait --for=condition=Ready tenant/llm-storage \
  -n minio --timeout=600s

echo "[4/7] Déploiement authentification Keycloak"
helmfile apply --selector name=keycloak
kubectl rollout status deployment/keycloak -n auth --timeout=300s
# Importer la configuration realm
python3 scripts/keycloak_import_realm.py

echo "[5/7] Déploiement monitoring"
helmfile apply --selector name=kube-prometheus-stack
helmfile apply --selector name=dcgm-exporter

echo "[6/7] Déploiement Kong API Gateway"
helmfile apply --selector name=kong
kubectl apply -f infra/k8s/kong-config.yaml

echo "[7/7] Déploiement vLLM + Qdrant + Open WebUI"
# Préparer les modèles
python3 scripts/download_models.py --model elodie-32b
# Déployer
helmfile apply --selector name=qdrant
helmfile apply --selector name=vllm
helmfile apply --selector name=open-webui

echo "Stack déployée avec succès !"
echo "Open WebUI : https://ai.entreprise.fr"
echo "Grafana : https://monitoring.entreprise.fr"
echo "Keycloak : https://auth.entreprise.fr"

Coût infrastructure pour 100 utilisateurs

ComposantRessourcesCoût/mois (cloud FR)Coût/mois (on-prem amorti)
GPU serving (2× A100 80GB)2 GPU H100 ou 4 A1005 000–7 000 €2 500–3 500 €
CPU nodes (Keycloak, Kong, monitoring)3× 16 vCPU, 64 GB RAM600–900 €300–500 €
Stockage NVMe (MinIO, Qdrant, modèles)20 TB NVMe SSD400–600 €200–350 €
Réseau (egress, load balancer)100–200 €50–100 €
Backup et monitoring storage5 TB100–150 €50–80 €
Total mensuel6 200–8 850 €3 100–4 530 €
Coût par utilisateur/mois62–88 €31–45 €

Coût logiciel vs coût infrastructure

Ces chiffres couvrent l'infrastructure uniquement. Le coût réel inclut également : les jours-ingénieurs d'installation et de maintenance (comptez 0.5 ETP pour une infrastructure 100 users), la formation des équipes, et le support. Un fournisseur comme Intelligence Privée peut absorber ces coûts opérationnels dans une offre managée, ramenant le coût réel total à 40-70 € par utilisateur/mois tout compris.

Ce qu'il faut retenir

  • La stack complète repose sur 10 composants open source éprouvés — aucune licence propriétaire, aucun vendor lock-in technologique.
  • Qdrant est recommandé sur Milvus pour sa simplicité opérationnelle (binaire Rust, pas de dépendances externes) sans compromis sur les performances.
  • Open WebUI est l'interface de référence : compatible vLLM/API OpenAI, auth Keycloak OIDC, RAG intégré — prête en production en quelques heures.
  • L'ordre d'installation est critique : stockage → auth → monitoring → gateway → LLM → UI. Les dépendances sont fortes entre couches.
  • Pour 100 utilisateurs : budget infra 6 000–9 000 €/mois en cloud souverain français, 3 000–4 500 € en on-premise amorti sur 5 ans.

Votre Private AI Stack déployée en 30 jours

Intelligence Privée déploie et opère votre pile IA souveraine complète — du bare metal à l'interface utilisateur — avec les modèles ELODIE et KEVINA intégrés, le support en français et un SLA de 99.9%.

Démarrer ma stack IA souveraine →

FAQ

Peut-on remplacer Keycloak par un autre fournisseur OIDC ?

Oui. Tout composant supportant OpenID Connect (OIDC) fonctionne : Microsoft Entra ID (Azure AD), Okta, Auth0, ou même un Authentik auto-hébergé. La condition est que votre IdP expose un endpoint JWKS pour la validation des tokens JWT. Configurez Kong avec le plugin jwt pointant vers votre JWKS endpoint et Open WebUI avec les variables OAUTH_* correspondantes. Keycloak est recommandé car il est 100% open source, auto-hébergeable, et supporte la fédération LDAP/AD native.

Qdrant peut-il remplacer une base de données traditionnelle pour les métadonnées ?

Non. Qdrant est optimisé pour la recherche vectorielle — pas pour les requêtes relationnelles complexes, les transactions ACID ou les jointures. Dans la Private AI Stack, Qdrant stocke les embeddings et les métadonnées simples associées (source, date, département). Pour les données relationnelles (utilisateurs, sessions, coûts, logs), utilisez PostgreSQL qui est déjà présent comme backend Keycloak. Les deux cohabitent naturellement.

Comment mettre à jour les composants de la stack sans tout réinstaller ?

Helmfile simplifie les mises à jour : modifiez la version du chart dans helmfile.yaml et exécutez helmfile apply --selector name=vllm pour mettre à jour uniquement vLLM. Chaque composant peut être mis à jour indépendamment. Respectez les dépendances : une mise à jour de Keycloak peut nécessiter une reconfiguration des clients OIDC dans Kong et Open WebUI. Maintenez un environnement de staging identique à la production pour tester les mises à jour avant déploiement.