Schritt7-3
This commit is contained in:
124
install.sh
124
install.sh
@@ -183,60 +183,88 @@ fi
|
||||
|
||||
info "Step 6 OK: Docker + Compose Plugin installiert, Locales gesetzt, Basis-Verzeichnisse erstellt"
|
||||
info "Next: Schritt 7 (finales docker-compose + Secrets + n8n/supabase up + Healthchecks)"
|
||||
# ===== Step 7: Compose + Secrets + Start =====
|
||||
step "7" "Deploy docker-compose + generate secrets + start stack"
|
||||
|
||||
# Annahmen:
|
||||
# - CTID ist in $CTID
|
||||
# - Hostname ist in $CT_HOSTNAME (z.B. supabase$(date +%s))
|
||||
# - Domain: zq0.de -> ergibt FQDN
|
||||
N8N_FQDN="${CT_HOSTNAME}.zq0.de"
|
||||
|
||||
POSTGRES_PASSWORD="$(rand_alnum 32)"
|
||||
DASHBOARD_USERNAME="$(rand_alnum 12)"
|
||||
DASHBOARD_PASSWORD="$(rand_alnum 24)"
|
||||
N8N_ENCRYPTION_KEY="$(rand_hex 64)"
|
||||
# ---------------------------
|
||||
# Step 7: Finalize stack + secrets + up + checks
|
||||
# ---------------------------
|
||||
info "Step 7: Stack finalisieren + Secrets + Up + Checks"
|
||||
|
||||
# Dateien in den CT kopieren
|
||||
pct push "$CTID" "${SCRIPT_DIR}/templates/docker-compose.yml" "/opt/customer-stack/docker-compose.yml" --perms 0644
|
||||
pct push "$CTID" "${SCRIPT_DIR}/sql/init_pgvector.sql" "/opt/customer-stack/sql/init_pgvector.sql" --perms 0644
|
||||
# ---- Host/IP für URL bauen
|
||||
# Wenn du später Reverse Proxy nutzt, werden diese Werte angepasst.
|
||||
STACK_DIR="/opt/customer-stack"
|
||||
|
||||
# .env im CT erstellen
|
||||
pct exec "$CTID" -- bash -lc "cat > /opt/customer-stack/.env <<'EOF'
|
||||
TZ=Europe/Berlin
|
||||
N8N_HOST=${N8N_FQDN}
|
||||
N8N_EDITOR_BASE_URL=https://${N8N_FQDN}/
|
||||
WEBHOOK_URL=https://${N8N_FQDN}/
|
||||
N8N_PORT="5678"
|
||||
N8N_PROTOCOL="http"
|
||||
N8N_HOST="${CT_IP}"
|
||||
N8N_EDITOR_BASE_URL="${N8N_PROTOCOL}://${N8N_HOST}:${N8N_PORT}/"
|
||||
WEBHOOK_URL="${N8N_EDITOR_BASE_URL}"
|
||||
|
||||
DASHBOARD_USERNAME=${DASHBOARD_USERNAME}
|
||||
DASHBOARD_PASSWORD=${DASHBOARD_PASSWORD}
|
||||
|
||||
N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
|
||||
|
||||
POSTGRES_USER=postgres
|
||||
POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
POSTGRES_DB=postgres
|
||||
# ---- Secrets generieren (einmalig pro CT)
|
||||
# Wichtig: nicht jedes Mal neu erzeugen, sonst ist n8n "kaputt" (encryption key ändert sich)
|
||||
pct_exec "${CTID}" "test -f ${STACK_DIR}/.env || ( \
|
||||
umask 077; \
|
||||
PG_DB='n8n'; \
|
||||
PG_USER='n8n'; \
|
||||
PG_PASSWORD=\"\$(tr -dc 'A-Za-z0-9' </dev/urandom | head -c 32)\"; \
|
||||
N8N_ENCRYPTION_KEY=\"\$(tr -dc 'A-Za-z0-9' </dev/urandom | head -c 32)\"; \
|
||||
N8N_SECURE_COOKIE='false'; \
|
||||
N8N_PORT='${N8N_PORT}'; \
|
||||
N8N_PROTOCOL='${N8N_PROTOCOL}'; \
|
||||
N8N_HOST='${N8N_HOST}'; \
|
||||
N8N_EDITOR_BASE_URL='${N8N_EDITOR_BASE_URL}'; \
|
||||
WEBHOOK_URL='${WEBHOOK_URL}'; \
|
||||
cat > ${STACK_DIR}/.env <<EOF
|
||||
PG_DB=\${PG_DB}
|
||||
PG_USER=\${PG_USER}
|
||||
PG_PASSWORD=\${PG_PASSWORD}
|
||||
N8N_ENCRYPTION_KEY=\${N8N_ENCRYPTION_KEY}
|
||||
N8N_SECURE_COOKIE=\${N8N_SECURE_COOKIE}
|
||||
N8N_PORT=\${N8N_PORT}
|
||||
N8N_PROTOCOL=\${N8N_PROTOCOL}
|
||||
N8N_HOST=\${N8N_HOST}
|
||||
N8N_EDITOR_BASE_URL=\${N8N_EDITOR_BASE_URL}
|
||||
WEBHOOK_URL=\${WEBHOOK_URL}
|
||||
EOF
|
||||
chmod 600 /opt/customer-stack/.env"
|
||||
)"
|
||||
|
||||
# Stack hochfahren
|
||||
pct exec "$CTID" -- bash -lc "cd /opt/customer-stack && docker compose up -d"
|
||||
# ---- Dateien rüberkopieren (compose + sql)
|
||||
# docker-compose.yml
|
||||
if [[ -f "${SCRIPT_DIR}/templates/docker-compose.yml" ]]; then
|
||||
COMPOSE_CONTENT="$(cat "${SCRIPT_DIR}/templates/docker-compose.yml")"
|
||||
pct exec "${CTID}" -- bash -lc "cat > ${STACK_DIR}/docker-compose.yml <<'YML'
|
||||
${COMPOSE_CONTENT}
|
||||
YML"
|
||||
else
|
||||
die "Missing template: ${SCRIPT_DIR}/templates/docker-compose.yml"
|
||||
fi
|
||||
|
||||
# Warten bis n8n antwortet
|
||||
pct exec "$CTID" -- bash -lc '
|
||||
set -e
|
||||
for i in $(seq 1 60); do
|
||||
if curl -fsS http://127.0.0.1:5678/ >/dev/null; then
|
||||
echo "[INFO] n8n is up"
|
||||
exit 0
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
echo "[ERROR] n8n did not become ready in time" >&2
|
||||
exit 1
|
||||
'
|
||||
# sql init
|
||||
pct_exec "${CTID}" "mkdir -p ${STACK_DIR}/sql"
|
||||
if [[ -f "${SCRIPT_DIR}/sql/init_pgvector.sql" ]]; then
|
||||
SQL_CONTENT="$(cat "${SCRIPT_DIR}/sql/init_pgvector.sql")"
|
||||
pct exec "${CTID}" -- bash -lc "cat > ${STACK_DIR}/sql/init_pgvector.sql <<'SQL'
|
||||
${SQL_CONTENT}
|
||||
SQL"
|
||||
else
|
||||
die "Missing sql file: ${SCRIPT_DIR}/sql/init_pgvector.sql"
|
||||
fi
|
||||
|
||||
log_info "Step 7 OK: Stack running"
|
||||
log_info "URL: https://${N8N_FQDN}"
|
||||
log_info "BasicAuth user: ${DASHBOARD_USERNAME}"
|
||||
log_info "BasicAuth pass: ${DASHBOARD_PASSWORD}"
|
||||
# ---- Volumes + Rechte (wichtig!)
|
||||
pct_exec "${CTID}" "mkdir -p ${STACK_DIR}/volumes/n8n-data ${STACK_DIR}/volumes/postgres/data"
|
||||
# n8n läuft als node (uid 1000), postgres i.d.R. uid 999
|
||||
pct_exec "${CTID}" "chown -R 1000:1000 ${STACK_DIR}/volumes/n8n-data"
|
||||
pct_exec "${CTID}" "chown -R 999:999 ${STACK_DIR}/volumes/postgres/data"
|
||||
|
||||
# ---- Start stack
|
||||
pct_exec "${CTID}" "cd ${STACK_DIR} && docker compose pull"
|
||||
pct_exec "${CTID}" "cd ${STACK_DIR} && docker compose up -d"
|
||||
|
||||
# ---- Minimal Checks
|
||||
pct_exec "${CTID}" "cd ${STACK_DIR} && docker compose ps"
|
||||
pct_exec "${CTID}" "cd ${STACK_DIR} && docker logs --tail=30 customer-postgres || true"
|
||||
pct_exec "${CTID}" "cd ${STACK_DIR} && docker logs --tail=30 n8n || true"
|
||||
|
||||
info "Step 7 OK: Stack deployed"
|
||||
info "n8n: ${N8N_EDITOR_BASE_URL}"
|
||||
info "Hinweis: Ohne Reverse-Proxy/TLS ist N8N_SECURE_COOKIE=false gesetzt. Später bei HTTPS wieder true."
|
||||
|
||||
@@ -1,35 +1,2 @@
|
||||
-- Wird beim ersten Start des Containers automatisch ausgeführt
|
||||
-- (liegt in /docker-entrypoint-initdb.d/)
|
||||
--
|
||||
-- Zweck:
|
||||
-- - DBs anlegen: n8n, vectors
|
||||
-- - pgvector Extension in beiden DBs aktivieren
|
||||
-- - optional Schema vec in vectors vorbereiten
|
||||
|
||||
\connect postgres
|
||||
|
||||
-- Datenbanken anlegen (idempotent)
|
||||
SELECT 'CREATE DATABASE n8n'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = 'n8n') \gexec;
|
||||
|
||||
SELECT 'CREATE DATABASE vectors'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = 'vectors') \gexec;
|
||||
|
||||
-- pgvector in n8n aktivieren (schadet nicht, hilft evtl. später)
|
||||
\connect n8n
|
||||
CREATE EXTENSION IF NOT EXISTS vector;
|
||||
|
||||
-- pgvector in vectors aktivieren
|
||||
\connect vectors
|
||||
CREATE EXTENSION IF NOT EXISTS vector;
|
||||
|
||||
-- Optional: Schema vorbereiten
|
||||
CREATE SCHEMA IF NOT EXISTS vec;
|
||||
|
||||
-- Optional: Beispiel-Tabelle (Dimension an Embeddings anpassen, z.B. 768 / 1024 / 1536)
|
||||
-- CREATE TABLE IF NOT EXISTS vec.documents (
|
||||
-- id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
-- content text,
|
||||
-- metadata jsonb,
|
||||
-- embedding vector(1536)
|
||||
-- );
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||
|
||||
@@ -1,81 +1,63 @@
|
||||
services:
|
||||
db:
|
||||
postgres:
|
||||
image: pgvector/pgvector:pg16
|
||||
container_name: customer-db
|
||||
container_name: customer-postgres
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
POSTGRES_DB: ${POSTGRES_DB}
|
||||
TZ: ${TZ:-Europe/Berlin}
|
||||
POSTGRES_DB: ${PG_DB}
|
||||
POSTGRES_USER: ${PG_USER}
|
||||
POSTGRES_PASSWORD: ${PG_PASSWORD}
|
||||
volumes:
|
||||
- db_data:/var/lib/postgresql/data
|
||||
- ./sql/init_pgvector.sql:/docker-entrypoint-initdb.d/10-init_pgvector.sql:ro
|
||||
networks:
|
||||
- internal
|
||||
- ./volumes/postgres/data:/var/lib/postgresql/data
|
||||
- ./sql:/docker-entrypoint-initdb.d:ro
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB} -h 127.0.0.1"]
|
||||
test: ["CMD-SHELL", "pg_isready -U ${PG_USER} -d ${PG_DB} || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 12
|
||||
retries: 20
|
||||
networks:
|
||||
- customer-net
|
||||
|
||||
n8n:
|
||||
image: n8nio/n8n:latest
|
||||
container_name: n8n
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
db:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
ports:
|
||||
- "5678:5678"
|
||||
- "${N8N_PORT}:5678"
|
||||
environment:
|
||||
TZ: ${TZ:-Europe/Berlin}
|
||||
|
||||
# --- n8n core ---
|
||||
N8N_HOST: ${N8N_HOST}
|
||||
# --- Web / Cookies / URL ---
|
||||
N8N_PORT: 5678
|
||||
N8N_PROTOCOL: https
|
||||
N8N_PATH: /
|
||||
N8N_PROTOCOL: ${N8N_PROTOCOL}
|
||||
N8N_HOST: ${N8N_HOST}
|
||||
N8N_EDITOR_BASE_URL: ${N8N_EDITOR_BASE_URL}
|
||||
WEBHOOK_URL: ${WEBHOOK_URL}
|
||||
|
||||
# Reverse-Proxy Betrieb (OPNsense davor)
|
||||
N8N_PROXY_HOPS: 1
|
||||
N8N_SECURE_COOKIE: true
|
||||
# Ohne TLS/Reverse Proxy: sonst Secure-Cookie Warning / Login-Probleme
|
||||
N8N_SECURE_COOKIE: ${N8N_SECURE_COOKIE}
|
||||
|
||||
# Optionaler Basisschutz via BasicAuth
|
||||
N8N_BASIC_AUTH_ACTIVE: "true"
|
||||
N8N_BASIC_AUTH_USER: ${DASHBOARD_USERNAME}
|
||||
N8N_BASIC_AUTH_PASSWORD: ${DASHBOARD_PASSWORD}
|
||||
# --- DB (Postgres) ---
|
||||
DB_TYPE: postgresdb
|
||||
DB_POSTGRESDB_HOST: postgres
|
||||
DB_POSTGRESDB_PORT: 5432
|
||||
DB_POSTGRESDB_DATABASE: ${PG_DB}
|
||||
DB_POSTGRESDB_USER: ${PG_USER}
|
||||
DB_POSTGRESDB_PASSWORD: ${PG_PASSWORD}
|
||||
|
||||
# Verschlüsselung für Credentials
|
||||
# --- Basics ---
|
||||
GENERIC_TIMEZONE: Europe/Berlin
|
||||
TZ: Europe/Berlin
|
||||
|
||||
# optional (später hart machen)
|
||||
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
|
||||
|
||||
# --- DB für n8n ---
|
||||
DB_TYPE: postgresdb
|
||||
DB_POSTGRESDB_HOST: db
|
||||
DB_POSTGRESDB_PORT: 5432
|
||||
DB_POSTGRESDB_DATABASE: n8n
|
||||
DB_POSTGRESDB_USER: ${POSTGRES_USER}
|
||||
DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
|
||||
# Qualität-of-life
|
||||
GENERIC_TIMEZONE: ${TZ:-Europe/Berlin}
|
||||
|
||||
volumes:
|
||||
- n8n_data:/home/node/.n8n
|
||||
- ./volumes/n8n-data:/home/node/.n8n
|
||||
networks:
|
||||
- internal
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:5678/ >/dev/null 2>&1 || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 20
|
||||
- customer-net
|
||||
|
||||
networks:
|
||||
internal:
|
||||
customer-net:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
db_data:
|
||||
n8n_data:
|
||||
|
||||
Reference in New Issue
Block a user