Files
customer-installer/n8n_setup.sh
2026-01-18 17:05:15 +01:00

358 lines
11 KiB
Bash
Executable File

#!/bin/bash
#
# n8n Owner Account Setup Script
# Erstellt den Owner-Account bei einer neuen n8n-Instanz
# Oder prüft den Status einer bereits eingerichteten Instanz
# Ausgabe im JSON-Format
#
# NICHT set -e verwenden, da wir Fehler selbst behandeln
# Standardwerte
owner_first_name="Admin"
owner_last_name="User"
timeout=10
# JSON Steps Array
json_steps=()
# Funktion: Step zum JSON hinzufügen
add_step() {
local step_name="$1"
local step_status="$2"
local step_message="$3"
# Escape quotes in message
step_message=$(echo "$step_message" | sed 's/"/\\"/g')
json_steps+=("{\"step\":\"$step_name\",\"status\":\"$step_status\",\"message\":\"$step_message\"}")
}
# Funktion: JSON-Ausgabe generieren
output_json() {
local success="$1"
local message="$2"
local action="$3"
local login_status="$4"
local login_message="$5"
# Escape quotes
message=$(echo "$message" | sed 's/"/\\"/g')
login_message=$(echo "$login_message" | sed 's/"/\\"/g')
# Steps Array zusammenbauen
local steps_json=""
for i in "${!json_steps[@]}"; do
if [[ $i -gt 0 ]]; then
steps_json+=","
fi
steps_json+="${json_steps[$i]}"
done
# Zeitstempel
local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# JSON ausgeben
cat << JSONEOF
{
"success": $success,
"timestamp": "$timestamp",
"message": "$message",
"action": "$action",
"config": {
"n8n_url": "$n8n_internal",
"owner_email": "$owner_email",
"owner_first_name": "$owner_first_name",
"owner_last_name": "$owner_last_name"
},
"login_test": {
"status": "$login_status",
"message": "$login_message"
},
"steps": [$steps_json]
}
JSONEOF
}
# Funktion: Fehler-Exit mit JSON
exit_error() {
local message="$1"
local error="$2"
output_json "false" "$message" "error" "not_tested" "$error"
exit 1
}
# Funktion: Login testen
test_login() {
local url="$1"
local email="$2"
local password="$3"
# Login-Request durchführen
local login_response
login_response=$(curl -s -w "\n%{http_code}" --connect-timeout "$timeout" \
-X POST "${url}/rest/login" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d "{\"email\":\"${email}\",\"password\":\"${password}\"}" 2>/dev/null)
local curl_exit=$?
if [[ $curl_exit -ne 0 ]]; then
echo "error|Verbindungsfehler beim Login-Test"
return 1
fi
local http_code=$(echo "$login_response" | tail -n1)
local body=$(echo "$login_response" | sed '$d')
if [[ "$http_code" == "200" ]]; then
if echo "$body" | grep -q '"id"'; then
echo "success|Login erfolgreich - Authentifizierung bestätigt"
return 0
else
echo "success|Login-Endpoint erreichbar (HTTP 200)"
return 0
fi
elif [[ "$http_code" == "401" ]]; then
echo "failed|Authentifizierung fehlgeschlagen - Falsche Zugangsdaten"
return 1
elif [[ "$http_code" == "400" ]]; then
echo "failed|Ungueltige Anfrage"
return 1
else
echo "error|Unerwarteter Status: HTTP $http_code"
return 1
fi
}
# Funktion: Port-Test
test_port() {
local host="$1"
local port="$2"
local timeout_sec="$3"
# Versuche verschiedene Methoden
if command -v nc &> /dev/null; then
nc -z -w "$timeout_sec" "$host" "$port" 2>/dev/null
return $?
elif command -v timeout &> /dev/null; then
timeout "$timeout_sec" bash -c "echo >/dev/tcp/$host/$port" 2>/dev/null
return $?
else
# Fallback: curl
curl -s --connect-timeout "$timeout_sec" "http://$host:$port" &>/dev/null
# Auch wenn curl fehlschlägt, war der Port erreichbar wenn kein Connection refused
return 0
fi
}
# Hilfe anzeigen
show_help() {
cat << EOF
Verwendung: $0 [OPTIONEN]
n8n Owner Account Setup Script (JSON-Ausgabe)
Optionen:
--n8n_internal <url> n8n URL (z.B. http://192.168.1.100:5678)
--owner_email <email> E-Mail-Adresse für den Owner-Account
--owner_password <pass> Passwort für den Owner-Account (min. 8 Zeichen)
--owner_first_name <name> Vorname des Owners (Standard: Admin)
--owner_last_name <name> Nachname des Owners (Standard: User)
--timeout <sekunden> Timeout für Requests (Standard: 10)
-h, --help Diese Hilfe anzeigen
EOF
exit 0
}
# ============================================
# Parameter parsen
# ============================================
while [[ $# -gt 0 ]]; do
case $1 in
--n8n_internal)
n8n_internal="$2"
shift 2
;;
--owner_email)
owner_email="$2"
shift 2
;;
--owner_password)
owner_password="$2"
shift 2
;;
--owner_first_name)
owner_first_name="$2"
shift 2
;;
--owner_last_name)
owner_last_name="$2"
shift 2
;;
--timeout)
timeout="$2"
shift 2
;;
-h|--help)
show_help
;;
*)
exit_error "Unbekannter Parameter" "$1"
;;
esac
done
# ============================================
# Pflichtparameter prüfen
# ============================================
if [[ -z "$n8n_internal" ]]; then
exit_error "Parameter fehlt" "--n8n_internal ist erforderlich"
fi
if [[ -z "$owner_email" ]]; then
exit_error "Parameter fehlt" "--owner_email ist erforderlich"
fi
if [[ -z "$owner_password" ]]; then
exit_error "Parameter fehlt" "--owner_password ist erforderlich"
fi
if [[ ${#owner_password} -lt 8 ]]; then
exit_error "Validierungsfehler" "Passwort muss mindestens 8 Zeichen lang sein"
fi
# URL normalisieren
n8n_internal="${n8n_internal%/}"
# ============================================
# Schritt 1: Server-Erreichbarkeit prüfen
# ============================================
# Host und Port extrahieren
host_port=$(echo "$n8n_internal" | sed -E 's|https?://||' | cut -d'/' -f1)
host=$(echo "$host_port" | cut -d':' -f1)
port=$(echo "$host_port" | grep -oE ':[0-9]+' | tr -d ':')
if [[ -z "$port" ]]; then
if [[ "$n8n_internal" == https://* ]]; then
port=443
else
port=80
fi
fi
# Ping-Test (optional, nicht kritisch)
if ping -c 1 -W 2 "$host" &> /dev/null; then
add_step "ping_test" "success" "Host $host antwortet auf Ping"
else
add_step "ping_test" "warning" "Host antwortet nicht auf Ping (ICMP blockiert)"
fi
# Port-Test
if test_port "$host" "$port" "$timeout"; then
add_step "port_test" "success" "Port $port ist offen"
else
add_step "port_test" "error" "Port $port ist nicht erreichbar"
exit_error "Server nicht erreichbar" "Port $port ist nicht erreichbar auf $host"
fi
# HTTP-Health-Check
http_status=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout "$timeout" "$n8n_internal/healthz" 2>/dev/null || echo "000")
if [[ "$http_status" == "200" ]]; then
add_step "health_check" "success" "n8n Health-Check erfolgreich (HTTP $http_status)"
elif [[ "$http_status" == "000" ]]; then
add_step "health_check" "error" "Keine HTTP-Verbindung moeglich"
exit_error "Health-Check fehlgeschlagen" "Keine HTTP-Verbindung moeglich"
else
add_step "health_check" "warning" "Health-Endpoint antwortet mit HTTP $http_status"
fi
# ============================================
# Schritt 2: Setup-Status prüfen
# ============================================
setup_check=$(curl -s --connect-timeout "$timeout" "$n8n_internal/rest/settings" 2>/dev/null || echo "")
setup_already_done=false
if echo "$setup_check" | grep -q '"showSetupOnFirstLoad":false'; then
setup_already_done=true
add_step "setup_check" "info" "Setup bereits abgeschlossen - Owner existiert"
else
add_step "setup_check" "success" "Setup ist verfuegbar"
fi
# ============================================
# Schritt 3: Owner erstellen ODER Login testen
# ============================================
if [[ "$setup_already_done" == "false" ]]; then
# Setup noch nicht durchgeführt -> Owner erstellen
response=$(curl -s -w "\n%{http_code}" --connect-timeout "$timeout" \
-X POST "${n8n_internal}/rest/owner/setup" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d "{\"email\":\"${owner_email}\",\"password\":\"${owner_password}\",\"firstName\":\"${owner_first_name}\",\"lastName\":\"${owner_last_name}\"}" 2>/dev/null || echo -e "\n000")
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')
if [[ "$http_code" == "200" ]] || [[ "$http_code" == "201" ]]; then
add_step "create_owner" "success" "Owner-Account erfolgreich erstellt"
# Kurz warten
sleep 2
# Login testen nach Erstellung
login_result=$(test_login "$n8n_internal" "$owner_email" "$owner_password")
login_status=$(echo "$login_result" | cut -d'|' -f1)
login_message=$(echo "$login_result" | cut -d'|' -f2)
if [[ "$login_status" == "success" ]]; then
add_step "login_test" "success" "$login_message"
output_json "true" "Owner-Account erfolgreich erstellt und Login verifiziert" "created" "$login_status" "$login_message"
exit 0
else
add_step "login_test" "warning" "$login_message"
output_json "true" "Owner-Account erstellt, Login-Test fehlgeschlagen" "created" "$login_status" "$login_message"
exit 0
fi
else
add_step "create_owner" "error" "Fehler beim Erstellen (HTTP $http_code)"
exit_error "Account-Erstellung fehlgeschlagen" "HTTP Status: $http_code"
fi
else
# Setup bereits abgeschlossen -> Login testen
add_step "action" "info" "Teste Login mit vorhandenen Zugangsdaten"
# Login-Seite prüfen
main_page=$(curl -s -L --connect-timeout "$timeout" "$n8n_internal/" 2>/dev/null || echo "")
if echo "$main_page" | grep -qi "sign.in\|login\|anmelden\|n8n"; then
add_step "login_page" "success" "Login-Seite ist erreichbar"
else
add_step "login_page" "warning" "Login-Seite nicht eindeutig erkannt"
fi
# Login durchführen
login_result=$(test_login "$n8n_internal" "$owner_email" "$owner_password")
login_status=$(echo "$login_result" | cut -d'|' -f1)
login_message=$(echo "$login_result" | cut -d'|' -f2)
if [[ "$login_status" == "success" ]]; then
add_step "login_test" "success" "$login_message"
output_json "true" "n8n-Instanz ist eingerichtet und Login erfolgreich" "existing" "$login_status" "$login_message"
exit 0
else
add_step "login_test" "failed" "$login_message"
output_json "true" "n8n-Instanz ist eingerichtet, Login fehlgeschlagen" "existing" "$login_status" "$login_message"
exit 0
fi
fi