4NK_IA_back/docs/CONFIGURATION.md
ncantu e4b7dc8b58 docs: Nettoyage et finalisation de la documentation
- Suppression des fichiers de documentation temporaires
- Mise à jour des URLs pour rester en localhost uniquement
- Finalisation de la documentation complète
- Nettoyage du dépôt
2025-09-09 06:35:10 +02:00

17 KiB

Configuration du Système - 4NK_IA Notarial

⚙️ Vue d'ensemble de la Configuration

Ce document détaille toutes les configurations nécessaires pour déployer et faire fonctionner le système notarial 4NK_IA.

🔧 Fichiers de Configuration

Structure des Fichiers

4NK_IA/
├── infra/
│   ├── .env                    # Variables d'environnement
│   ├── .env.example           # Template de configuration
│   ├── docker-compose.yml     # Services de production
│   └── docker-compose.dev.yml # Services de développement
├── services/
│   ├── host_api/
│   │   ├── requirements.txt   # Dépendances Python
│   │   └── app.py            # Configuration FastAPI
│   └── worker/
│       └── requirements.txt   # Dépendances Worker
├── ops/
│   ├── nginx.conf            # Configuration Nginx
│   └── grafana/              # Dashboards Grafana
└── Makefile                  # Commandes de gestion

🌍 Variables d'Environnement

Fichier .env Principal

# Configuration du projet
PROJECT_NAME=notariat
DOMAIN=localhost
TZ=Europe/Paris

# Base de données PostgreSQL
POSTGRES_USER=notariat
POSTGRES_PASSWORD=notariat_pwd
POSTGRES_DB=notariat
DATABASE_URL=postgresql+psycopg://notariat:notariat_pwd@postgres:5432/notariat

# Redis (Cache et Queue)
REDIS_URL=redis://redis:6379/0
REDIS_PASSWORD=

# MinIO (Stockage objet)
MINIO_ROOT_USER=minio
MINIO_ROOT_PASSWORD=minio_pwd
MINIO_BUCKET=ingest
MINIO_ENDPOINT=minio:9000

# Ollama (LLM local)
OLLAMA_BASE_URL=http://ollama:11434
OLLAMA_MODEL=llama3:8b

# AnythingLLM (RAG)
ANYLLM_BASE_URL=http://anythingsqlite:3001
ANYLLM_API_KEY=sk-anythingllm
ANYLLM_WORKSPACE_NORMES=normes
ANYLLM_WORKSPACE_TRAMES=trames
ANYLLM_WORKSPACE_ACTES=actes

# Neo4j (Graphe)
NEO4J_AUTH=neo4j/neo4j_pwd
NEO4J_URI=bolt://neo4j:7687

# OpenSearch (Recherche)
OPENSEARCH_URL=http://opensearch:9200
OPENSEARCH_PASSWORD=opensearch_pwd

# Traefik (Load Balancer)
TRAEFIK_DASHBOARD=true
TRAEFIK_API=true
TRAEFIK_ACME_EMAIL=ops@4nkweb.com

# Sécurité
JWT_SECRET_KEY=your-super-secret-jwt-key-change-in-production
JWT_ALGORITHM=HS256
JWT_EXPIRATION=3600

# Monitoring
PROMETHEUS_URL=http://prometheus:9090
GRAFANA_URL=http://grafana:3000

Variables par Environnement

Développement

# .env.dev
ENVIRONMENT=development
DEBUG=true
LOG_LEVEL=DEBUG
DATABASE_URL=postgresql+psycopg://notariat:notariat_pwd@localhost:5432/notariat_dev
REDIS_URL=redis://localhost:6379/0

Production

# .env.prod
ENVIRONMENT=production
DEBUG=false
LOG_LEVEL=INFO
DATABASE_URL=postgresql+psycopg://notariat:${POSTGRES_PASSWORD}@postgres:5432/notariat
REDIS_URL=redis://redis:6379/0

🐳 Configuration Docker

Docker Compose Principal

# infra/docker-compose.yml
version: '3.8'

x-env: &default-env
  TZ: ${TZ}
  PUID: "1000"
  PGID: "1000"

