427 lines
13 KiB
Bash
427 lines
13 KiB
Bash
|
|
#!/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}" <<EOF
|
||
|
|
{
|
||
|
|
"lxc": {
|
||
|
|
"lxc_id": ${CTID},
|
||
|
|
"hostname": "${HOSTNAME}",
|
||
|
|
"ip": "${CONTAINER_IP}",
|
||
|
|
"cores": ${CORES},
|
||
|
|
"memory": ${MEMORY},
|
||
|
|
"disk": ${DISK}
|
||
|
|
},
|
||
|
|
"n8n": {
|
||
|
|
"url_internal": "http://${CONTAINER_IP}:5678",
|
||
|
|
"url_external": "http://${CONTAINER_IP}:5678",
|
||
|
|
"owner_email": "${N8N_OWNER_EMAIL}",
|
||
|
|
"owner_password": "${N8N_OWNER_PASSWORD}",
|
||
|
|
"encryption_key": "${N8N_ENCRYPTION_KEY}",
|
||
|
|
"webhook_base": "http://${CONTAINER_IP}:5678/webhook"
|
||
|
|
},
|
||
|
|
"postgresql": {
|
||
|
|
"host": "localhost",
|
||
|
|
"port": 5432,
|
||
|
|
"database": "botkonzept",
|
||
|
|
"user": "postgres",
|
||
|
|
"password": "${PG_PASSWORD}"
|
||
|
|
},
|
||
|
|
"workflows": {
|
||
|
|
"registration": "/opt/n8n/registration-workflow.json",
|
||
|
|
"trial_management": "/opt/n8n/trial-workflow.json"
|
||
|
|
},
|
||
|
|
"frontend": {
|
||
|
|
"test_url": "http://192.168.0.20:8000",
|
||
|
|
"webhook_url": "http://${CONTAINER_IP}:5678/webhook/botkonzept-registration"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
EOF
|
||
|
|
|
||
|
|
log_success "Credentials gespeichert: ${CREDENTIALS_FILE}"
|
||
|
|
|
||
|
|
# =====================================================
|
||
|
|
# Zusammenfassung
|
||
|
|
# =====================================================
|
||
|
|
echo ""
|
||
|
|
echo "=========================================="
|
||
|
|
echo " BotKonzept LXC Setup abgeschlossen! ✅"
|
||
|
|
echo "=========================================="
|
||
|
|
echo ""
|
||
|
|
echo "LXC Details:"
|
||
|
|
echo " CTID: ${CTID}"
|
||
|
|
echo " Hostname: ${HOSTNAME}"
|
||
|
|
echo " IP: ${CONTAINER_IP}"
|
||
|
|
echo ""
|
||
|
|
echo "n8n:"
|
||
|
|
echo " URL: http://${CONTAINER_IP}:5678"
|
||
|
|
echo " E-Mail: ${N8N_OWNER_EMAIL}"
|
||
|
|
echo " Passwort: ${N8N_OWNER_PASSWORD}"
|
||
|
|
echo ""
|
||
|
|
echo "PostgreSQL:"
|
||
|
|
echo " Host: localhost (im Container)"
|
||
|
|
echo " Database: botkonzept"
|
||
|
|
echo " User: postgres"
|
||
|
|
echo " Passwort: ${PG_PASSWORD}"
|
||
|
|
echo ""
|
||
|
|
echo "Nächste Schritte:"
|
||
|
|
echo " 1. n8n öffnen: http://${CONTAINER_IP}:5678"
|
||
|
|
echo " 2. Mit obigen Credentials einloggen"
|
||
|
|
echo " 3. Workflows importieren:"
|
||
|
|
echo " - /opt/n8n/registration-workflow.json"
|
||
|
|
echo " - /opt/n8n/trial-workflow.json"
|
||
|
|
echo " 4. Credentials in n8n erstellen (siehe QUICK_START.md)"
|
||
|
|
echo " 5. Workflows aktivieren"
|
||
|
|
echo " 6. Frontend Webhook-URL aktualisieren:"
|
||
|
|
echo " http://${CONTAINER_IP}:5678/webhook/botkonzept-registration"
|
||
|
|
echo ""
|
||
|
|
echo "Credentials-Datei: ${CREDENTIALS_FILE}"
|
||
|
|
echo "=========================================="
|