mirror of
https://github.com/kossakovsky/n8n-install.git
synced 2026-03-07 22:33:11 +00:00
- Adjusted the service selection wizard to dynamically set the height of the checklist based on the number of services. - Updated final report script to provide clearer API access information for PaddleOCR, distinguishing between external and internal access.
334 lines
12 KiB
Bash
Executable File
334 lines
12 KiB
Bash
Executable File
#!/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 "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 "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 "qdrant"; then
|
|
echo
|
|
echo "================================= Qdrant =============================="
|
|
echo
|
|
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 "paddleocr"; then
|
|
echo
|
|
echo "================================= PaddleOCR ==========================="
|
|
echo
|
|
echo "Host: ${PADDLEOCR_HOSTNAME:-<hostname_not_set>}"
|
|
echo "API (external via Caddy): https://${PADDLEOCR_HOSTNAME:-<hostname_not_set>}"
|
|
echo "API (internal): http://paddleocr:8080"
|
|
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:-LOCALONLYREDIS} (Note: Default if not set in .env)"
|
|
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 "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
|
|
|
|
exit 0 |