mirror of
https://github.com/kossakovsky/n8n-install.git
synced 2026-03-07 22:33:11 +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.
544 lines
15 KiB
Bash
Executable File
544 lines
15 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Generate data.json for the welcome page with active services and credentials
|
|
|
|
set -e
|
|
|
|
# Source the utilities file and initialize paths
|
|
source "$(dirname "$0")/utils.sh"
|
|
init_paths
|
|
|
|
OUTPUT_FILE="$PROJECT_ROOT/welcome/data.json"
|
|
|
|
# Load environment variables from .env file
|
|
load_env || exit 1
|
|
|
|
# Ensure welcome directory exists
|
|
mkdir -p "$PROJECT_ROOT/welcome"
|
|
|
|
# Remove existing data.json if it exists (always regenerate)
|
|
if [ -f "$OUTPUT_FILE" ]; then
|
|
rm -f "$OUTPUT_FILE"
|
|
fi
|
|
|
|
# Start building JSON
|
|
GENERATED_AT=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
|
|
# Build services array - each entry is a formatted JSON block
|
|
declare -a SERVICES_ARRAY
|
|
|
|
# n8n
|
|
if is_profile_active "n8n"; then
|
|
N8N_WORKER_COUNT_VAL="${N8N_WORKER_COUNT:-1}"
|
|
SERVICES_ARRAY+=(" \"n8n\": {
|
|
\"hostname\": \"$(json_escape "$N8N_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"note\": \"Create your account on first login\"
|
|
},
|
|
\"extra\": {
|
|
\"workers\": \"$N8N_WORKER_COUNT_VAL\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Flowise
|
|
if is_profile_active "flowise"; then
|
|
SERVICES_ARRAY+=(" \"flowise\": {
|
|
\"hostname\": \"$(json_escape "$FLOWISE_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"note\": \"Create your account on first login\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Open WebUI
|
|
if is_profile_active "open-webui"; then
|
|
SERVICES_ARRAY+=(" \"open-webui\": {
|
|
\"hostname\": \"$(json_escape "$WEBUI_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"note\": \"Create account on first login\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Grafana (monitoring)
|
|
if is_profile_active "monitoring"; then
|
|
SERVICES_ARRAY+=(" \"grafana\": {
|
|
\"hostname\": \"$(json_escape "$GRAFANA_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"username\": \"admin\",
|
|
\"password\": \"$(json_escape "$GRAFANA_ADMIN_PASSWORD")\"
|
|
}
|
|
}")
|
|
SERVICES_ARRAY+=(" \"prometheus\": {
|
|
\"hostname\": \"$(json_escape "$PROMETHEUS_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"username\": \"$(json_escape "$PROMETHEUS_USERNAME")\",
|
|
\"password\": \"$(json_escape "$PROMETHEUS_PASSWORD")\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Portainer
|
|
if is_profile_active "portainer"; then
|
|
SERVICES_ARRAY+=(" \"portainer\": {
|
|
\"hostname\": \"$(json_escape "$PORTAINER_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"note\": \"Create admin account on first login\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Databasus
|
|
if is_profile_active "databasus"; then
|
|
SERVICES_ARRAY+=(" \"databasus\": {
|
|
\"hostname\": \"$(json_escape "$DATABASUS_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"note\": \"PostgreSQL credentials are shown in the PostgreSQL card\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Langfuse
|
|
if is_profile_active "langfuse"; then
|
|
SERVICES_ARRAY+=(" \"langfuse\": {
|
|
\"hostname\": \"$(json_escape "$LANGFUSE_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"username\": \"$(json_escape "$LANGFUSE_INIT_USER_EMAIL")\",
|
|
\"password\": \"$(json_escape "$LANGFUSE_INIT_USER_PASSWORD")\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Supabase
|
|
if is_profile_active "supabase"; then
|
|
SERVICES_ARRAY+=(" \"supabase\": {
|
|
\"hostname\": \"$(json_escape "$SUPABASE_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"username\": \"$(json_escape "$DASHBOARD_USERNAME")\",
|
|
\"password\": \"$(json_escape "$DASHBOARD_PASSWORD")\"
|
|
},
|
|
\"extra\": {
|
|
\"internal_api\": \"http://kong:8000\",
|
|
\"service_role_key\": \"$(json_escape "$SERVICE_ROLE_KEY")\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Dify
|
|
if is_profile_active "dify"; then
|
|
SERVICES_ARRAY+=(" \"dify\": {
|
|
\"hostname\": \"$(json_escape "$DIFY_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"note\": \"Create account on first login\"
|
|
},
|
|
\"extra\": {
|
|
\"api_endpoint\": \"https://$(json_escape "$DIFY_HOSTNAME")/v1\",
|
|
\"internal_api\": \"http://dify-api:5001\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Qdrant
|
|
if is_profile_active "qdrant"; then
|
|
SERVICES_ARRAY+=(" \"qdrant\": {
|
|
\"hostname\": \"$(json_escape "$QDRANT_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"api_key\": \"$(json_escape "$QDRANT_API_KEY")\"
|
|
},
|
|
\"extra\": {
|
|
\"dashboard\": \"https://$(json_escape "$QDRANT_HOSTNAME")/dashboard\",
|
|
\"internal_api\": \"http://qdrant:6333\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Weaviate
|
|
if is_profile_active "weaviate"; then
|
|
SERVICES_ARRAY+=(" \"weaviate\": {
|
|
\"hostname\": \"$(json_escape "$WEAVIATE_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"api_key\": \"$(json_escape "$WEAVIATE_API_KEY")\",
|
|
\"username\": \"$(json_escape "$WEAVIATE_USERNAME")\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Neo4j
|
|
if is_profile_active "neo4j"; then
|
|
SERVICES_ARRAY+=(" \"neo4j\": {
|
|
\"hostname\": \"$(json_escape "$NEO4J_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"username\": \"$(json_escape "$NEO4J_AUTH_USERNAME")\",
|
|
\"password\": \"$(json_escape "$NEO4J_AUTH_PASSWORD")\"
|
|
},
|
|
\"extra\": {
|
|
\"bolt_port\": \"7687\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# NocoDB
|
|
if is_profile_active "nocodb"; then
|
|
SERVICES_ARRAY+=(" \"nocodb\": {
|
|
\"hostname\": \"$(json_escape "$NOCODB_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"note\": \"Create your account on first login\",
|
|
\"user_token\": \"$(json_escape "$NOCODB_JWT_SECRET")\"
|
|
},
|
|
\"extra\": {
|
|
\"internal_api\": \"http://nocodb:8080\",
|
|
\"docs\": \"https://docs.nocodb.com\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# SearXNG
|
|
if is_profile_active "searxng"; then
|
|
SERVICES_ARRAY+=(" \"searxng\": {
|
|
\"hostname\": \"$(json_escape "$SEARXNG_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"username\": \"$(json_escape "$SEARXNG_USERNAME")\",
|
|
\"password\": \"$(json_escape "$SEARXNG_PASSWORD")\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# RAGApp
|
|
if is_profile_active "ragapp"; then
|
|
SERVICES_ARRAY+=(" \"ragapp\": {
|
|
\"hostname\": \"$(json_escape "$RAGAPP_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"username\": \"$(json_escape "$RAGAPP_USERNAME")\",
|
|
\"password\": \"$(json_escape "$RAGAPP_PASSWORD")\"
|
|
},
|
|
\"extra\": {
|
|
\"admin\": \"https://$(json_escape "$RAGAPP_HOSTNAME")/admin\",
|
|
\"docs\": \"https://$(json_escape "$RAGAPP_HOSTNAME")/docs\",
|
|
\"internal_api\": \"http://ragapp:8000\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# RAGFlow
|
|
if is_profile_active "ragflow"; then
|
|
SERVICES_ARRAY+=(" \"ragflow\": {
|
|
\"hostname\": \"$(json_escape "$RAGFLOW_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"note\": \"Create account on first login\"
|
|
},
|
|
\"extra\": {
|
|
\"internal_api\": \"http://ragflow:80\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# LightRAG
|
|
if is_profile_active "lightrag"; then
|
|
SERVICES_ARRAY+=(" \"lightrag\": {
|
|
\"hostname\": \"$(json_escape "$LIGHTRAG_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"username\": \"$(json_escape "$LIGHTRAG_USERNAME")\",
|
|
\"password\": \"$(json_escape "$LIGHTRAG_PASSWORD")\",
|
|
\"api_key\": \"$(json_escape "$LIGHTRAG_API_KEY")\"
|
|
},
|
|
\"extra\": {
|
|
\"docs\": \"https://$(json_escape "$LIGHTRAG_HOSTNAME")/docs\",
|
|
\"internal_api\": \"http://lightrag:9621\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Letta
|
|
if is_profile_active "letta"; then
|
|
SERVICES_ARRAY+=(" \"letta\": {
|
|
\"hostname\": \"$(json_escape "$LETTA_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"api_key\": \"$(json_escape "$LETTA_SERVER_PASSWORD")\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# ComfyUI
|
|
if is_profile_active "comfyui"; then
|
|
SERVICES_ARRAY+=(" \"comfyui\": {
|
|
\"hostname\": \"$(json_escape "$COMFYUI_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"username\": \"$(json_escape "$COMFYUI_USERNAME")\",
|
|
\"password\": \"$(json_escape "$COMFYUI_PASSWORD")\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# LibreTranslate
|
|
if is_profile_active "libretranslate"; then
|
|
SERVICES_ARRAY+=(" \"libretranslate\": {
|
|
\"hostname\": \"$(json_escape "$LT_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"username\": \"$(json_escape "$LT_USERNAME")\",
|
|
\"password\": \"$(json_escape "$LT_PASSWORD")\"
|
|
},
|
|
\"extra\": {
|
|
\"internal_api\": \"http://libretranslate:5000\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Docling
|
|
if is_profile_active "docling"; then
|
|
SERVICES_ARRAY+=(" \"docling\": {
|
|
\"hostname\": \"$(json_escape "$DOCLING_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"username\": \"$(json_escape "$DOCLING_USERNAME")\",
|
|
\"password\": \"$(json_escape "$DOCLING_PASSWORD")\"
|
|
},
|
|
\"extra\": {
|
|
\"ui\": \"https://$(json_escape "$DOCLING_HOSTNAME")/ui\",
|
|
\"docs\": \"https://$(json_escape "$DOCLING_HOSTNAME")/docs\",
|
|
\"internal_api\": \"http://docling:5001\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# PaddleOCR
|
|
if is_profile_active "paddleocr"; then
|
|
SERVICES_ARRAY+=(" \"paddleocr\": {
|
|
\"hostname\": \"$(json_escape "$PADDLEOCR_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"username\": \"$(json_escape "$PADDLEOCR_USERNAME")\",
|
|
\"password\": \"$(json_escape "$PADDLEOCR_PASSWORD")\"
|
|
},
|
|
\"extra\": {
|
|
\"internal_api\": \"http://paddleocr:8080\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Postiz
|
|
if is_profile_active "postiz"; then
|
|
SERVICES_ARRAY+=(" \"postiz\": {
|
|
\"hostname\": \"$(json_escape "$POSTIZ_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"note\": \"Create account on first login\"
|
|
},
|
|
\"extra\": {
|
|
\"internal_api\": \"http://postiz:5000\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# WAHA
|
|
if is_profile_active "waha"; then
|
|
SERVICES_ARRAY+=(" \"waha\": {
|
|
\"hostname\": \"$(json_escape "$WAHA_HOSTNAME")\",
|
|
\"credentials\": {
|
|
\"username\": \"$(json_escape "$WAHA_DASHBOARD_USERNAME")\",
|
|
\"password\": \"$(json_escape "$WAHA_DASHBOARD_PASSWORD")\",
|
|
\"api_key\": \"$(json_escape "$WAHA_API_KEY_PLAIN")\"
|
|
},
|
|
\"extra\": {
|
|
\"dashboard\": \"https://$(json_escape "$WAHA_HOSTNAME")/dashboard\",
|
|
\"swagger_user\": \"$(json_escape "$WHATSAPP_SWAGGER_USERNAME")\",
|
|
\"swagger_pass\": \"$(json_escape "$WHATSAPP_SWAGGER_PASSWORD")\",
|
|
\"internal_api\": \"http://waha:3000\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Crawl4AI (internal only)
|
|
if is_profile_active "crawl4ai"; then
|
|
SERVICES_ARRAY+=(" \"crawl4ai\": {
|
|
\"hostname\": null,
|
|
\"credentials\": {
|
|
\"note\": \"Internal service only\"
|
|
},
|
|
\"extra\": {
|
|
\"internal_api\": \"http://crawl4ai:11235\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Gotenberg (internal only)
|
|
if is_profile_active "gotenberg"; then
|
|
SERVICES_ARRAY+=(" \"gotenberg\": {
|
|
\"hostname\": null,
|
|
\"credentials\": {
|
|
\"note\": \"Internal service only\"
|
|
},
|
|
\"extra\": {
|
|
\"internal_api\": \"http://gotenberg:3000\",
|
|
\"docs\": \"https://gotenberg.dev/docs\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Ollama (internal only)
|
|
if is_profile_active "cpu" || is_profile_active "gpu-nvidia" || is_profile_active "gpu-amd"; then
|
|
SERVICES_ARRAY+=(" \"ollama\": {
|
|
\"hostname\": null,
|
|
\"credentials\": {
|
|
\"note\": \"Internal service only\"
|
|
},
|
|
\"extra\": {
|
|
\"internal_api\": \"http://ollama:11434\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Redis/Valkey (internal only, shown if n8n or langfuse active)
|
|
if is_profile_active "n8n" || is_profile_active "langfuse"; then
|
|
SERVICES_ARRAY+=(" \"redis\": {
|
|
\"hostname\": null,
|
|
\"credentials\": {
|
|
\"password\": \"$(json_escape "$REDIS_AUTH")\"
|
|
},
|
|
\"extra\": {
|
|
\"internal_url\": \"${REDIS_HOST:-redis}:${REDIS_PORT:-6379}\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# PostgreSQL (internal only, shown if n8n or langfuse active)
|
|
if is_profile_active "n8n" || is_profile_active "langfuse"; then
|
|
SERVICES_ARRAY+=(" \"postgres\": {
|
|
\"hostname\": null,
|
|
\"credentials\": {
|
|
\"username\": \"$(json_escape "${POSTGRES_USER:-postgres}")\",
|
|
\"password\": \"$(json_escape "$POSTGRES_PASSWORD")\"
|
|
},
|
|
\"extra\": {
|
|
\"internal_host\": \"postgres\",
|
|
\"internal_port\": \"${POSTGRES_PORT:-5432}\",
|
|
\"database\": \"$(json_escape "${POSTGRES_DB:-postgres}")\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Python Runner (internal only)
|
|
if is_profile_active "python-runner"; then
|
|
SERVICES_ARRAY+=(" \"python-runner\": {
|
|
\"hostname\": null,
|
|
\"credentials\": {
|
|
\"note\": \"Mount: ./python-runner → /app\\nEntry: /app/main.py\\nLogs: make logs s=python-runner\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Cloudflare Tunnel
|
|
if is_profile_active "cloudflare-tunnel"; then
|
|
SERVICES_ARRAY+=(" \"cloudflare-tunnel\": {
|
|
\"hostname\": null,
|
|
\"credentials\": {
|
|
\"note\": \"Zero-trust access via Cloudflare network\"
|
|
},
|
|
\"extra\": {
|
|
\"recommendation\": \"Close ports 80, 443, 7687 in your VPS firewall after confirming tunnel connectivity\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Gost Proxy (internal only)
|
|
if is_profile_active "gost"; then
|
|
SERVICES_ARRAY+=(" \"gost\": {
|
|
\"hostname\": null,
|
|
\"credentials\": {
|
|
\"username\": \"$(json_escape "$GOST_USERNAME")\",
|
|
\"password\": \"$(json_escape "$GOST_PASSWORD")\"
|
|
},
|
|
\"extra\": {
|
|
\"note\": \"Routes AI traffic through external proxy for geo-bypass\",
|
|
\"proxy_url\": \"$(json_escape "$GOST_PROXY_URL")\",
|
|
\"upstream_proxy\": \"$(json_escape "$GOST_UPSTREAM_PROXY")\",
|
|
\"internal_api\": \"http://gost:8080\"
|
|
}
|
|
}")
|
|
fi
|
|
|
|
# Join array with commas and newlines
|
|
SERVICES_JSON=""
|
|
for i in "${!SERVICES_ARRAY[@]}"; do
|
|
if [ $i -gt 0 ]; then
|
|
SERVICES_JSON+=",
|
|
"
|
|
fi
|
|
SERVICES_JSON+="${SERVICES_ARRAY[$i]}"
|
|
done
|
|
|
|
# Build quick_start array based on active profiles
|
|
declare -a QUICK_START_ARRAY
|
|
STEP_NUM=1
|
|
|
|
# Step 1: Log into primary service (n8n or Flowise)
|
|
if is_profile_active "n8n"; then
|
|
QUICK_START_ARRAY+=(" {
|
|
\"step\": $STEP_NUM,
|
|
\"title\": \"Log into n8n\",
|
|
\"description\": \"Create your account on first login\"
|
|
}")
|
|
((STEP_NUM++))
|
|
elif is_profile_active "flowise"; then
|
|
QUICK_START_ARRAY+=(" {
|
|
\"step\": $STEP_NUM,
|
|
\"title\": \"Log into Flowise\",
|
|
\"description\": \"Create your account on first login\"
|
|
}")
|
|
((STEP_NUM++))
|
|
fi
|
|
|
|
# Step 2: Create first workflow (if n8n active)
|
|
if is_profile_active "n8n"; then
|
|
QUICK_START_ARRAY+=(" {
|
|
\"step\": $STEP_NUM,
|
|
\"title\": \"Create your first workflow\",
|
|
\"description\": \"Start with Manual Trigger + HTTP Request nodes\"
|
|
}")
|
|
((STEP_NUM++))
|
|
fi
|
|
|
|
# Step 3: Configure database backups (if databasus active)
|
|
if is_profile_active "databasus"; then
|
|
QUICK_START_ARRAY+=(" {
|
|
\"step\": $STEP_NUM,
|
|
\"title\": \"Configure database backups\",
|
|
\"description\": \"Set up Databasus for automated database backups\"
|
|
}")
|
|
((STEP_NUM++))
|
|
fi
|
|
|
|
# Step 4: Monitor system (if monitoring active)
|
|
if is_profile_active "monitoring"; then
|
|
QUICK_START_ARRAY+=(" {
|
|
\"step\": $STEP_NUM,
|
|
\"title\": \"Monitor your system\",
|
|
\"description\": \"Use Grafana to track performance metrics\"
|
|
}")
|
|
((STEP_NUM++))
|
|
fi
|
|
|
|
# Join quick_start array
|
|
QUICK_START_JSON=""
|
|
for i in "${!QUICK_START_ARRAY[@]}"; do
|
|
if [ $i -gt 0 ]; then
|
|
QUICK_START_JSON+=",
|
|
"
|
|
fi
|
|
QUICK_START_JSON+="${QUICK_START_ARRAY[$i]}"
|
|
done
|
|
|
|
# Write final JSON with proper formatting
|
|
cat > "$OUTPUT_FILE" << EOF
|
|
{
|
|
"domain": "$(json_escape "$USER_DOMAIN_NAME")",
|
|
"generated_at": "$GENERATED_AT",
|
|
"services": {
|
|
$SERVICES_JSON
|
|
},
|
|
"quick_start": [
|
|
$QUICK_START_JSON
|
|
]
|
|
}
|
|
EOF
|
|
|
|
log_success "Welcome page data generated at: $OUTPUT_FILE"
|
|
log_info "Access it at: https://${WELCOME_HOSTNAME:-welcome.${USER_DOMAIN_NAME}}"
|