feat: complete n8n stack setup
Docker Compose stack (n8n, PostgreSQL 16, Redis 7, 1 worker) with: - nginx local proxy on port 8088, YunoHost TLS termination config - helper scripts: backup/restore/import/export/update - .env.example, README with architecture, ops commands, to-do list Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
78aa8da747
commit
87cd005352
12 changed files with 586 additions and 2 deletions
48
scripts/backup-n8n.sh
Executable file
48
scripts/backup-n8n.sh
Executable file
|
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
COMPOSE="$ROOT/compose/docker-compose.yml"
|
||||
ENV="$ROOT/.env"
|
||||
BACKUP_DIR="$ROOT/backups"
|
||||
MAX_BACKUPS=2
|
||||
|
||||
# shellcheck source=/dev/null
|
||||
source "$ENV"
|
||||
|
||||
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
|
||||
TARGET="$BACKUP_DIR/backup_$TIMESTAMP"
|
||||
mkdir -p "$TARGET"
|
||||
|
||||
echo "[backup] Starte Backup → $TARGET"
|
||||
|
||||
# PostgreSQL dump
|
||||
echo "[backup] Datenbank-Dump..."
|
||||
docker compose -f "$COMPOSE" exec -T postgres \
|
||||
pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB" \
|
||||
> "$TARGET/postgres.sql"
|
||||
|
||||
# n8n data
|
||||
echo "[backup] n8n Datendirectory..."
|
||||
tar -czf "$TARGET/n8n-data.tar.gz" -C "$ROOT/data" n8n
|
||||
|
||||
# Compose-Konfiguration
|
||||
echo "[backup] Compose + .env..."
|
||||
cp "$COMPOSE" "$TARGET/docker-compose.yml"
|
||||
cp "$ENV" "$TARGET/.env"
|
||||
|
||||
echo "[backup] Backup abgeschlossen: $TARGET"
|
||||
|
||||
# Retention: nur die letzten MAX_BACKUPS behalten
|
||||
EXISTING=$(ls -dt "$BACKUP_DIR"/backup_* 2>/dev/null)
|
||||
COUNT=$(echo "$EXISTING" | wc -l)
|
||||
if [ "$COUNT" -gt "$MAX_BACKUPS" ]; then
|
||||
TO_DELETE=$(echo "$EXISTING" | tail -n +"$((MAX_BACKUPS + 1))")
|
||||
echo "[backup] Lösche alte Backups:"
|
||||
echo "$TO_DELETE"
|
||||
echo "$TO_DELETE" | xargs rm -rf
|
||||
fi
|
||||
|
||||
echo "[backup] Fertig. Aktuelle Backups:"
|
||||
ls -lht "$BACKUP_DIR"
|
||||
19
scripts/export-credentials.sh
Executable file
19
scripts/export-credentials.sh
Executable file
|
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
COMPOSE="$ROOT/compose/docker-compose.yml"
|
||||
|
||||
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
|
||||
OUTPUT_DIR="$ROOT/imports/credentials/export_$TIMESTAMP"
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
echo "[export-credentials] WARNUNG: Export enthält unverschlüsselte Credentials!"
|
||||
echo "[export-credentials] Exportiere → $OUTPUT_DIR"
|
||||
docker compose -f "$COMPOSE" exec n8n \
|
||||
n8n export:credentials --all --output="/imports/credentials/export_$TIMESTAMP/"
|
||||
|
||||
echo "[export-credentials] Fertig."
|
||||
echo "[export-credentials] WICHTIG: Export-Verzeichnis sichern und nach Gebrauch löschen!"
|
||||
ls -lh "$OUTPUT_DIR"
|
||||
17
scripts/export-workflows.sh
Executable file
17
scripts/export-workflows.sh
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
COMPOSE="$ROOT/compose/docker-compose.yml"
|
||||
|
||||
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
|
||||
OUTPUT_DIR="$ROOT/imports/workflows/export_$TIMESTAMP"
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
echo "[export-workflows] Exportiere alle Workflows → $OUTPUT_DIR"
|
||||
docker compose -f "$COMPOSE" exec n8n \
|
||||
n8n export:workflow --all --output="/imports/workflows/export_$TIMESTAMP/"
|
||||
|
||||
echo "[export-workflows] Fertig."
|
||||
ls -lh "$OUTPUT_DIR"
|
||||
24
scripts/import-credentials.sh
Executable file
24
scripts/import-credentials.sh
Executable file
|
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
COMPOSE="$ROOT/compose/docker-compose.yml"
|
||||
|
||||
if [ -z "${1:-}" ]; then
|
||||
echo "Verwendung: $0 <credentials.json>"
|
||||
echo "WARNUNG: Credentials-Exporte sind unverschlüsselt. Datei nach Import löschen!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SOURCE="$1"
|
||||
DEST="$ROOT/imports/credentials/$(basename "$SOURCE")"
|
||||
cp "$SOURCE" "$DEST"
|
||||
|
||||
echo "[import-credentials] Importiere: $(basename "$SOURCE")"
|
||||
echo "[import-credentials] WARNUNG: Diese Datei enthält unverschlüsselte Credentials!"
|
||||
docker compose -f "$COMPOSE" exec n8n \
|
||||
n8n import:credentials --input="/imports/credentials/$(basename "$SOURCE")"
|
||||
|
||||
echo "[import-credentials] Fertig."
|
||||
echo "[import-credentials] Empfehlung: Quelldatei jetzt löschen: rm '$SOURCE'"
|
||||
35
scripts/import-workflow.sh
Executable file
35
scripts/import-workflow.sh
Executable file
|
|
@ -0,0 +1,35 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
COMPOSE="$ROOT/compose/docker-compose.yml"
|
||||
|
||||
if [ -z "${1:-}" ]; then
|
||||
echo "Verwendung: $0 <workflow.json | verzeichnis/>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SOURCE="$1"
|
||||
|
||||
if [ -d "$SOURCE" ]; then
|
||||
# Verzeichnis: alle JSON-Dateien importieren
|
||||
echo "[import-workflow] Importiere alle Workflows aus: $SOURCE"
|
||||
for f in "$SOURCE"/*.json; do
|
||||
[ -f "$f" ] || continue
|
||||
DEST="$ROOT/imports/workflows/$(basename "$f")"
|
||||
cp "$f" "$DEST"
|
||||
echo "[import-workflow] → $(basename "$f")"
|
||||
docker compose -f "$COMPOSE" exec n8n \
|
||||
n8n import:workflow --input="/imports/workflows/$(basename "$f")"
|
||||
done
|
||||
else
|
||||
# Einzelne Datei
|
||||
DEST="$ROOT/imports/workflows/$(basename "$SOURCE")"
|
||||
cp "$SOURCE" "$DEST"
|
||||
echo "[import-workflow] Importiere: $(basename "$SOURCE")"
|
||||
docker compose -f "$COMPOSE" exec n8n \
|
||||
n8n import:workflow --input="/imports/workflows/$(basename "$SOURCE")"
|
||||
fi
|
||||
|
||||
echo "[import-workflow] Fertig."
|
||||
50
scripts/restore-n8n.sh
Executable file
50
scripts/restore-n8n.sh
Executable file
|
|
@ -0,0 +1,50 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
COMPOSE="$ROOT/compose/docker-compose.yml"
|
||||
ENV="$ROOT/.env"
|
||||
|
||||
if [ -z "${1:-}" ]; then
|
||||
echo "Verwendung: $0 <backup-verzeichnis>"
|
||||
echo "Verfügbare Backups:"
|
||||
ls -lht "$ROOT/backups/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BACKUP="$1"
|
||||
if [ ! -d "$BACKUP" ]; then
|
||||
echo "Fehler: Verzeichnis '$BACKUP' nicht gefunden."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# shellcheck source=/dev/null
|
||||
source "$ENV"
|
||||
|
||||
echo "[restore] Stelle wieder her aus: $BACKUP"
|
||||
echo "[restore] Stack wird gestoppt..."
|
||||
docker compose -f "$COMPOSE" down
|
||||
|
||||
# n8n data
|
||||
echo "[restore] n8n Daten..."
|
||||
rm -rf "$ROOT/data/n8n"
|
||||
mkdir -p "$ROOT/data/n8n"
|
||||
tar -xzf "$BACKUP/n8n-data.tar.gz" -C "$ROOT/data"
|
||||
|
||||
# Postgres
|
||||
echo "[restore] Datenbank wird gestartet..."
|
||||
docker compose -f "$COMPOSE" up -d postgres
|
||||
echo "[restore] Warte auf PostgreSQL..."
|
||||
sleep 10
|
||||
|
||||
echo "[restore] Datenbank-Restore..."
|
||||
docker compose -f "$COMPOSE" exec -T postgres \
|
||||
psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" \
|
||||
< "$BACKUP/postgres.sql"
|
||||
|
||||
echo "[restore] Stack wird neu gestartet..."
|
||||
docker compose -f "$COMPOSE" up -d
|
||||
|
||||
echo "[restore] Fertig. Stack-Status:"
|
||||
docker compose -f "$COMPOSE" ps
|
||||
23
scripts/update-n8n.sh
Executable file
23
scripts/update-n8n.sh
Executable file
|
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
COMPOSE="$ROOT/compose/docker-compose.yml"
|
||||
|
||||
echo "[update] Starte Pre-Update-Backup..."
|
||||
bash "$SCRIPT_DIR/backup-n8n.sh"
|
||||
|
||||
echo "[update] Neue Images ziehen..."
|
||||
docker compose -f "$COMPOSE" pull
|
||||
|
||||
echo "[update] Stack neu starten..."
|
||||
docker compose -f "$COMPOSE" up -d
|
||||
|
||||
echo "[update] Warte 15s auf Start..."
|
||||
sleep 15
|
||||
|
||||
echo "[update] Stack-Status nach Update:"
|
||||
docker compose -f "$COMPOSE" ps
|
||||
|
||||
echo "[update] Update abgeschlossen."
|
||||
Loading…
Add table
Add a link
Reference in a new issue