Ajout: Notice d'installation complète pour référence future

This commit is contained in:
Folzo
2026-04-04 11:17:34 +02:00
parent ba0dea40e1
commit ef98a16b70
+841
View File
@@ -0,0 +1,841 @@
# 📋 Notice d'Installation - Effi (Infrastructure IA Self-Hosted)
> **Date de création** : Avril 2026
> **Auteur** : Folzo
> **Version** : 1.0
---
## 🎯 Architecture
```
┌─────────────────────────────────────────────────────────────────┐
│ EFFI-SERVER (192.168.1.27) │
│ Ubuntu Server 22.04+ / Intel J5040 / 8GB RAM │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Open WebUI │ │ Qdrant │ │ CouchDB │ │
│ │ Port 3000 │ │ Port 6333 │ │ Port 5984 │ │
│ └──────┬───────┘ └──────────────┘ └──────────────┘ │
│ │ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ wol-proxy │ │ mcpo │ │ n8n │ │
│ │ Port 3011 │ │ Port 8000 │ │ Port 5678 │ │
│ └──────┬───────┘ └──────────────┘ └──────────────┘ │
└─────────┼──────────────────────────────────────────────────────┘
│ Wake-on-LAN + Proxy
▼
┌─────────────────────────────────────────────────────────────────┐
│ FOLZO-CORP (192.168.1.11) │
│ Fedora / Ryzen 5800X3D / RX 7800 XT 16GB │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Ollama (LLM) │ │
│ │ Port 11434 │ │
│ │ Modèles : qwen2.5:14b, bge-m3, etc. │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
---
## 📦 Phase 1 : Préparation du Serveur (effi-server)
### 1.1 Installation de Ubuntu Server
**Prérequis matériels :**
- CPU : Intel J5040 ou équivalent (4 cœurs min)
- RAM : 8 GB minimum
- Stockage : 100 GB SSD
- Réseau : Ethernet filaire
**Installation :**
1. Télécharger Ubuntu Server 22.04 LTS
2. Créer une clé USB bootable
3. Installer avec les options par défaut
4. Créer un utilisateur `effi` avec droits sudo
5. Configurer une IP statique : `192.168.1.27`
### 1.2 Installation de Docker
```bash
# Mettre à jour le système
sudo apt update && sudo apt upgrade -y
# Installer les dépendances
sudo apt install -y ca-certificates curl gnupg lsb-release
# Ajouter la clé GPG Docker
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# Ajouter le repository
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Installer Docker
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# Ajouter l'utilisateur au groupe docker
sudo usermod -aG docker $USER
# Vérifier l'installation
docker --version
docker compose version
# Déconnexion/reconnexion nécessaire
exit
# Reconnectez-vous en SSH
```
### 1.3 Création de la structure
```bash
# Créer le dossier principal
mkdir -p ~/effi
cd ~/effi
# Créer les sous-dossiers
mkdir -p mcpo-config
mkdir -p qdrant-storage
mkdir -p couchdb-data
mkdir -p n8n-data
mkdir -p wol-proxy
mkdir -p tts-voices
mkdir -p tts-config
mkdir -p obsidian-vault
mkdir -p mem0-data
```
### 1.4 Fichier docker-compose.yml
Créer `~/effi/docker-compose.yml` :
```yaml
# ═══════════════════════════════════════════════════════════
# EFFI SERVER - Stack IA Locale
# Machine : effi-server (192.168.1.27)
# ═══════════════════════════════════════════════════════════
services:
# ─────────────────────────────────────────────────────────
# 1. OPEN WEBUI - Interface Chat Effi
# → http://192.168.1.27:3000
# ─────────────────────────────────────────────────────────
open-webui:
image: ghcr.io/open-webui/open-webui:main
container_name: open-webui
restart: unless-stopped
extra_hosts:
- "host.docker.internal:host-gateway"
ports:
- "3000:8080"
environment:
- OLLAMA_BASE_URL=http://host.docker.internal:3011
- WEBUI_SECRET_KEY=${WEBUI_SECRET_KEY}
- VECTOR_DB=qdrant
- QDRANT_URI=http://qdrant:6333
- DEFAULT_LOCALE=fr-FR
- ENABLE_MEMORIES=true
- AUDIO_STT_ENGINE=openai
- AUDIO_STT_OPENAI_API_BASE_URL=http://192.168.1.11:8200/v1
- AUDIO_STT_OPENAI_API_KEY=anything
- AUDIO_STT_MODEL=Systran/faster-whisper-large-v3
volumes:
- open-webui-data:/app/backend/data
depends_on:
- qdrant
- wol-proxy
networks:
- effi-net
# ─────────────────────────────────────────────────────────
# 2. WOL PROXY - Réveil PC Gaming avant appel Ollama
# → Proxy :3011 → PC Gaming :11434
# ─────────────────────────────────────────────────────────
wol-proxy:
build: ./wol-proxy
container_name: wol-proxy
restart: unless-stopped
network_mode: host
environment:
- TARGET_HOST=${OLLAMA_HOST}
- TARGET_PORT=11434
- TARGET_MAC=${PC_GAMING_MAC}
- LISTEN_PORT=3011
- WAKE_TIMEOUT=60
- CHECK_INTERVAL=5
- BROADCAST_IP=${BROADCAST_IP}
# ─────────────────────────────────────────────────────────
# 3. MCPO - Proxy outils MCP (Obsidian, etc.)
# → http://192.168.1.27:8000
# ─────────────────────────────────────────────────────────
mcpo:
image: ghcr.io/open-webui/mcpo:main
container_name: mcpo
restart: unless-stopped
ports:
- "8000:8000"
volumes:
- ./mcpo-config:/app/config:ro
- ./mcpo-patch.sh:/mcpo-patch.sh:ro
entrypoint: ["sh", "/mcpo-patch.sh"]
# ─────────────────────────────────────────────────────────
# 4. QDRANT - Vector Store (RAG sémantique)
# → http://192.168.1.27:6333
# ─────────────────────────────────────────────────────────
qdrant:
image: qdrant/qdrant:latest
container_name: qdrant
restart: unless-stopped
ports:
- "6333:6333"
- "6334:6334"
volumes:
- ./qdrant-storage:/qdrant/storage:z
networks:
- effi-net
# ─────────────────────────────────────────────────────────
# 5. COUCHDB - Backend Obsidian LiveSync
# → http://192.168.1.27:5984
# ─────────────────────────────────────────────────────────
couchdb:
image: couchdb:3.3
container_name: couchdb
restart: unless-stopped
ports:
- "5984:5984"
environment:
- COUCHDB_USER=${COUCHDB_USER}
- COUCHDB_PASSWORD=${COUCHDB_PASSWORD}
volumes:
- ./couchdb-data:/opt/couchdb/data
networks:
- effi-net
# ─────────────────────────────────────────────────────────
# 6. N8N - Automatisation autonome Effi
# → http://192.168.1.27:5678
# ─────────────────────────────────────────────────────────
n8n:
image: docker.n8n.io/n8nio/n8n:latest
container_name: n8n
restart: unless-stopped
ports:
- "5678:5678"
environment:
- N8N_HOST=0.0.0.0
- N8N_PORT=5678
- N8N_PROTOCOL=http
- WEBHOOK_URL=http://192.168.1.27:5678
- N8N_BASIC_AUTH_ACTIVE=true
- N8N_BASIC_AUTH_USER=${N8N_USER}
- N8N_BASIC_AUTH_PASSWORD=${N8N_PASSWORD}
- GENERIC_TIMEZONE=Europe/Paris
- TZ=Europe/Paris
volumes:
- ./n8n-data:/home/node/.n8n
networks:
- effi-net
# ─────────────────────────────────────────────────────────
# 7. PIPELINES - Middleware Open WebUI (mem0 memory)
# → http://192.168.1.27:9099
# ─────────────────────────────────────────────────────────
pipelines:
image: ghcr.io/open-webui/pipelines:main
container_name: pipelines
restart: unless-stopped
ports:
- "9099:9099"
volumes:
- pipelines-data:/app/pipelines
networks:
- effi-net
# ─────────────────────────────────────────────────────────
# 8. WHISPER - Speech To Text (STT)
# → http://192.168.1.27:8200
# ─────────────────────────────────────────────────────────
whisper:
image: fedirz/faster-whisper-server:latest-cpu
container_name: whisper
restart: unless-stopped
ports:
- "8200:8000"
volumes:
- whisper-cache:/root/.cache/huggingface
environment:
- WHISPER__MODEL=guillaumekln/faster-whisper-tiny
- WHISPER__LANGUAGE=fr
- HF_HUB_OFFLINE=0
# ─────────────────────────────────────────────────────────
# 9. OPENEDAI-SPEECH - Text To Speech (TTS)
# → http://192.168.1.27:8100
# ─────────────────────────────────────────────────────────
openedai-speech:
image: ghcr.io/matatonic/openedai-speech
container_name: openedai-speech
restart: unless-stopped
ports:
- "8100:8000"
volumes:
- ./tts-voices:/app/voices
- ./tts-config:/app/config
# ─────────────────────────────────────────────────────────
# 10. WATCHTOWER - Mise à jour automatique des containers
# → Vérifie les mises à jour chaque nuit à 4h00
# ─────────────────────────────────────────────────────────
watchtower:
image: nickfedor/watchtower:latest
container_name: watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_CLEANUP=true
- WATCHTOWER_SCHEDULE=0 0 4 * * *
- WATCHTOWER_NOTIFICATIONS_LEVEL=warn
- WATCHTOWER_INCLUDE_STOPPED=true
- WATCHTOWER_REVIVE_STOPPED=false
- TZ=Europe/Paris
restart: unless-stopped
networks:
- effi-net
# ─────────────────────────────────────────────────────────
# 11. OBSIDIAN - Version Serveur 24/7 (Web UI & MCP)
# → Interface Web : https://192.168.1.27:3100
# ─────────────────────────────────────────────────────────
obsidian:
image: lscr.io/linuxserver/obsidian:latest
container_name: obsidian
restart: unless-stopped
security_opt:
- seccomp:unconfined
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Paris
ports:
- "3100:3001"
volumes:
- ./obsidian-vault:/config
shm_size: "1gb"
networks:
- effi-net
networks:
effi-net:
driver: bridge
volumes:
open-webui-data:
pipelines-data:
whisper-cache:
```
### 1.5 Configuration des variables d'environnement
Créer `~/effi/.env` :
```bash
# ═══════════════════════════════════════════════════════════
# EFFI SERVER - Variables d'environnement
# ═══════════════════════════════════════════════════════════
# OpenWebUI
WEBUI_SECRET_KEY=changez_moi_par_une_cle_longue_et_aleatoire
# Ollama / PC Gaming
OLLAMA_HOST=192.168.1.11
PC_GAMING_MAC=XX:XX:XX:XX:XX:XX
BROADCAST_IP=192.168.1.255
# CouchDB (Obsidian LiveSync)
COUCHDB_USER=master
COUCHDB_PASSWORD=mot_de_passe_securise
# n8n (Automatisation)
N8N_USER=master
N8N_PASSWORD=mot_de_passe_securise
```
**Générer une clé secrète :**
```bash
openssl rand -hex 32
```
### 1.6 Création du wol-proxy
Créer `~/effi/wol-proxy/app.py` :
```python
#!/usr/bin/env python3
import socket
import struct
import subprocess
import time
import os
from flask import Flask, request, Response
import requests
app = Flask(__name__)
TARGET_HOST = os.getenv('TARGET_HOST', '192.168.1.11')
TARGET_PORT = int(os.getenv('TARGET_PORT', '11434'))
TARGET_MAC = os.getenv('TARGET_MAC', '00:00:00:00:00:00')
LISTEN_PORT = int(os.getenv('LISTEN_PORT', '3011'))
WAKE_TIMEOUT = int(os.getenv('WAKE_TIMEOUT', '60'))
CHECK_INTERVAL = int(os.getenv('CHECK_INTERVAL', '5'))
BROADCAST_IP = os.getenv('BROADCAST_IP', '192.168.1.255')
def send_wol_packet(mac_address):
"""Envoie un magic packet Wake-on-LAN"""
mac_bytes = bytes.fromhex(mac_address.replace(':', '').replace('-', ''))
magic_packet = b'\xff' * 6 + mac_bytes * 16
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.sendto(magic_packet, (BROADCAST_IP, 9))
sock.close()
print(f"Magic packet envoyé à {mac_address}")
def is_target_awake():
"""Vérifie si Ollama répond"""
try:
response = requests.get(f"http://{TARGET_HOST}:{TARGET_PORT}/api/tags", timeout=5)
return response.status_code == 200
except:
return False
def wake_target():
"""Réveille le PC Gaming si nécessaire"""
if is_target_awake():
return True
print(f"{TARGET_HOST} ne répond pas, envoi WOL...")
send_wol_packet(TARGET_MAC)
# Attendre que le PC démarre
for i in range(0, WAKE_TIMEOUT, CHECK_INTERVAL):
time.sleep(CHECK_INTERVAL)
if is_target_awake():
print(f"{TARGET_HOST} est réveillé!")
return True
print(f"Attente... {i+CHECK_INTERVAL}s/{WAKE_TIMEOUT}s")
return False
@app.route('/', defaults={'path': ''}, methods=['GET', 'POST', 'PUT', 'DELETE'])
@app.route('/<path:path>', methods=['GET', 'POST', 'PUT', 'DELETE'])
def proxy(path):
"""Proxy vers Ollama avec WOL"""
if not wake_target():
return Response("Target unavailable after WOL timeout", status=503)
# Proxy la requête
url = f"http://{TARGET_HOST}:{TARGET_PORT}/{path}"
try:
resp = requests.request(
method=request.method,
url=url,
headers={key: value for key, value in request.headers if key != 'Host'},
data=request.get_data(),
cookies=request.cookies,
allow_redirects=False,
timeout=300
)
excluded_headers = ['content-encoding', 'content-length', 'transfer-encoding', 'connection']
headers = [(name, value) for name, value in resp.raw.headers.items()
if name.lower() not in excluded_headers]
return Response(resp.content, resp.status_code, headers)
except Exception as e:
return Response(f"Proxy error: {str(e)}", status=502)
if __name__ == '__main__':
print(f"WOL Proxy démarré sur le port {LISTEN_PORT}")
print(f"Cible: {TARGET_HOST}:{TARGET_PORT} (MAC: {TARGET_MAC})")
app.run(host='0.0.0.0', port=LISTEN_PORT, threaded=True)
```
Créer `~/effi/wol-proxy/Dockerfile` :
```dockerfile
FROM python:3.11-slim
WORKDIR /app
RUN pip install flask requests
COPY app.py .
EXPOSE 3011
CMD ["python", "app.py"]
```
### 1.7 Configuration mcpo
Créer `~/effi/mcpo-config/config.json` :
```json
{
"mcpServers": {}
}
```
Créer `~/effi/mcpo-patch.sh` :
```bash
#!/bin/sh
# Patch pour mcpo - installe les dépendances si nécessaire
pip install mcpo 2>/dev/null || true
exec mcpo "$@"
```
```bash
chmod +x ~/effi/mcpo-patch.sh
```
### 1.8 Initialisation de CouchDB
```bash
# Démarrer uniquement CouchDB
cd ~/effi
docker compose up -d couchdb
# Attendre 10 secondes
sleep 10
# Créer les bases nécessaires
curl -X PUT http://master:MOT_DE_PASSE@192.168.1.27:5984/_users
curl -X PUT http://master:MOT_DE_PASSE@192.168.1.27:5984/_replicator
curl -X PUT http://master:MOT_DE_PASSE@192.168.1.27:5984/obsidian-livesync
```
### 1.9 Démarrage complet
```bash
cd ~/effi
docker compose up -d
# Vérifier l'état
docker compose ps
```
---
## 💻 Phase 2 : Configuration du PC Gaming (folzo-Corp)
### 2.1 Installation de Fedora
1. Télécharger Fedora Workstation ou Server
2. Créer une clé USB bootable
3. Installer avec les options par défaut
4. Configurer IP statique : `192.168.1.11`
### 2.2 Installation d'Ollama
```bash
# Installer Ollama
curl -fsSL https://ollama.com/install.sh | sh
# Vérifier l'installation
ollama --version
```
### 2.3 Configuration du service Ollama
Créer le fichier de service systemd :
```bash
sudo tee /etc/systemd/system/ollama.service > /dev/null << 'EOF'
[Unit]
Description=Ollama Service
After=network-online.target
[Service]
Type=simple
User=ollama
Group=ollama
ExecStart=/usr/local/bin/ollama serve
Restart=always
RestartSec=3
Environment="HOME=/usr/share/ollama"
Environment="OLLAMA_HOST=0.0.0.0:11434"
[Install]
WantedBy=multi-user.target
EOF
```
Configurer les permissions :
```bash
# Créer l'utilisateur ollama
sudo useradd -r -s /bin/false ollama 2>/dev/null || echo "Utilisateur existe déjà"
# Créer le répertoire home
sudo mkdir -p /usr/share/ollama
sudo chown -R ollama:ollama /usr/share/ollama
# Recharger systemd
sudo systemctl daemon-reload
sudo systemctl enable ollama
sudo systemctl start ollama
# Vérifier
sudo systemctl status ollama
```
### 2.4 Téléchargement des modèles
```bash
# Modèle principal pour Effi
ollama pull qwen2.5:14b
# Modèle pour les embeddings (RAG)
ollama pull bge-m3
# Modèle léger pour les filtres
ollama pull qwen2.5:3b
# Vérifier
ollama list
```
### 2.5 Configuration Wake-on-LAN
```bash
# Vérifier que la carte supporte WOL
sudo ethtool enp6s0 | grep -i wake
# Si WOL n'est pas activé, créer le script
sudo tee /etc/NetworkManager/dispatcher.d/99-wol > /dev/null << 'EOF'
#!/bin/bash
if [ "$1" = "enp6s0" ] && [ "$2" = "up" ]; then
/sbin/ethtool -s $1 wol g
fi
EOF
sudo chmod +x /etc/NetworkManager/dispatcher.d/99-wol
# Activer maintenant
sudo ethtool -s enp6s0 wol g
```
### 2.6 Test de connectivité
```bash
# Vérifier qu'Ollama écoute sur toutes les interfaces
sudo ss -tlnp | grep 11434
# Doit afficher : 0.0.0.0:11434 (pas 127.0.0.1:11434)
```
---
## ⚙️ Phase 3 : Configuration OpenWebUI
### 3.1 Premier accès
1. Ouvrir `http://192.168.1.27:3000`
2. Créer un compte (le premier devient admin)
3. Se connecter
### 3.2 Configuration des connexions
**Admin Panel → Settings → Connections**
- **Ollama URL** : `http://192.168.1.27:3011`
### 3.3 Configuration Audio
**Admin Panel → Settings → Audio**
**STT :**
- Engine : `OpenAI`
- URL : `http://192.168.1.11:8200/v1`
- Model : `Systran/faster-whisper-large-v3`
**TTS :**
- Engine : `OpenAI`
- URL : `http://192.168.1.11:8100/v1`
- Model : `tts-1`
### 3.4 Création du modèle Effi
**Admin Panel → Models → + New Model**
- **Name** : `Effi`
- **Base Model** : `qwen2.5:14b`
- **System Prompt** : Voir ci-dessous
**System Prompt :**
```
Tu es Effi, l'assistante IA locale de Folzo (Open WebUI + Ollama).
## Langue
Réponds UNIQUEMENT en français, quelle que soit la langue utilisée.
## Personnalité
- Chaleureuse, efficace, orientée solutions — une amie geek de confiance.
- Humour fin : 0 à 1 vanne max par réponse, jamais forcée.
- Ton conversationnel IRL, phrases courtes, pas de pavés.
## Priorités
1. Répondre à la demande directement et clairement.
2. Ajouter un conseil ou alternative si pertinent.
3. Si ambigu → 1 à 3 questions courtes avant de proposer une solution.
## Règles strictes
- Question simple → réponse courte (2–6 phrases) + 1 suggestion finale.
- Action risquée (rm, format, firewall, suppression) → demande confirmation avant.
- Ne sur-parle pas, pas de répétitions inutiles.
## Mémoire
N'invente pas de souvenirs. Les infos sur Folzo sont injectées automatiquement ci-dessous.
<memory_user_context></memory_user_context>
```
---
## 🔧 Phase 4 : Configuration Mémoire Persistante
### 4.1 Installation d'Auto Memory
1. **Admin Panel → Functions → Discover**
2. Rechercher "Auto Memory" par nokodo
3. Installer
**Configuration des Valves :**
- OpenAI API URL : `http://192.168.1.27:3011/v1`
- Model : `qwen2.5:3b`
- API Key : `toto`
- Messages To Consider : `10`
- Related Memories N : `5`
- Minimum Memory Similarity : `0.7`
**Activation :** Toggle Global → ON
### 4.2 Installation de Memory Injection
1. **Admin Panel → Functions → Discover**
2. Rechercher "Memory Injection Filter" par Raphael
3. Installer
**Configuration :**
- PREPENDING_TEXT : `Voici les souvenirs à long terme de l'utilisateur :`
- SHOW_MEMORY_COUNT_EMITTER : `ON`
**Activation :** Toggle Global → ON
### 4.3 Patch du code Auto Memory
**Admin Panel → Functions → Auto Memory → Edit**
Remplacer le bloc `if response_model:` par :
```python
if response_model:
try:
cleaned = re.sub(r'```(?:json)?\s*', '', text_response)
cleaned = re.sub(r'```\s*', '', cleaned).strip()
match = re.search(r'\{.*\}', cleaned, re.DOTALL)
if match:
cleaned = match.group(0)
return response_model.model_validate_json(cleaned)
except ValidationError as e:
self.log(f"response model validation error: {e}", level="warning")
raise
return text_response
```
---
## ✅ Phase 5 : Vérifications Finales
### 5.1 Test de conversation
1. Créer un nouveau chat avec Effi
2. Dire : "Je m'appelle Folzo et j'habite à Paris"
3. Créer un autre chat
4. Demander : "Comment je m'appelle ?"
5. **Résultat attendu** : Effi répond "Folzo"
### 5.2 Test WOL
1. Éteindre folzo-Corp
2. Envoyer un message dans OpenWebUI
3. Le wol-proxy doit réveiller le PC automatiquement
4. Attendre 30-60 secondes
5. Effi répond
### 5.3 Test audio (si configuré)
1. Activer le micro dans OpenWebUI
2. Parler : "Bonjour Effi"
3. Vérifier la transcription
---
## 🛠️ Dépannage
### Ollama inaccessible
```bash
# Sur folzo-Corp
sudo systemctl status ollama
sudo systemctl restart ollama
sudo ss -tlnp | grep 11434
```
### Wake-on-LAN ne marche pas
```bash
# Sur folzo-Corp
sudo ethtool enp6s0 | grep -i wake
# Doit afficher : Wake-on: g
```
### Services Docker en erreur
```bash
# Sur effi-server
cd ~/effi
docker compose ps
docker compose logs [service]
docker compose restart [service]
```
### Reset complet
```bash
# Sur effi-server
cd ~/effi
docker compose down
docker compose up -d
```
---
## 📚 Ressources
- **Dépôt Gitea** : https://gitea.folzocorp.fr/Folzo/effi
- **Documentation** : Voir dossier `docs/` dans le dépôt
- **Scripts utilitaires** : Voir dossier `scripts/` dans le dépôt
---
**Félicitations ! Effi est opérationnelle !** 🚀