services:
  postgres:
    image: postgres:16
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    volumes:
      - pgdata:/var/lib/postgresql/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
      interval: 30s
      timeout: 10s
      retries: 3

  redis:
    image: redis:7
    command: ["redis-server", "--appendonly", "yes"]
    volumes:
      - redis:/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 30s
      timeout: 10s
      retries: 3

  minio:
    image: minio/minio:latest
    command: server /data --console-address ":9001"
    environment:
      MINIO_ROOT_USER: ${MINIO_ROOT_USER}
      MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
    volumes:
      - minio:/data
    ports:
      - "9000:9000"
      - "9001:9001"
    restart: unless-stopped

  ollama:
    image: ollama/ollama:latest
    volumes:
      - ollama:/root/.ollama
    ports:
      - "11434:11434"
    restart: unless-stopped
    environment:
      - OLLAMA_HOST=0.0.0.0

  anythingsqlite:
    image: kevincharm/anythingllm:latest
    environment:
      - DISABLE_AUTH=true
    depends_on:
      - ollama
    ports:
      - "3001:3001"
    restart: unless-stopped

  neo4j:
    image: neo4j:5.23
    environment:
      - NEO4J_AUTH=${NEO4J_AUTH}
      - NEO4J_PLUGINS=["apoc"]
    volumes:
      - neo4j:/data
    ports:
      - "7474:7474"
      - "7687:7687"
    restart: unless-stopped

  opensearch:
    image: opensearchproject/opensearch:2.11.0
    environment:
      - discovery.type=single-node
      - "OPENSEARCH_INITIAL_ADMIN_PASSWORD=${OPENSEARCH_PASSWORD}"
    volumes:
      - opensearch:/usr/share/opensearch/data
    ports:
      - "9200:9200"
    restart: unless-stopped

  traefik:
    image: traefik:v3.0
    command:
      - "--api.dashboard=true"
      - "--providers.docker=true"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.letsencrypt.acme.email=${TRAEFIK_ACME_EMAIL}"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - letsencrypt:/letsencrypt
    restart: unless-stopped

  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./ops/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus:/prometheus
    ports:
      - "9090:9090"
    restart: unless-stopped

  grafana:
    image: grafana/grafana:latest
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - grafana:/var/lib/grafana
      - ./ops/grafana/provisioning:/etc/grafana/provisioning
    ports:
      - "3000:3000"
    restart: unless-stopped

volumes:
  pgdata:
  redis:
  minio:
  ollama:
  neo4j:
  opensearch:
  letsencrypt:
  prometheus:
  grafana:

networks:
  default:
    driver: bridge

Configuration de Développement

# infra/docker-compose.dev.yml
version: '3.8'

services:
  postgres:
    image: postgres:16
    environment:
      POSTGRES_USER: notariat
      POSTGRES_PASSWORD: notariat_pwd
      POSTGRES_DB: notariat_dev
    ports:
      - "5432:5432"
    volumes:
      - ./dev-data/postgres:/var/lib/postgresql/data

  redis:
    image: redis:7
    ports:
      - "6379:6379"
    volumes:
      - ./dev-data/redis:/data

  minio:
    image: minio/minio:latest
    command: server /data --console-address ":9001"
    environment:
      MINIO_ROOT_USER: minio
      MINIO_ROOT_PASSWORD: minio_pwd
    ports:
      - "9000:9000"
      - "9001:9001"
    volumes:
      - ./dev-data/minio:/data

🐍 Configuration Python

Configuration FastAPI

# services/host_api/config.py
from pydantic import BaseSettings
from typing import Optional

class Settings(BaseSettings):
    # Application
    app_name: str = "API Notariale"
    app_version: str = "1.0.0"
    debug: bool = False

    # Database
    database_url: str = "postgresql+psycopg://notariat:notariat_pwd@localhost:5432/notariat"

    # Redis
    redis_url: str = "redis://localhost:6379/0"

    # MinIO
    minio_endpoint: str = "localhost:9000"
    minio_access_key: str = "minio"
    minio_secret_key: str = "minio_pwd"
    minio_bucket: str = "ingest"

    # Ollama
    ollama_base_url: str = "http://localhost:11434"
    ollama_model: str = "llama3:8b"

    # Security
    jwt_secret_key: str = "your-secret-key"
    jwt_algorithm: str = "HS256"
    jwt_expiration: int = 3600

    # External APIs
    cadastre_api_key: Optional[str] = None
    georisques_api_key: Optional[str] = None
    bodacc_api_key: Optional[str] = None

    class Config:
        env_file = ".env"
        case_sensitive = False

