mirror of
https://github.com/kossakovsky/n8n-install.git
synced 2026-03-07 22:33:11 +00:00
- Introduced LightRAG hostname and credentials in .env.example for environment setup. - Updated Caddyfile to include reverse proxy configuration for LightRAG service. - Added LightRAG service definition in docker-compose.yml with necessary environment variables and volume mappings. - Enhanced README.md to document LightRAG integration and access details. - Updated scripts to generate LightRAG credentials and include them in the final report for user visibility.
417 lines
16 KiB
Bash
417 lines
16 KiB
Bash
#!/bin/bash
|
|
|
|
set -e
|
|
|
|
# Source the utilities file
|
|
source "$(dirname "$0")/utils.sh"
|
|
|
|
# Get the directory where the script resides
|
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
|
PROJECT_ROOT="$( cd "$SCRIPT_DIR/.." &> /dev/null && pwd )"
|
|
ENV_FILE="$PROJECT_ROOT/.env"
|
|
|
|
# Check if .env file exists
|
|
if [ ! -f "$ENV_FILE" ]; then
|
|
log_error "The .env file ('$ENV_FILE') was not found."
|
|
exit 1
|
|
fi
|
|
|
|
# Load environment variables from .env file
|
|
# Use set -a to export all variables read from the file
|
|
set -a
|
|
source "$ENV_FILE"
|
|
set +a
|
|
|
|
# Function to check if a profile is active
|
|
is_profile_active() {
|
|
local profile_to_check="$1"
|
|
# COMPOSE_PROFILES is sourced from .env and will be available here
|
|
if [ -z "$COMPOSE_PROFILES" ]; then
|
|
return 1 # Not active if COMPOSE_PROFILES is empty or not set
|
|
fi
|
|
# Check if the profile_to_check is in the comma-separated list
|
|
# Adding commas at the beginning and end of both strings handles edge cases
|
|
# (e.g., single profile, profile being a substring of another)
|
|
if [[ ",$COMPOSE_PROFILES," == *",$profile_to_check,"* ]]; then
|
|
return 0 # Active
|
|
else
|
|
return 1 # Not active
|
|
fi
|
|
}
|
|
|
|
# --- Service Access Credentials ---
|
|
|
|
# Display credentials, checking if variables exist
|
|
echo
|
|
log_info "Service Access Credentials. Save this information securely!"
|
|
# Display credentials, checking if variables exist
|
|
|
|
if is_profile_active "n8n"; then
|
|
echo
|
|
echo "================================= n8n ================================="
|
|
echo
|
|
echo "Host: ${N8N_HOSTNAME:-<hostname_not_set>}"
|
|
fi
|
|
|
|
if is_profile_active "open-webui"; then
|
|
echo
|
|
echo "================================= WebUI ==============================="
|
|
echo
|
|
echo "Host: ${WEBUI_HOSTNAME:-<hostname_not_set>}"
|
|
fi
|
|
|
|
if is_profile_active "flowise"; then
|
|
echo
|
|
echo "================================= Flowise ============================="
|
|
echo
|
|
echo "Host: ${FLOWISE_HOSTNAME:-<hostname_not_set>}"
|
|
echo "User: ${FLOWISE_USERNAME:-<not_set_in_env>}"
|
|
echo "Password: ${FLOWISE_PASSWORD:-<not_set_in_env>}"
|
|
fi
|
|
|
|
if is_profile_active "dify"; then
|
|
echo
|
|
echo "================================= Dify ================================="
|
|
echo
|
|
echo "Host: ${DIFY_HOSTNAME:-<hostname_not_set>}"
|
|
echo "Description: AI Application Development Platform with LLMOps"
|
|
echo
|
|
echo "API Access:"
|
|
echo " - Web Interface: https://${DIFY_HOSTNAME:-<hostname_not_set>}"
|
|
echo " - API Endpoint: https://${DIFY_HOSTNAME:-<hostname_not_set>}/v1"
|
|
echo " - Internal API: http://dify-api:5001"
|
|
fi
|
|
|
|
if is_profile_active "supabase"; then
|
|
echo
|
|
echo "================================= Supabase ============================"
|
|
echo
|
|
echo "External Host (via Caddy): ${SUPABASE_HOSTNAME:-<hostname_not_set>}"
|
|
echo "Studio User: ${DASHBOARD_USERNAME:-<not_set_in_env>}"
|
|
echo "Studio Password: ${DASHBOARD_PASSWORD:-<not_set_in_env>}"
|
|
echo
|
|
echo "Internal API Gateway: http://kong:8000"
|
|
echo "Service Role Secret: ${SERVICE_ROLE_KEY:-<not_set_in_env>}"
|
|
fi
|
|
|
|
if is_profile_active "langfuse"; then
|
|
echo
|
|
echo "================================= Langfuse ============================"
|
|
echo
|
|
echo "Host: ${LANGFUSE_HOSTNAME:-<hostname_not_set>}"
|
|
echo "User: ${LANGFUSE_INIT_USER_EMAIL:-<not_set_in_env>}"
|
|
echo "Password: ${LANGFUSE_INIT_USER_PASSWORD:-<not_set_in_env>}"
|
|
fi
|
|
|
|
if is_profile_active "monitoring"; then
|
|
echo
|
|
echo "================================= Grafana ============================="
|
|
echo
|
|
echo "Host: ${GRAFANA_HOSTNAME:-<hostname_not_set>}"
|
|
echo "User: admin"
|
|
echo "Password: ${GRAFANA_ADMIN_PASSWORD:-<not_set_in_env>}"
|
|
echo
|
|
echo "================================= Prometheus =========================="
|
|
echo
|
|
echo "Host: ${PROMETHEUS_HOSTNAME:-<hostname_not_set>}"
|
|
echo "User: ${PROMETHEUS_USERNAME:-<not_set_in_env>}"
|
|
echo "Password: ${PROMETHEUS_PASSWORD:-<not_set_in_env>}"
|
|
fi
|
|
|
|
if is_profile_active "searxng"; then
|
|
echo
|
|
echo "================================= Searxng ============================="
|
|
echo
|
|
echo "Host: ${SEARXNG_HOSTNAME:-<hostname_not_set>}"
|
|
echo "User: ${SEARXNG_USERNAME:-<not_set_in_env>}"
|
|
echo "Password: ${SEARXNG_PASSWORD:-<not_set_in_env>}"
|
|
fi
|
|
|
|
if is_profile_active "portainer"; then
|
|
echo
|
|
echo "================================= Portainer ==========================="
|
|
echo
|
|
echo "Host: ${PORTAINER_HOSTNAME:-<hostname_not_set>}"
|
|
echo "(Note: On first login, Portainer will prompt to set up an admin user.)"
|
|
fi
|
|
|
|
if is_profile_active "postiz"; then
|
|
echo
|
|
echo "================================= Postiz =============================="
|
|
echo
|
|
echo "Host: ${POSTIZ_HOSTNAME:-<hostname_not_set>}"
|
|
echo "Internal Access (e.g., from n8n): http://postiz:5000"
|
|
fi
|
|
|
|
if is_profile_active "postgresus"; then
|
|
echo
|
|
echo "================================= Postgresus =========================="
|
|
echo
|
|
echo "Host: ${POSTGRESUS_HOSTNAME:-<hostname_not_set>}"
|
|
echo "UI (external via Caddy): https://${POSTGRESUS_HOSTNAME:-<hostname_not_set>}"
|
|
echo "UI (internal): http://postgresus:4005"
|
|
echo "------ Backup Target (internal PostgreSQL) ------"
|
|
echo "PG version: ${POSTGRES_VERSION:-17}"
|
|
echo "Host: ${POSTGRES_HOST:-postgres}"
|
|
echo "Port: ${POSTGRES_PORT:-5432}"
|
|
echo "Username: ${POSTGRES_USER:-postgres}"
|
|
echo "Password: ${POSTGRES_PASSWORD:-<not_set_in_env>}"
|
|
echo "DB name: ${POSTGRES_DB:-postgres}"
|
|
echo "Use HTTPS: false"
|
|
fi
|
|
|
|
if is_profile_active "ragapp"; then
|
|
echo
|
|
echo "================================= RAGApp =============================="
|
|
echo
|
|
echo "Host: ${RAGAPP_HOSTNAME:-<hostname_not_set>}"
|
|
echo "Internal Access (e.g., from n8n): http://ragapp:8000"
|
|
echo "User: ${RAGAPP_USERNAME:-<not_set_in_env>}"
|
|
echo "Password: ${RAGAPP_PASSWORD:-<not_set_in_env>}"
|
|
echo "Admin: https://${RAGAPP_HOSTNAME:-<hostname_not_set>}/admin"
|
|
echo "API Docs: https://${RAGAPP_HOSTNAME:-<hostname_not_set>}/docs"
|
|
fi
|
|
|
|
if is_profile_active "ragflow"; then
|
|
echo
|
|
echo "================================= RAGFlow ============================="
|
|
echo
|
|
echo "Host: ${RAGFLOW_HOSTNAME:-<hostname_not_set>}"
|
|
echo "API (external via Caddy): https://${RAGFLOW_HOSTNAME:-<hostname_not_set>}"
|
|
echo "API (internal): http://ragflow:80"
|
|
echo "Note: Uses built-in authentication (login/registration available in web UI)"
|
|
fi
|
|
|
|
if is_profile_active "comfyui"; then
|
|
echo
|
|
echo "================================= ComfyUI ============================="
|
|
echo
|
|
echo "Host: ${COMFYUI_HOSTNAME:-<hostname_not_set>}"
|
|
echo "User: ${COMFYUI_USERNAME:-<not_set_in_env>}"
|
|
echo "Password: ${COMFYUI_PASSWORD:-<not_set_in_env>}"
|
|
fi
|
|
|
|
if is_profile_active "libretranslate"; then
|
|
echo
|
|
echo "================================= LibreTranslate ==========================="
|
|
echo
|
|
echo "Host: ${LT_HOSTNAME:-<hostname_not_set>}"
|
|
echo "User: ${LT_USERNAME:-<not_set_in_env>}"
|
|
echo "Password: ${LT_PASSWORD:-<not_set_in_env>}"
|
|
echo "API (external via Caddy): https://${LT_HOSTNAME:-<hostname_not_set>}"
|
|
echo "API (internal): http://libretranslate:5000"
|
|
echo "Docs: https://github.com/LibreTranslate/LibreTranslate"
|
|
fi
|
|
|
|
if is_profile_active "qdrant"; then
|
|
echo
|
|
echo "================================= Qdrant =============================="
|
|
echo
|
|
echo "Dashboard: https://${QDRANT_HOSTNAME:-<hostname_not_set>}/dashboard"
|
|
echo "Host: https://${QDRANT_HOSTNAME:-<hostname_not_set>}"
|
|
echo "API Key: ${QDRANT_API_KEY:-<not_set_in_env>}"
|
|
echo "Internal REST API Access (e.g., from backend): http://qdrant:6333"
|
|
fi
|
|
|
|
if is_profile_active "crawl4ai"; then
|
|
echo
|
|
echo "================================= Crawl4AI ============================"
|
|
echo
|
|
echo "Internal Access (e.g., from n8n): http://crawl4ai:11235"
|
|
echo "(Note: Not exposed externally via Caddy by default)"
|
|
fi
|
|
|
|
if is_profile_active "gotenberg"; then
|
|
echo
|
|
echo "================================= Gotenberg ============================"
|
|
echo
|
|
echo "Internal Access (e.g., from n8n): http://gotenberg:3000"
|
|
echo "API Documentation: https://gotenberg.dev/docs"
|
|
echo
|
|
echo "Common API Endpoints:"
|
|
echo " HTML to PDF: POST /forms/chromium/convert/html"
|
|
echo " URL to PDF: POST /forms/chromium/convert/url"
|
|
echo " Markdown to PDF: POST /forms/chromium/convert/markdown"
|
|
echo " Office to PDF: POST /forms/libreoffice/convert"
|
|
fi
|
|
|
|
if is_profile_active "waha"; then
|
|
echo
|
|
echo "============================== WAHA (WhatsApp HTTP API) =============================="
|
|
echo
|
|
echo "Dashboard: https://${WAHA_HOSTNAME:-<hostname_not_set>}/dashboard"
|
|
echo "Swagger: https://${WAHA_HOSTNAME:-<hostname_not_set>}"
|
|
echo "Internal: http://waha:3000"
|
|
echo
|
|
echo "Dashboard User: ${WAHA_DASHBOARD_USERNAME:-<not_set_in_env>}"
|
|
echo "Dashboard Pass: ${WAHA_DASHBOARD_PASSWORD:-<not_set_in_env>}"
|
|
echo "Swagger User: ${WHATSAPP_SWAGGER_USERNAME:-<not_set_in_env>}"
|
|
echo "Swagger Pass: ${WHATSAPP_SWAGGER_PASSWORD:-<not_set_in_env>}"
|
|
echo "API key (plain): ${WAHA_API_KEY_PLAIN:-<not_set_in_env>}"
|
|
fi
|
|
|
|
if is_profile_active "paddleocr"; then
|
|
echo
|
|
echo "================================= PaddleOCR ==========================="
|
|
echo
|
|
echo "Host: ${PADDLEOCR_HOSTNAME:-<hostname_not_set>}"
|
|
echo "User: ${PADDLEOCR_USERNAME:-<not_set_in_env>}"
|
|
echo "Password: ${PADDLEOCR_PASSWORD:-<not_set_in_env>}"
|
|
echo "API (external via Caddy): https://${PADDLEOCR_HOSTNAME:-<hostname_not_set>}"
|
|
echo "API (internal): http://paddleocr:8080"
|
|
echo "Docs: https://paddleocr.a2.fyi/docs"
|
|
echo "Notes: PaddleX Basic Serving (CPU), pipeline=OCR"
|
|
fi
|
|
|
|
if is_profile_active "python-runner"; then
|
|
echo
|
|
echo "================================= Python Runner ========================"
|
|
echo
|
|
echo "Internal Container DNS: python-runner"
|
|
echo "Mounted Code Directory: ./python-runner (host) -> /app (container)"
|
|
echo "Entry File: /app/main.py"
|
|
echo "(Note: Internal-only service with no exposed ports; view output via logs)"
|
|
echo "Logs: docker compose -p localai logs -f python-runner"
|
|
fi
|
|
|
|
if is_profile_active "n8n" || is_profile_active "langfuse"; then
|
|
echo
|
|
echo "================================= Redis (Valkey) ======================"
|
|
echo
|
|
echo "Internal Host: ${REDIS_HOST:-redis}"
|
|
echo "Internal Port: ${REDIS_PORT:-6379}"
|
|
echo "Password: ${REDIS_AUTH:-}"
|
|
echo "(Note: Primarily for internal service communication, not exposed externally by default)"
|
|
fi
|
|
|
|
if is_profile_active "letta"; then
|
|
echo
|
|
echo "================================= Letta ================================"
|
|
echo
|
|
echo "Host: ${LETTA_HOSTNAME:-<hostname_not_set>}"
|
|
echo "Authorization: Bearer ${LETTA_SERVER_PASSWORD}"
|
|
fi
|
|
|
|
if is_profile_active "lightrag"; then
|
|
echo
|
|
echo "================================= LightRAG ============================="
|
|
echo
|
|
echo "Host: ${LIGHTRAG_HOSTNAME:-<hostname_not_set>}"
|
|
echo "Web UI: https://${LIGHTRAG_HOSTNAME:-<hostname_not_set>}"
|
|
echo "Internal Access (e.g., from n8n): http://lightrag:9621"
|
|
echo ""
|
|
echo "Authentication (Web UI):"
|
|
echo " User: ${LIGHTRAG_USERNAME:-<not_set_in_env>}"
|
|
echo " Password: ${LIGHTRAG_PASSWORD:-<not_set_in_env>}"
|
|
echo ""
|
|
echo "API Access:"
|
|
echo " API Key: ${LIGHTRAG_API_KEY:-<not_set_in_env>}"
|
|
echo " API Docs: https://${LIGHTRAG_HOSTNAME:-<hostname_not_set>}/docs"
|
|
echo " Ollama-compatible: https://${LIGHTRAG_HOSTNAME:-<hostname_not_set>}/v1/chat/completions"
|
|
echo ""
|
|
echo "Configuration:"
|
|
echo " LLM: Ollama (qwen2.5:32b) at http://ollama:11434"
|
|
echo " Embeddings: Ollama (bge-m3:latest) at http://ollama:11434"
|
|
echo " Storage: Flexible (JSON/PostgreSQL/Neo4j based on installed services)"
|
|
echo ""
|
|
echo "Note: Requires Ollama to be installed and running for LLM and embeddings."
|
|
echo " Upload documents via /app/data/inputs volume or Web UI."
|
|
fi
|
|
|
|
if is_profile_active "cpu" || is_profile_active "gpu-nvidia" || is_profile_active "gpu-amd"; then
|
|
echo
|
|
echo "================================= Ollama =============================="
|
|
echo
|
|
echo "Internal Access (e.g., from n8n, Open WebUI): http://ollama:11434"
|
|
echo "(Note: Ollama runs with the selected profile: cpu, gpu-nvidia, or gpu-amd)"
|
|
fi
|
|
|
|
if is_profile_active "weaviate"; then
|
|
echo
|
|
echo "================================= Weaviate ============================"
|
|
echo
|
|
echo "Host: ${WEAVIATE_HOSTNAME:-<hostname_not_set>}"
|
|
echo "Admin User (for Weaviate RBAC): ${WEAVIATE_USERNAME:-<not_set_in_env>}"
|
|
echo "Weaviate API Key: ${WEAVIATE_API_KEY:-<not_set_in_env>}"
|
|
fi
|
|
|
|
if is_profile_active "neo4j"; then
|
|
echo
|
|
echo "================================= Neo4j =================================="
|
|
echo
|
|
echo "Web UI Host: https://${NEO4J_HOSTNAME:-<hostname_not_set>}"
|
|
echo "Bolt Port (for drivers): 7687 (e.g., neo4j://\\${NEO4J_HOSTNAME:-<hostname_not_set>}:7687)"
|
|
echo "User (for Web UI & API): ${NEO4J_AUTH_USERNAME:-<not_set_in_env>}"
|
|
echo "Password (for Web UI & API): ${NEO4J_AUTH_PASSWORD:-<not_set_in_env>}"
|
|
echo
|
|
echo "HTTP API Access (e.g., for N8N):"
|
|
echo " Authentication: Basic (use User/Password above)"
|
|
echo " Cypher API Endpoint (POST): https://\\${NEO4J_HOSTNAME:-<hostname_not_set>}/db/neo4j/tx/commit"
|
|
echo " Authorization Header Value (for 'Authorization: Basic <value>'): \$(echo -n \"${NEO4J_AUTH_USERNAME:-neo4j}:${NEO4J_AUTH_PASSWORD}\" | base64)"
|
|
fi
|
|
|
|
# Standalone PostgreSQL (used by n8n, Langfuse, etc.)
|
|
# Check if n8n or langfuse is active, as they use this PostgreSQL instance.
|
|
# The Supabase section already details its own internal Postgres.
|
|
if is_profile_active "n8n" || is_profile_active "langfuse"; then
|
|
# Check if Supabase is NOT active, to avoid confusion with Supabase's Postgres if both are present
|
|
# However, the main POSTGRES_PASSWORD is used by this standalone instance.
|
|
# Supabase has its own environment variables for its internal Postgres if configured differently,
|
|
# but the current docker-compose.yml uses the main POSTGRES_PASSWORD for langfuse's postgres dependency too.
|
|
# For clarity, we will label this distinctly.
|
|
echo
|
|
echo "==================== Standalone PostgreSQL (for n8n, Langfuse, etc.) ====================="
|
|
echo
|
|
echo "Host: ${POSTGRES_HOST:-postgres}"
|
|
echo "Port: ${POSTGRES_PORT:-5432}"
|
|
echo "Database: ${POSTGRES_DB:-postgres}" # This is typically 'postgres' or 'n8n' for n8n, and 'langfuse' for langfuse, but refers to the service.
|
|
echo "User: ${POSTGRES_USER:-postgres}"
|
|
echo "Password: ${POSTGRES_PASSWORD:-<not_set_in_env>}"
|
|
echo "(Note: This is the PostgreSQL instance used by services like n8n and Langfuse.)"
|
|
echo "(It is separate from Supabase's internal PostgreSQL if Supabase is also enabled.)"
|
|
fi
|
|
|
|
echo
|
|
echo "======================================================================="
|
|
echo
|
|
|
|
# --- Update Script Info (Placeholder) ---
|
|
log_info "To update the services, run the 'update.sh' script: bash ./scripts/update.sh"
|
|
|
|
# ============================================
|
|
# Cloudflare Tunnel Security Notice
|
|
# ============================================
|
|
if is_profile_active "cloudflare-tunnel"; then
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "🔒 CLOUDFLARE TUNNEL SECURITY"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo ""
|
|
echo "✅ Cloudflare Tunnel is configured and running!"
|
|
echo ""
|
|
echo "Your services are accessible through Cloudflare's secure network."
|
|
echo "All traffic is encrypted and routed through the tunnel."
|
|
echo ""
|
|
echo "🛡️ RECOMMENDED SECURITY ENHANCEMENT:"
|
|
echo " For maximum security, close the following ports in your VPS firewall:"
|
|
echo " • Port 80 (HTTP)"
|
|
echo " • Port 443 (HTTPS)"
|
|
echo " • Port 7687 (Neo4j Bolt)"
|
|
echo ""
|
|
echo " ⚠️ Only close ports AFTER confirming tunnel connectivity!"
|
|
echo ""
|
|
fi
|
|
|
|
echo
|
|
echo "======================================================================"
|
|
echo
|
|
echo "Next Steps:"
|
|
echo "1. Review the credentials above and store them safely."
|
|
echo "2. Access the services via their respective URLs (check \`docker compose ps\` if needed)."
|
|
echo "3. Configure services as needed (e.g., first-run setup for n8n)."
|
|
echo
|
|
echo "======================================================================"
|
|
echo
|
|
log_info "Thank you for using this installer setup!"
|
|
echo
|