Files
Effi/docs/NOTICE_INSTALLATION.md

842 lines
26 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 📋 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 !** 🚀