settings = Settings()

Configuration Celery

# services/worker/config.py
from celery import Celery
import os

# Configuration Celery
broker_url = os.getenv("REDIS_URL", "redis://localhost:6379/0")
result_backend = os.getenv("REDIS_URL", "redis://localhost:6379/0")

app = Celery('worker', broker=broker_url, backend=result_backend)

# Configuration des tâches
app.conf.update(
    task_serializer='json',
    accept_content=['json'],
    result_serializer='json',
    timezone='Europe/Paris',
    enable_utc=True,
    task_track_started=True,
    task_time_limit=30 * 60,  # 30 minutes
    task_soft_time_limit=25 * 60,  # 25 minutes
    worker_prefetch_multiplier=1,
    worker_max_tasks_per_child=1000,
    task_routes={
        'pipeline.process_document': {'queue': 'processing'},
        'pipeline.health_check': {'queue': 'monitoring'},
        'pipeline.cleanup': {'queue': 'cleanup'},
    }
)

🔧 Configuration des Services

Nginx Configuration

# ops/nginx.conf
upstream api_backend {
    server api:8000;
}

upstream web_backend {
    server web:8081;
}

server {
    listen 80;
    server_name localhost;

    # API
    location /api/ {
        proxy_pass http://api_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # Web UI
    location / {
        proxy_pass http://web_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # Static files
    location /static/ {
        alias /app/static/;
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

Prometheus Configuration

# ops/prometheus/prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

rule_files:
  - "rules/*.yml"

scrape_configs:
  - job_name: 'api'
    static_configs:
      - targets: ['api:8000']
    metrics_path: '/metrics'
    scrape_interval: 5s

  - job_name: 'worker'
    static_configs:
      - targets: ['worker:5555']
    metrics_path: '/metrics'
    scrape_interval: 5s

  - job_name: 'postgres'
    static_configs:
      - targets: ['postgres:5432']
    scrape_interval: 30s

  - job_name: 'redis'
    static_configs:
      - targets: ['redis:6379']
    scrape_interval: 30s

  - job_name: 'minio'
    static_configs:
      - targets: ['minio:9000']
    scrape_interval: 30s

  - job_name: 'ollama'
    static_configs:
      - targets: ['ollama:11434']
    scrape_interval: 30s

  - job_name: 'neo4j'
    static_configs:
      - targets: ['neo4j:7474']
    scrape_interval: 30s

  - job_name: 'opensearch'
    static_configs:
      - targets: ['opensearch:9200']
    scrape_interval: 30s

Grafana Dashboards

{
  "dashboard": {
    "title": "4NK_IA Notarial System",
    "panels": [
      {
        "title": "API Requests",
        "type": "graph",
        "targets": [
          {
            "expr": "rate(http_requests_total[5m])",
            "legendFormat": "{{method}} {{endpoint}}"
          }
        ]
      },
      {
        "title": "Document Processing",
        "type": "stat",
        "targets": [
          {
            "expr": "documents_processed_total",
            "legendFormat": "Documents Processed"
          }
        ]
      },
      {
        "title": "System Health",
        "type": "table",
        "targets": [
          {
            "expr": "up",
            "legendFormat": "{{instance}}"
          }
        ]
      }
    ]
  }
}

🔐 Configuration de Sécurité

Certificats SSL

# Génération des certificats Let's Encrypt
certbot certonly --webroot -w /var/www/html -d yourdomain.com

# Configuration Traefik pour SSL
traefik:
  command:
    - "--certificatesresolvers.letsencrypt.acme.email=ops@4nkweb.com"
    - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
    - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"

Firewall Configuration

# UFW Configuration
ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 8081/tcp
ufw allow 3000/tcp
ufw allow 9001/tcp
ufw allow 7474/tcp
ufw enable

Secrets Management

# Docker Secrets
echo "notariat_pwd" | docker secret create postgres_password -
echo "minio_pwd" | docker secret create minio_password -
echo "jwt_secret_key" | docker secret create jwt_secret -

# Utilisation dans docker-compose.yml
services:
  postgres:
    secrets:
      - postgres_password
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password

📊 Configuration de Monitoring

Logging Configuration

# services/host_api/logging.py
import logging
import sys
from pythonjsonlogger import jsonlogger

def setup_logging():
    # Configuration du logger
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)

    # Handler pour stdout
    handler = logging.StreamHandler(sys.stdout)
    handler.setLevel(logging.INFO)

    # Format JSON
    formatter = jsonlogger.JsonFormatter(
        '%(asctime)s %(name)s %(levelname)s %(message)s'
    )
    handler.setFormatter(formatter)

    logger.addHandler(handler)

    return logger

Health Checks

# services/host_api/health.py
from fastapi import APIRouter, HTTPException
import asyncio
import aiohttp

router = APIRouter()

@router.get("/health")
async def health_check():
    """Vérification de l'état de tous les services"""
    services = {
        "database": await check_database(),
        "redis": await check_redis(),
        "minio": await check_minio(),
        "ollama": await check_ollama(),
        "neo4j": await check_neo4j(),
        "opensearch": await check_opensearch()
    }

    all_healthy = all(services.values())

    if not all_healthy:
        raise HTTPException(status_code=503, detail=services)

    return {"status": "healthy", "services": services}

async def check_database():
    """Vérification de la base de données"""
    try:
        # Test de connexion
        return True
    except Exception:
        return False

🚀 Configuration de Déploiement

Makefile Commands

# Makefile
.PHONY: help build up down logs clean

help: ## Afficher l'aide
	@echo "Commandes disponibles:"
	@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'

build: ## Construire les images Docker
	docker-compose build

up: ## Démarrer tous les services
	docker-compose up -d

down: ## Arrêter tous les services
	docker-compose down

logs: ## Afficher les logs
	docker-compose logs -f

clean: ## Nettoyer les volumes et images
	docker-compose down -v
	docker system prune -f

dev: ## Démarrer en mode développement
	docker-compose -f docker-compose.dev.yml up -d

test: ## Exécuter les tests
	pytest tests/ -v

install: ## Installer les dépendances
	pip install -r requirements-test.txt

Scripts de Déploiement

#!/bin/bash
# scripts/deploy.sh

set -e

echo "🚀 Déploiement du système notarial 4NK_IA"

# Vérification des prérequis
if ! command -v docker &> /dev/null; then
    echo "❌ Docker n'est pas installé"
    exit 1
fi

if ! command -v docker-compose &> /dev/null; then
    echo "❌ Docker Compose n'est pas installé"
    exit 1
fi

# Copie de la configuration
cp infra/.env.example infra/.env
echo "✅ Configuration copiée"

# Construction des images
docker-compose -f infra/docker-compose.yml build
echo "✅ Images construites"

# Démarrage des services
docker-compose -f infra/docker-compose.yml up -d
echo "✅ Services démarrés"

# Attente de la disponibilité
echo "⏳ Attente de la disponibilité des services..."
sleep 30

# Vérification de la santé
curl -f http://localhost:8000/api/health || {
    echo "❌ L'API n'est pas disponible"
    exit 1
}

echo "✅ Déploiement terminé avec succès"
echo "🌐 API: http://localhost:8000"
echo "🖥️  Web UI: http://localhost:8081"
echo "📊 Grafana: http://localhost:3000"

📋 Checklist de Configuration

Pré-déploiement

  • Variables d'environnement : Fichier .env configuré
  • Certificats SSL : Certificats valides pour HTTPS
  • Firewall : Ports ouverts et sécurisés
  • Base de données : PostgreSQL configuré et accessible
  • Redis : Cache et queue configurés
  • MinIO : Stockage objet configuré
  • Ollama : Modèles LLM téléchargés
  • Monitoring : Prometheus et Grafana configurés

Post-déploiement

  • Health checks : Tous les services répondent
  • Logs : Logs structurés et centralisés
  • Métriques : Collecte des métriques opérationnelle
  • Alertes : Alertes configurées et testées
  • Backup : Stratégie de sauvegarde en place
  • Sécurité : Authentification et autorisation fonctionnelles
  • Performance : Tests de charge effectués
  • Documentation : Documentation mise à jour