From 8b94507aeb10ee2ccc6597f1979fa2044c1d0bd9 Mon Sep 17 00:00:00 2001 From: Francwa Date: Sun, 14 Dec 2025 07:03:37 +0100 Subject: [PATCH] Finished dockerization --- .env.example | 87 ++++++++++----- brain/app.py | 17 ++- docker-compose.yml | 182 ++++++++++++++++++++++++++++++- generate-keys.sh | 27 +++++ librechat/Dockerfile | 4 - librechat/librechat_providers.js | 10 -- 6 files changed, 279 insertions(+), 48 deletions(-) create mode 100755 generate-keys.sh delete mode 100644 librechat/Dockerfile delete mode 100644 librechat/librechat_providers.js diff --git a/.env.example b/.env.example index 1ba74e5..2ea651e 100644 --- a/.env.example +++ b/.env.example @@ -1,34 +1,69 @@ -# LLM Provider Selection -# Options: "deepseek" or "ollama" -LLM_PROVIDER=ollama +# Agent Media - Environment Variables -# DeepSeek LLM Configuration (if using DeepSeek) -DEEPSEEK_API_KEY=your_deepseek_api_key -DEEPSEEK_BASE_URL=https://api.deepseek.com -DEEPSEEK_MODEL=deepseek-chat +# LibreChat Security Keys +# Generate secure keys with: openssl rand -base64 32 +JWT_SECRET=your-super-secret-jwt-key-change-this-in-production +JWT_REFRESH_SECRET=your-super-secret-refresh-key-change-this-too -# Ollama LLM Configuration (if using Ollama) -OLLAMA_BASE_URL=http://localhost:11434 -OLLAMA_MODEL=llama3.2 +# Generate with: openssl rand -hex 16 (for CREDS_KEY) +CREDS_KEY=your-32-character-secret-key-here -# LLM Settings -TEMPERATURE=0.2 +# Generate with: openssl rand -hex 8 (for CREDS_IV) +CREDS_IV=your-16-character-iv-here -# TMDB API Configuration -TMDB_API_KEY=your_tmdb_api_key -TMDB_BASE_URL=https://api.themoviedb.org/3 +# LibreChat Configuration +DOMAIN_CLIENT=http://localhost:3080 +DOMAIN_SERVER=http://localhost:3080 -# Storage Configuration -MEMORY_FILE=memory.json +# Session expiry (in milliseconds) +# Default: 15 minutes +SESSION_EXPIRY=900000 + +# Refresh token expiry (in milliseconds) +# Default: 7 days +REFRESH_TOKEN_EXPIRY=604800000 + +# Meilisearch Configuration +# Master key for Meilisearch (generate with: openssl rand -base64 32) +MEILI_MASTER_KEY=DrhYf7zENyR6AlUCKmnz0eYASOQdl6zxH7s7MKFSfFU + +# PostgreSQL Configuration (for RAG API) +POSTGRES_DB=librechat_rag +POSTGRES_USER=postgres +POSTGRES_PASSWORD=postgres + +# RAG API Configuration (Vector Database) +RAG_COLLECTION_NAME=testcollection +RAG_EMBEDDINGS_PROVIDER=openai +RAG_EMBEDDINGS_MODEL=text-embedding-3-small + +# API Keys +# OpenAI API Key (required for RAG embeddings) +OPENAI_API_KEY=your-openai-api-key-here + +# Deepseek API Key (for LLM in agent-brain) +DEEPSEEK_API_KEY=your-deepseek-api-key-here + +# Agent Brain Configuration + +# LLM Provider (deepseek or ollama) +LLM_PROVIDER=deepseek + +# Memory storage directory (inside container) +MEMORY_STORAGE_DIR=/data/memory + +# API Key for agent-brain (used by LibreChat custom endpoint) +AGENT_BRAIN_API_KEY=agent-brain-secret-key + +# External Services (Optional) +# TMDB API Key (for movie metadata) +TMDB_API_KEY=your-tmdb-key # qBittorrent Configuration -QBIT_HOST=http://192.168.178.47:30024 -QBIT_USER=admin -QBIT_PASS=adminadmin +QBITTORRENT_URL=http://localhost:8080 +QBITTORRENT_USERNAME=admin +QBITTORRENT_PASSWORD=adminpass -# Security Configuration -MAX_TOOL_ITERATIONS=10 -REQUEST_TIMEOUT=30 - -# Memory Configuration -MAX_HISTORY_MESSAGES=10 +# Debug Options +DEBUG_LOGGING=false +DEBUG_CONSOLE=false diff --git a/brain/app.py b/brain/app.py index 3e6849c..2788a9f 100644 --- a/brain/app.py +++ b/brain/app.py @@ -9,6 +9,7 @@ from typing import Any from fastapi import FastAPI, HTTPException from fastapi.responses import JSONResponse, StreamingResponse +from fastapi.staticfiles import StaticFiles from pydantic import BaseModel, Field, validator from agent.agent import Agent @@ -29,9 +30,21 @@ app = FastAPI( version="0.2.0", ) +# TODO: Make a variable +manifests = "manifests" +# Sécurité : on vérifie que le dossier existe pour ne pas faire planter l'app au démarrage +if os.path.exists(manifests): + app.mount("/manifests", StaticFiles(directory=manifests), name="manifests") +else: + print( + f"⚠️ ATTENTION : Le dossier '{manifests}' est introuvable. Le plugin ne marchera pas." + ) + # Initialize memory context at startup -init_memory(storage_dir="memory_data") -logger.info("Memory context initialized") +# Use /data/memory in Docker, fallback to memory_data for local dev +storage_dir = os.getenv("MEMORY_STORAGE_DIR", "memory_data") +init_memory(storage_dir=storage_dir) +logger.info(f"Memory context initialized (storage: {storage_dir})") # Initialize LLM based on environment variable llm_provider = os.getenv("LLM_PROVIDER", "deepseek").lower() diff --git a/docker-compose.yml b/docker-compose.yml index ba3409e..22d2291 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,6 +6,8 @@ services: build: context: ./brain dockerfile: Dockerfile + container_name: agent-brain + restart: unless-stopped env_file: .env ports: - "8000:8000" @@ -15,20 +17,188 @@ services: - agent-logs:/data/logs # Development: mount code for hot reload (comment out in production) # - ./brain:/app + environment: + # LLM Configuration + LLM_PROVIDER: ${LLM_PROVIDER:-deepseek} + DEEPSEEK_API_KEY: ${DEEPSEEK_API_KEY:-} - # Da face - frontend: - build: - context: ./librechat - dockerfile: Dockerfile + # Memory storage + MEMORY_STORAGE_DIR: /data/memory + + # External services + TMDB_API_KEY: ${TMDB_API_KEY:-} + QBITTORRENT_URL: ${QBITTORRENT_URL:-} + QBITTORRENT_USERNAME: ${QBITTORRENT_USERNAME:-} + QBITTORRENT_PASSWORD: ${QBITTORRENT_PASSWORD:-} + networks: + - agent-network + + # Da face (LibreChat) + librechat: + image: ghcr.io/danny-avila/librechat-dev:latest + container_name: librechat-frontend + restart: unless-stopped ports: - "3080:3080" depends_on: + - mongodb + - meilisearch + - rag_api - agent-brain + env_file: .env + environment: + # MongoDB connection (no auth, matching LibreChat default) + MONGO_URI: mongodb://mongodb:27017/LibreChat + + # App configuration + HOST: 0.0.0.0 + PORT: 3080 + + # Security + JWT_SECRET: ${JWT_SECRET:-your-super-secret-jwt-key-change-this-in-production} + JWT_REFRESH_SECRET: ${JWT_REFRESH_SECRET:-your-super-secret-refresh-key-change-this-too} + CREDS_KEY: ${CREDS_KEY:-your-32-character-secret-key-here} + CREDS_IV: ${CREDS_IV:-your-16-character-iv-here} + + # Session + SESSION_EXPIRY: ${SESSION_EXPIRY:-1000 * 60 * 15} + REFRESH_TOKEN_EXPIRY: ${REFRESH_TOKEN_EXPIRY:-1000 * 60 * 60 * 24 * 7} + + # Domain + DOMAIN_CLIENT: ${DOMAIN_CLIENT:-http://localhost:3080} + DOMAIN_SERVER: ${DOMAIN_SERVER:-http://localhost:3080} + + # Meilisearch + MEILI_HOST: http://meilisearch:7700 + MEILI_MASTER_KEY: ${MEILI_MASTER_KEY:-DrhYf7zENyR6AlUCKmnz0eYASOQdl6zxH7s7MKFSfFU} + + # RAG API + RAG_API_URL: http://rag_api:8000 + + # Endpoints + ENDPOINTS: custom + + # Custom endpoint pointing to agent-brain + CUSTOM_API_KEY: ${AGENT_BRAIN_API_KEY:-agent-brain-secret-key} + + # Debug (optional) + DEBUG_LOGGING: ${DEBUG_LOGGING:-false} + DEBUG_CONSOLE: ${DEBUG_CONSOLE:-false} + volumes: + - ./librechat/librechat.yaml:/app/librechat.yaml:ro + - librechat-images:/app/client/public/images + - librechat-logs:/app/api/logs + networks: + - agent-network + + # MongoDB for LibreChat + mongodb: + image: mongo:latest + container_name: librechat-mongodb + restart: unless-stopped + volumes: + - mongodb-data:/data/db + command: mongod --noauth + ports: + - "27017:27017" + networks: + - agent-network + + # Meilisearch - Search engine for LibreChat + meilisearch: + image: getmeili/meilisearch:v1.11.3 + container_name: librechat-meilisearch + restart: unless-stopped + volumes: + - meilisearch-data:/meili_data + environment: + MEILI_HOST: http://meilisearch:7700 + MEILI_HTTP_ADDR: meilisearch:7700 + MEILI_MASTER_KEY: ${MEILI_MASTER_KEY:-DrhYf7zENyR6AlUCKmnz0eYASOQdl6zxH7s7MKFSfFU} + ports: + - "7700:7700" + networks: + - agent-network + + # PostgreSQL with pgvector for RAG API + pgvector: + image: ankane/pgvector:latest + container_name: librechat-pgvector + restart: unless-stopped + environment: + POSTGRES_DB: ${POSTGRES_DB:-librechat_rag} + POSTGRES_USER: ${POSTGRES_USER:-postgres} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres} + volumes: + - pgvector-data:/var/lib/postgresql/data + ports: + - "5432:5432" + networks: + - agent-network + + # RAG API - Vector database for LibreChat + rag_api: + image: ghcr.io/danny-avila/librechat-rag-api-dev-lite:latest + container_name: librechat-rag-api + restart: unless-stopped + depends_on: + - pgvector + environment: + PORT: 8000 + HOST: 0.0.0.0 + # PostgreSQL connection (multiple variable names for compatibility) + DB_HOST: pgvector + DB_PORT: 5432 + DB_NAME: ${POSTGRES_DB:-librechat_rag} + DB_USER: ${POSTGRES_USER:-postgres} + DB_PASSWORD: ${POSTGRES_PASSWORD:-postgres} + POSTGRES_DB: ${POSTGRES_DB:-librechat_rag} + POSTGRES_USER: ${POSTGRES_USER:-postgres} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres} + # RAG configuration + COLLECTION_NAME: ${RAG_COLLECTION_NAME:-testcollection} + EMBEDDINGS_PROVIDER: ${RAG_EMBEDDINGS_PROVIDER:-openai} + EMBEDDINGS_MODEL: ${RAG_EMBEDDINGS_MODEL:-text-embedding-3-small} + OPENAI_API_KEY: ${OPENAI_API_KEY:-} + RAG_UPLOAD_DIR: /app/uploads + volumes: + - rag-uploads:/app/uploads + ports: + - "8001:8000" + networks: + - agent-network # Named volumes for persistent data volumes: + # MongoDB data + mongodb-data: + driver: local + + # Meilisearch data + meilisearch-data: + driver: local + + # PostgreSQL pgvector data + pgvector-data: + driver: local + + # RAG API uploads + rag-uploads: + driver: local + + # LibreChat data + librechat-images: + driver: local + librechat-logs: + driver: local + + # Agent Brain data agent-memory: driver: local agent-logs: - driver: local \ No newline at end of file + driver: local + +# Network for inter-service communication +networks: + agent-network: + driver: bridge \ No newline at end of file diff --git a/generate-keys.sh b/generate-keys.sh new file mode 100755 index 0000000..3923201 --- /dev/null +++ b/generate-keys.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# Script to generate secure keys for LibreChat +# Run this script to generate random secure keys for your .env file + +echo "===================================" +echo "LibreChat Security Keys Generator" +echo "===================================" +echo "" + +echo "# MongoDB Password" +echo "MONGO_PASSWORD=$(openssl rand -base64 24)" +echo "" + +echo "# JWT Secrets" +echo "JWT_SECRET=$(openssl rand -base64 32)" +echo "JWT_REFRESH_SECRET=$(openssl rand -base64 32)" +echo "" + +echo "# Credentials Encryption Keys" +echo "CREDS_KEY=$(openssl rand -hex 16)" +echo "CREDS_IV=$(openssl rand -hex 8)" +echo "" + +echo "===================================" +echo "Copy these values to your .env file" +echo "===================================" diff --git a/librechat/Dockerfile b/librechat/Dockerfile deleted file mode 100644 index 1fb04a2..0000000 --- a/librechat/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM ghcr.io/danny-avila/librechat:latest - -COPY librechat.yaml /app/librechat.yaml -COPY librechat_providers.js /app/librechat_providers.js \ No newline at end of file diff --git a/librechat/librechat_providers.js b/librechat/librechat_providers.js deleted file mode 100644 index a073eb7..0000000 --- a/librechat/librechat_providers.js +++ /dev/null @@ -1,10 +0,0 @@ -[ - { - "name": "LocalAgent", - "type": "openai", - "baseURL": "http://host.docker.internal:8000", - "apiKey": "sk-8b00d72c417740ea96efd9c3eeddd148", - "model": "local-deepseek-agent", - "custom": true - } -]