mirror of
https://github.com/kossakovsky/n8n-install.git
synced 2026-03-07 14:23:08 +00:00
rebrand backup service following upstream project rename. updates docker image to databasus/databasus:latest, adds healthcheck, and includes cleanup function for migration from old container name.
278 lines
11 KiB
Bash
Executable File
278 lines
11 KiB
Bash
Executable File
#!/bin/bash
|
||
# =============================================================================
|
||
# 04_wizard.sh - Interactive service selection wizard
|
||
# =============================================================================
|
||
# Guides the user through selecting which services to install using whiptail.
|
||
#
|
||
# Features:
|
||
# - Single-screen checklist for service selection
|
||
# - Default services: n8n, portainer, monitoring, databasus
|
||
# - Preserves previously selected services on re-run
|
||
# - Updates COMPOSE_PROFILES in .env file
|
||
#
|
||
# Usage: bash scripts/04_wizard.sh
|
||
# =============================================================================
|
||
|
||
# Source the utilities file and initialize paths
|
||
source "$(dirname "$0")/utils.sh"
|
||
init_paths
|
||
|
||
# Verify whiptail is available
|
||
require_whiptail
|
||
|
||
# Set DEBIAN_FRONTEND for whiptail
|
||
save_debian_frontend
|
||
|
||
# --- Read current COMPOSE_PROFILES from .env ---
|
||
CURRENT_PROFILES_VALUE=""
|
||
if [ -f "$ENV_FILE" ]; then
|
||
LINE_CONTENT=$(grep "^COMPOSE_PROFILES=" "$ENV_FILE" || echo "")
|
||
if [ -n "$LINE_CONTENT" ]; then
|
||
# Get value after '=', remove potential surrounding quotes
|
||
CURRENT_PROFILES_VALUE=$(echo "$LINE_CONTENT" | cut -d'=' -f2- | sed 's/^"//' | sed 's/"$//')
|
||
fi
|
||
fi
|
||
# Prepare comma-separated current profiles for easy matching, adding leading/trailing commas
|
||
current_profiles_for_matching=",$CURRENT_PROFILES_VALUE,"
|
||
|
||
# --- Define available services and their descriptions ---
|
||
# Base service definitions (tag, description)
|
||
base_services_data=(
|
||
"cloudflare-tunnel" "Cloudflare Tunnel (Zero-Trust Secure Access)"
|
||
"comfyui" "ComfyUI (Node-based Stable Diffusion UI)"
|
||
"crawl4ai" "Crawl4ai (Web Crawler for AI)"
|
||
"databasus" "Databasus (Database backups & monitoring)"
|
||
"dify" "Dify (AI Application Development Platform with LLMOps)"
|
||
"docling" "Docling (Universal Document Converter to Markdown/JSON)"
|
||
"flowise" "Flowise (AI Agent Builder)"
|
||
"gost" "Gost Proxy (HTTP/HTTPS proxy for AI services outbound traffic)"
|
||
"gotenberg" "Gotenberg (Document Conversion API)"
|
||
"langfuse" "Langfuse Suite (AI Observability - includes Clickhouse, Minio)"
|
||
"letta" "Letta (Agent Server & SDK)"
|
||
"libretranslate" "LibreTranslate (Self-hosted translation API - 50+ languages)"
|
||
"lightrag" "LightRAG (Graph-based RAG with knowledge graphs)"
|
||
"monitoring" "Monitoring Suite (Prometheus, Grafana, cAdvisor, Node-Exporter)"
|
||
"n8n" "n8n, n8n-worker, n8n-import (Workflow Automation)"
|
||
"neo4j" "Neo4j (Graph Database)"
|
||
"nocodb" "NocoDB (Open Source Airtable Alternative - Spreadsheet Database)"
|
||
"ollama" "Ollama (Local LLM Runner - select hardware in next step)"
|
||
"open-webui" "Open WebUI (ChatGPT-like Interface)"
|
||
"paddleocr" "PaddleOCR (OCR API Server)"
|
||
"portainer" "Portainer (Docker management UI)"
|
||
"postiz" "Postiz (Social publishing platform)"
|
||
"python-runner" "Python Runner (Run your custom Python code from ./python-runner)"
|
||
"qdrant" "Qdrant (Vector Database)"
|
||
"ragapp" "RAGApp (Open-source RAG UI + API)"
|
||
"ragflow" "RAGFlow (Deep document understanding RAG engine)"
|
||
"searxng" "SearXNG (Private Metasearch Engine)"
|
||
"supabase" "Supabase (Backend as a Service)"
|
||
"waha" "WAHA – WhatsApp HTTP API (NOWEB engine)"
|
||
"weaviate" "Weaviate (Vector Database with API Key Auth)"
|
||
)
|
||
|
||
services=() # This will be the final array for whiptail
|
||
|
||
# Populate the services array for whiptail based on current profiles or defaults
|
||
idx=0
|
||
while [ $idx -lt ${#base_services_data[@]} ]; do
|
||
tag="${base_services_data[idx]}"
|
||
description="${base_services_data[idx+1]}"
|
||
status="OFF" # Default to OFF
|
||
|
||
if [ -n "$CURRENT_PROFILES_VALUE" ] && [ "$CURRENT_PROFILES_VALUE" != '""' ]; then # Check if .env has profiles
|
||
if [[ "$tag" == "ollama" ]]; then
|
||
if [[ "$current_profiles_for_matching" == *",cpu,"* || \
|
||
"$current_profiles_for_matching" == *",gpu-nvidia,"* || \
|
||
"$current_profiles_for_matching" == *",gpu-amd,"* ]]; then
|
||
status="ON"
|
||
fi
|
||
elif [[ "$current_profiles_for_matching" == *",$tag,"* ]]; then
|
||
status="ON"
|
||
fi
|
||
else
|
||
# .env has no COMPOSE_PROFILES or it's empty/just quotes, use hardcoded defaults
|
||
case "$tag" in
|
||
"n8n"|"portainer"|"monitoring"|"databasus") status="ON" ;;
|
||
*) status="OFF" ;;
|
||
esac
|
||
fi
|
||
services+=("$tag" "$description" "$status")
|
||
idx=$((idx + 2))
|
||
done
|
||
|
||
# Use whiptail to display the checklist (with adaptive sizing)
|
||
CHOICES=$(wt_checklist "Service Selection Wizard" \
|
||
"Choose the services you want to deploy.\nUse ARROW KEYS to navigate, SPACEBAR to select/deselect, ENTER to confirm." \
|
||
"${services[@]}")
|
||
exitstatus=$?
|
||
|
||
# Restore original DEBIAN_FRONTEND
|
||
restore_debian_frontend
|
||
|
||
# Exit if user pressed Cancel or Esc
|
||
if [ $exitstatus -ne 0 ]; then
|
||
log_info "Service selection cancelled by user. Exiting wizard."
|
||
log_info "No changes made to service profiles. Default services will be used."
|
||
# Set COMPOSE_PROFILES to empty to ensure only core services run
|
||
update_compose_profiles ""
|
||
exit 0
|
||
fi
|
||
|
||
# Process selected services
|
||
selected_profiles=()
|
||
ollama_selected=0
|
||
ollama_profile=""
|
||
|
||
if [ -n "$CHOICES" ]; then
|
||
# Parse whiptail output safely (without eval)
|
||
temp_choices=()
|
||
wt_parse_choices "$CHOICES" temp_choices
|
||
|
||
for choice in "${temp_choices[@]}"; do
|
||
if [ "$choice" == "ollama" ]; then
|
||
ollama_selected=1
|
||
else
|
||
selected_profiles+=("$choice")
|
||
fi
|
||
done
|
||
fi
|
||
|
||
# Enforce mutual exclusivity between Dify and Supabase (compact)
|
||
if printf '%s\n' "${selected_profiles[@]}" | grep -qx "dify" && \
|
||
printf '%s\n' "${selected_profiles[@]}" | grep -qx "supabase"; then
|
||
CHOSEN_EXCLUSIVE=$(wt_radiolist "Conflict: Dify and Supabase" \
|
||
"Dify and Supabase are mutually exclusive. Choose which one to keep." \
|
||
"supabase" \
|
||
"dify" "Keep Dify (AI App Platform)" OFF \
|
||
"supabase" "Keep Supabase (Backend as a Service)" ON)
|
||
[ -z "$CHOSEN_EXCLUSIVE" ] && CHOSEN_EXCLUSIVE="supabase"
|
||
|
||
to_remove=$([ "$CHOSEN_EXCLUSIVE" = "dify" ] && echo "supabase" || echo "dify")
|
||
tmp=()
|
||
for p in "${selected_profiles[@]}"; do
|
||
[ "$p" = "$to_remove" ] || tmp+=("$p")
|
||
done
|
||
selected_profiles=("${tmp[@]}")
|
||
log_info "Mutual exclusivity enforced: kept '$CHOSEN_EXCLUSIVE', removed '$to_remove'."
|
||
fi
|
||
|
||
# If Ollama was selected, prompt for the hardware profile
|
||
if [ $ollama_selected -eq 1 ]; then
|
||
# Determine default selected Ollama hardware profile from .env
|
||
default_ollama_hardware="cpu" # Fallback default
|
||
ollama_hw_on_cpu="OFF"
|
||
ollama_hw_on_gpu_nvidia="OFF"
|
||
ollama_hw_on_gpu_amd="OFF"
|
||
|
||
# Check current_profiles_for_matching which includes commas, e.g., ",cpu,"
|
||
if [[ "$current_profiles_for_matching" == *",cpu,"* ]]; then
|
||
ollama_hw_on_cpu="ON"
|
||
default_ollama_hardware="cpu"
|
||
elif [[ "$current_profiles_for_matching" == *",gpu-nvidia,"* ]]; then
|
||
ollama_hw_on_gpu_nvidia="ON"
|
||
default_ollama_hardware="gpu-nvidia"
|
||
elif [[ "$current_profiles_for_matching" == *",gpu-amd,"* ]]; then
|
||
ollama_hw_on_gpu_amd="ON"
|
||
default_ollama_hardware="gpu-amd"
|
||
else
|
||
# If ollama was selected in the main list, but no specific hardware profile was previously set,
|
||
# default to CPU ON for the radiolist.
|
||
ollama_hw_on_cpu="ON"
|
||
default_ollama_hardware="cpu"
|
||
fi
|
||
|
||
ollama_hardware_options=(
|
||
"cpu" "CPU (Recommended for most users)" "$ollama_hw_on_cpu"
|
||
"gpu-nvidia" "NVIDIA GPU (Requires NVIDIA drivers & CUDA)" "$ollama_hw_on_gpu_nvidia"
|
||
"gpu-amd" "AMD GPU (Requires ROCm drivers)" "$ollama_hw_on_gpu_amd"
|
||
)
|
||
CHOSEN_OLLAMA_PROFILE=$(wt_radiolist "Ollama Hardware Profile" \
|
||
"Choose the hardware profile for Ollama. This will be added to your Docker Compose profiles." \
|
||
"$default_ollama_hardware" \
|
||
"${ollama_hardware_options[@]}")
|
||
|
||
ollama_exitstatus=$?
|
||
if [ $ollama_exitstatus -eq 0 ] && [ -n "$CHOSEN_OLLAMA_PROFILE" ]; then
|
||
selected_profiles+=("$CHOSEN_OLLAMA_PROFILE")
|
||
ollama_profile="$CHOSEN_OLLAMA_PROFILE" # Store for user message
|
||
log_info "Ollama hardware profile selected: $CHOSEN_OLLAMA_PROFILE"
|
||
else
|
||
log_info "Ollama hardware profile selection cancelled or no choice made. Ollama will not be configured with a specific hardware profile."
|
||
# ollama_selected remains 1, but no specific profile is added.
|
||
# This means "ollama" won't be in COMPOSE_PROFILES unless a hardware profile is chosen.
|
||
ollama_selected=0 # Mark as not fully selected if profile choice is cancelled
|
||
fi
|
||
fi
|
||
|
||
# If Gost was selected, prompt for upstream proxy URL
|
||
gost_selected=0
|
||
for p in "${selected_profiles[@]}"; do
|
||
[ "$p" = "gost" ] && gost_selected=1 && break
|
||
done
|
||
|
||
if [ $gost_selected -eq 1 ]; then
|
||
# Get existing value from .env if available
|
||
EXISTING_UPSTREAM=$(read_env_var "GOST_UPSTREAM_PROXY")
|
||
|
||
GOST_UPSTREAM_INPUT=$(wt_input "Gost Upstream Proxy" \
|
||
"Enter your external proxy URL for geo-bypass.\n\nExamples:\n socks5://user:pass@proxy.com:1080\n http://user:pass@proxy.com:8080\n\nThis proxy should be located outside restricted regions." \
|
||
"$EXISTING_UPSTREAM") || true
|
||
|
||
if [ -n "$GOST_UPSTREAM_INPUT" ]; then
|
||
# Save upstream proxy to .env file
|
||
write_env_var "GOST_UPSTREAM_PROXY" "$GOST_UPSTREAM_INPUT"
|
||
log_info "Gost upstream proxy configured: $GOST_UPSTREAM_INPUT"
|
||
|
||
# Also generate GOST_PROXY_URL (needed because wizard runs AFTER generate_secrets)
|
||
GOST_USER=$(read_env_var "GOST_USERNAME")
|
||
GOST_PASS=$(read_env_var "GOST_PASSWORD")
|
||
if [ -n "$GOST_USER" ] && [ -n "$GOST_PASS" ]; then
|
||
GOST_PROXY_URL="http://${GOST_USER}:${GOST_PASS}@gost:8080"
|
||
write_env_var "GOST_PROXY_URL" "$GOST_PROXY_URL"
|
||
log_info "Gost proxy URL generated: http://***:***@gost:8080"
|
||
fi
|
||
else
|
||
# Remove gost from selected profiles if no upstream provided
|
||
tmp=()
|
||
for p in "${selected_profiles[@]}"; do
|
||
[ "$p" != "gost" ] && tmp+=("$p")
|
||
done
|
||
selected_profiles=("${tmp[@]}")
|
||
log_warning "Gost requires an upstream proxy. Gost has been removed from selection."
|
||
fi
|
||
fi
|
||
|
||
if [ ${#selected_profiles[@]} -eq 0 ]; then
|
||
log_info "No optional services selected."
|
||
COMPOSE_PROFILES_VALUE=""
|
||
else
|
||
log_info "Selected service profiles:"
|
||
# Join the array into a comma-separated string
|
||
COMPOSE_PROFILES_VALUE=$(IFS=,; echo "${selected_profiles[*]}")
|
||
for profile in "${selected_profiles[@]}"; do
|
||
# Check if the current profile is an Ollama hardware profile that was chosen
|
||
if [[ "$profile" == "cpu" || "$profile" == "gpu-nvidia" || "$profile" == "gpu-amd" ]]; then
|
||
if [ "$profile" == "$ollama_profile" ]; then
|
||
echo -e " ${GREEN}*${NC} Ollama ($profile profile)"
|
||
else
|
||
echo -e " ${GREEN}*${NC} $profile"
|
||
fi
|
||
else
|
||
echo -e " ${GREEN}*${NC} $profile"
|
||
fi
|
||
done
|
||
fi
|
||
|
||
# Update or add COMPOSE_PROFILES in .env file
|
||
update_compose_profiles "$COMPOSE_PROFILES_VALUE"
|
||
if [ -z "$COMPOSE_PROFILES_VALUE" ]; then
|
||
log_info "Only core services (Caddy, Postgres, Redis) will be started."
|
||
else
|
||
log_info "The following Docker Compose profiles will be active: ${COMPOSE_PROFILES_VALUE}"
|
||
fi
|
||
|
||
# Cleanup any .bak files created by sed
|
||
cleanup_bak_files "$PROJECT_ROOT"
|
||
|
||
exit 0
|