#!/usr/bin/env bash set -Eeuo pipefail # ===================================================== # BotKonzept LXC Setup Script # ===================================================== # Erstellt eine LXC (ID 5000) mit: # - n8n # - PostgreSQL + botkonzept Datenbank # - Alle benötigten Workflows # - Vorkonfigurierte Credentials # ===================================================== SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Konfiguration CTID=5010 HOSTNAME="botkonzept-n8n" CORES=4 MEMORY=8192 SWAP=2048 DISK=100 STORAGE="local-zfs" BRIDGE="vmbr0" VLAN=90 IP="dhcp" # Farben für Output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color log_info() { echo -e "${BLUE}[INFO]${NC} $*"; } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $*"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } log_error() { echo -e "${RED}[ERROR]${NC} $*"; exit 1; } # ===================================================== # Schritt 1: LXC erstellen # ===================================================== log_info "Schritt 1: Erstelle LXC ${CTID}..." # Prüfen ob LXC bereits existiert if pct status ${CTID} &>/dev/null; then log_warn "LXC ${CTID} existiert bereits. Soll sie gelöscht werden? (y/n)" read -r answer if [[ "$answer" == "y" ]]; then log_info "Stoppe und lösche LXC ${CTID}..." pct stop ${CTID} || true pct destroy ${CTID} else log_error "Abbruch. Bitte andere CTID wählen." fi fi # Debian 12 Template (bereits vorhanden) TEMPLATE="debian-12-standard_12.12-1_amd64.tar.zst" if [[ ! -f "/var/lib/vz/template/cache/${TEMPLATE}" ]]; then log_info "Lade Debian 12 Template herunter..." pveam download local ${TEMPLATE} || log_warn "Template-Download fehlgeschlagen, versuche fortzufahren..." fi log_info "Verwende Template: ${TEMPLATE}" # LXC erstellen log_info "Erstelle LXC Container..." pct create ${CTID} local:vztmpl/${TEMPLATE} \ --hostname ${HOSTNAME} \ --cores ${CORES} \ --memory ${MEMORY} \ --swap ${SWAP} \ --rootfs ${STORAGE}:${DISK} \ --net0 name=eth0,bridge=${BRIDGE},tag=${VLAN},ip=${IP} \ --features nesting=1 \ --unprivileged 1 \ --onboot 1 \ --start 1 log_success "LXC ${CTID} erstellt und gestartet" # Warten bis Container bereit ist log_info "Warte auf Container-Start..." sleep 10 # ===================================================== # Schritt 2: System aktualisieren # ===================================================== log_info "Schritt 2: System aktualisieren..." pct exec ${CTID} -- bash -c " apt-get update DEBIAN_FRONTEND=noninteractive apt-get upgrade -y DEBIAN_FRONTEND=noninteractive apt-get install -y \ curl \ wget \ git \ vim \ htop \ ca-certificates \ gnupg \ lsb-release \ postgresql \ postgresql-contrib \ build-essential \ postgresql-server-dev-15 " log_success "System aktualisiert" # ===================================================== # Schritt 2b: pgvector installieren # ===================================================== log_info "Schritt 2b: pgvector installieren..." pct exec ${CTID} -- bash -c " cd /tmp git clone --branch v0.7.4 https://github.com/pgvector/pgvector.git cd pgvector make make install cd / rm -rf /tmp/pgvector " log_success "pgvector installiert" # ===================================================== # Schritt 3: Docker installieren # ===================================================== log_info "Schritt 3: Docker installieren..." pct exec ${CTID} -- bash -c ' # Docker GPG Key install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg chmod a+r /etc/apt/keyrings/docker.gpg # Docker Repository echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null # Docker installieren apt-get update DEBIAN_FRONTEND=noninteractive apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin # Docker starten systemctl enable docker systemctl start docker ' log_success "Docker installiert" # ===================================================== # Schritt 4: PostgreSQL konfigurieren # ===================================================== log_info "Schritt 4: PostgreSQL konfigurieren..." # PostgreSQL Passwort generieren PG_PASSWORD=$(openssl rand -base64 32 | tr -d '/+=' | head -c 24) pct exec ${CTID} -- bash -c " # PostgreSQL starten systemctl enable postgresql systemctl start postgresql # Warten bis PostgreSQL bereit ist sleep 5 # Postgres Passwort setzen su - postgres -c \"psql -c \\\"ALTER USER postgres PASSWORD '${PG_PASSWORD}';\\\"\" # Datenbank erstellen su - postgres -c \"createdb botkonzept\" # pgvector Extension aktivieren su - postgres -c \"psql -d botkonzept -c 'CREATE EXTENSION IF NOT EXISTS vector;'\" su - postgres -c \"psql -d botkonzept -c 'CREATE EXTENSION IF NOT EXISTS \\\"uuid-ossp\\\";'\" " log_success "PostgreSQL konfiguriert (Passwort: ${PG_PASSWORD})" # ===================================================== # Schritt 5: Datenbank-Schema importieren # ===================================================== log_info "Schritt 5: Datenbank-Schema importieren..." # Schema-Datei in Container kopieren pct push ${CTID} "${SCRIPT_DIR}/sql/botkonzept_schema.sql" /tmp/botkonzept_schema.sql pct exec ${CTID} -- bash -c " su - postgres -c 'psql -d botkonzept < /tmp/botkonzept_schema.sql' rm /tmp/botkonzept_schema.sql " log_success "Datenbank-Schema importiert" # ===================================================== # Schritt 6: n8n installieren # ===================================================== log_info "Schritt 6: n8n installieren..." # n8n Encryption Key generieren N8N_ENCRYPTION_KEY=$(openssl rand -base64 32) # Docker Compose Datei erstellen pct exec ${CTID} -- bash -c " mkdir -p /opt/n8n cat > /opt/n8n/docker-compose.yml <<'COMPOSE_EOF' version: '3.8' services: n8n: image: n8nio/n8n:latest container_name: n8n restart: unless-stopped ports: - '5678:5678' environment: - N8N_HOST=0.0.0.0 - N8N_PORT=5678 - N8N_PROTOCOL=http - WEBHOOK_URL=http://botkonzept-n8n:5678/ - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY} - EXECUTIONS_DATA_SAVE_ON_ERROR=all - EXECUTIONS_DATA_SAVE_ON_SUCCESS=all - EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS=true - N8N_LOG_LEVEL=info - N8N_LOG_OUTPUT=console - DB_TYPE=postgresdb - DB_POSTGRESDB_HOST=localhost - DB_POSTGRESDB_PORT=5432 - DB_POSTGRESDB_DATABASE=botkonzept - DB_POSTGRESDB_USER=postgres - DB_POSTGRESDB_PASSWORD=${PG_PASSWORD} volumes: - n8n_data:/home/node/.n8n network_mode: host volumes: n8n_data: COMPOSE_EOF " # n8n starten pct exec ${CTID} -- bash -c " cd /opt/n8n docker compose up -d " log_success "n8n installiert und gestartet" # Warten bis n8n bereit ist log_info "Warte auf n8n-Start (30 Sekunden)..." sleep 30 # ===================================================== # Schritt 7: n8n Owner Account erstellen (robuste Methode) # ===================================================== log_info "Schritt 7: n8n Owner Account erstellen..." N8N_OWNER_EMAIL="admin@botkonzept.de" N8N_OWNER_PASSWORD=$(openssl rand -base64 16) N8N_OWNER_FIRSTNAME="BotKonzept" N8N_OWNER_LASTNAME="Admin" # Methode 1: Via CLI im Container (bevorzugt) log_info "Versuche Owner Account via CLI zu erstellen..." pct exec ${CTID} -- bash -c " cd /opt/n8n docker exec -u node n8n n8n user-management:reset \ --email '${N8N_OWNER_EMAIL}' \ --password '${N8N_OWNER_PASSWORD}' \ --firstName '${N8N_OWNER_FIRSTNAME}' \ --lastName '${N8N_OWNER_LASTNAME}' 2>&1 || echo 'CLI method failed, trying REST API...' " # Methode 2: Via REST API (Fallback) log_info "Versuche Owner Account via REST API zu erstellen..." sleep 5 pct exec ${CTID} -- bash -c " curl -sS -X POST 'http://127.0.0.1:5678/rest/owner/setup' \ -H 'Content-Type: application/json' \ -d '{ \"email\": \"${N8N_OWNER_EMAIL}\", \"firstName\": \"${N8N_OWNER_FIRSTNAME}\", \"lastName\": \"${N8N_OWNER_LASTNAME}\", \"password\": \"${N8N_OWNER_PASSWORD}\" }' 2>&1 || echo 'REST API method also failed - manual setup may be required' " log_success "n8n Owner Account Setup abgeschlossen (prüfen Sie die n8n UI)" # ===================================================== # Schritt 8: Workflows vorbereiten # ===================================================== log_info "Schritt 8: Workflows vorbereiten..." # Workflows in Container kopieren pct push ${CTID} "${SCRIPT_DIR}/BotKonzept-Customer-Registration-Workflow.json" /opt/n8n/registration-workflow.json pct push ${CTID} "${SCRIPT_DIR}/BotKonzept-Trial-Management-Workflow.json" /opt/n8n/trial-workflow.json log_success "Workflows kopiert nach /opt/n8n/" # ===================================================== # Schritt 9: Systemd Service für n8n # ===================================================== log_info "Schritt 9: Systemd Service erstellen..." pct exec ${CTID} -- bash -c " cat > /etc/systemd/system/n8n.service <<'SERVICE_EOF' [Unit] Description=n8n Workflow Automation After=docker.service postgresql.service Requires=docker.service postgresql.service [Service] Type=oneshot RemainAfterExit=yes WorkingDirectory=/opt/n8n ExecStart=/usr/bin/docker compose up -d ExecStop=/usr/bin/docker compose down Restart=on-failure [Install] WantedBy=multi-user.target SERVICE_EOF systemctl daemon-reload systemctl enable n8n.service " log_success "Systemd Service erstellt" # ===================================================== # Schritt 10: IP-Adresse ermitteln # ===================================================== log_info "Schritt 10: IP-Adresse ermitteln..." sleep 5 CONTAINER_IP=$(pct exec ${CTID} -- hostname -I | awk '{print $1}') log_success "Container IP: ${CONTAINER_IP}" # ===================================================== # Schritt 11: Credentials-Datei erstellen # ===================================================== log_info "Schritt 11: Credentials-Datei erstellen..." CREDENTIALS_FILE="${SCRIPT_DIR}/credentials/botkonzept-lxc-${CTID}.json" mkdir -p "${SCRIPT_DIR}/credentials" cat > "${CREDENTIALS_FILE}" <