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
35
.env.example
Normal file
35
.env.example
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
# =============================================================================
|
||||||
|
# n8n Stack — Konfigurationsvorlage
|
||||||
|
# Kopieren nach .env und alle Werte ausfüllen.
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# --- Domain & URL ---
|
||||||
|
N8N_HOST=n8n.linix.de
|
||||||
|
N8N_PROTOCOL=https
|
||||||
|
WEBHOOK_URL=https://n8n.linix.de/
|
||||||
|
|
||||||
|
# --- Datenbank ---
|
||||||
|
POSTGRES_DB=n8n
|
||||||
|
POSTGRES_USER=n8n
|
||||||
|
POSTGRES_PASSWORD=HIER_STARKES_PASSWORT_EINTRAGEN
|
||||||
|
|
||||||
|
# --- Redis ---
|
||||||
|
REDIS_PASSWORD=HIER_STARKES_PASSWORT_EINTRAGEN
|
||||||
|
|
||||||
|
# --- n8n Encryption Key ---
|
||||||
|
# KRITISCH: Einmalig generieren (z.B. openssl rand -base64 32) und nie mehr ändern!
|
||||||
|
# Änderung macht alle gespeicherten Credentials unbrauchbar.
|
||||||
|
N8N_ENCRYPTION_KEY=HIER_ZUFALLSKEY_EINTRAGEN
|
||||||
|
|
||||||
|
# --- SMTP ---
|
||||||
|
SMTP_HOST=linix.de
|
||||||
|
SMTP_PORT=587
|
||||||
|
SMTP_USER=nutzer@linix.de
|
||||||
|
SMTP_PASSWORD=SMTP_PASSWORT
|
||||||
|
SMTP_SENDER=n8n@linix.de
|
||||||
|
|
||||||
|
# --- Worker ---
|
||||||
|
N8N_WORKER_REPLICAS=1
|
||||||
|
|
||||||
|
# --- Zeitzone ---
|
||||||
|
TZ=Europe/Berlin
|
||||||
142
README.md
142
README.md
|
|
@ -1,3 +1,141 @@
|
||||||
# n8n_stack
|
# n8n Stack
|
||||||
|
|
||||||
Das Projekt installiert und konfiguriert einen vollständigen, produktionsnahen n8n-Stack auf einem Ubuntu-Linux-System.
|
Produktionsnaher n8n-Stack auf Docker Compose mit PostgreSQL, Redis und Queue-Mode.
|
||||||
|
|
||||||
|
## Architektur
|
||||||
|
|
||||||
|
```
|
||||||
|
Internet → n8n.linix.de:443
|
||||||
|
→ YunoHost (192.168.179.10) — TLS-Terminierung (Let's Encrypt)
|
||||||
|
→ nginx lokal :8088 (192.168.179.124)
|
||||||
|
→ n8n Docker :5678
|
||||||
|
↔ PostgreSQL (n8n-stack-postgres-1)
|
||||||
|
↔ Redis (n8n-stack-redis-1)
|
||||||
|
← n8n-worker (n8n-stack-n8n-worker-1)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Verzeichnisstruktur
|
||||||
|
|
||||||
|
```
|
||||||
|
n8n_stack/
|
||||||
|
├── compose/docker-compose.yml # Stack-Definition
|
||||||
|
├── .env # Secrets (600, nie committen!)
|
||||||
|
├── .env.example # Vorlage
|
||||||
|
├── scripts/ # Hilfsskripte (700)
|
||||||
|
├── data/ # Docker-Volumes (gitignoriert)
|
||||||
|
│ ├── n8n/
|
||||||
|
│ ├── postgres/
|
||||||
|
│ └── redis/
|
||||||
|
├── backups/ # Backups, max. 2 (gitignoriert)
|
||||||
|
├── imports/workflows/ # Workflow-JSONs zum Importieren
|
||||||
|
├── imports/credentials/ # Credentials-Exporte (unverschlüsselt!)
|
||||||
|
├── local-files/ # Dateien für n8n-Container (/files)
|
||||||
|
└── docs/ # nginx-Configs, Runbooks
|
||||||
|
```
|
||||||
|
|
||||||
|
## Start / Stop / Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start
|
||||||
|
docker compose -f compose/docker-compose.yml up -d
|
||||||
|
|
||||||
|
# Stop
|
||||||
|
docker compose -f compose/docker-compose.yml down
|
||||||
|
|
||||||
|
# Status
|
||||||
|
docker compose -f compose/docker-compose.yml ps
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
docker compose -f compose/docker-compose.yml logs -f n8n
|
||||||
|
|
||||||
|
# Worker skalieren (z.B. auf 2)
|
||||||
|
docker compose -f compose/docker-compose.yml up -d --scale n8n-worker=2
|
||||||
|
```
|
||||||
|
|
||||||
|
## Update
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash scripts/update-n8n.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Führt automatisch ein Backup aus, zieht neue Images und startet den Stack neu.
|
||||||
|
|
||||||
|
## Backup / Restore
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backup erstellen (behält immer die letzten 2)
|
||||||
|
bash scripts/backup-n8n.sh
|
||||||
|
|
||||||
|
# Restore aus Backup-Verzeichnis
|
||||||
|
bash scripts/restore-n8n.sh backups/backup_20240101_120000
|
||||||
|
```
|
||||||
|
|
||||||
|
## Import / Export von Workflows
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Einzelne Workflow-JSON importieren
|
||||||
|
bash scripts/import-workflow.sh imports/workflows/mein-workflow.json
|
||||||
|
|
||||||
|
# Ganzes Verzeichnis importieren
|
||||||
|
bash scripts/import-workflow.sh imports/workflows/
|
||||||
|
|
||||||
|
# Alle Workflows exportieren
|
||||||
|
bash scripts/export-workflows.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Import / Export von Credentials
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Credentials importieren
|
||||||
|
bash scripts/import-credentials.sh imports/credentials/creds.json
|
||||||
|
|
||||||
|
# Credentials exportieren (UNVERSCHLÜSSELT — sicher aufbewahren!)
|
||||||
|
bash scripts/export-credentials.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
**Wichtig:** Credential-Exporte enthalten alle Secrets im Klartext. Export-Dateien nach Gebrauch löschen.
|
||||||
|
|
||||||
|
## Übernahme fremder n8n-Projekte
|
||||||
|
|
||||||
|
1. Workflow-JSON-Dateien nach `imports/workflows/` kopieren
|
||||||
|
2. `bash scripts/import-workflow.sh imports/workflows/<datei>.json`
|
||||||
|
3. Falls Credentials mitgeliefert: `bash scripts/import-credentials.sh <datei.json>`
|
||||||
|
4. In der n8n-UI: Credentials der importierten Workflows prüfen und neu verknüpfen
|
||||||
|
|
||||||
|
Bei Voll-Exporten (`.zip` mit mehreren JSONs): entpacken, dann Verzeichnis übergeben.
|
||||||
|
|
||||||
|
## Deployment auf neuem Host
|
||||||
|
|
||||||
|
1. Repo klonen
|
||||||
|
2. `.env.example` → `.env` kopieren, alle Werte ausfüllen
|
||||||
|
3. Neuen `N8N_ENCRYPTION_KEY` generieren: `openssl rand -base64 32`
|
||||||
|
4. `N8N_HOST` und `WEBHOOK_URL` auf die neue Domain anpassen
|
||||||
|
5. nginx-Config aus `docs/nginx-local-n8n.conf` anpassen und aktivieren
|
||||||
|
6. YunoHost-Config aus `docs/yunohost-nginx-n8n.conf` anpassen und installieren
|
||||||
|
7. `docker compose -f compose/docker-compose.yml up -d`
|
||||||
|
|
||||||
|
## Kritische Hinweise
|
||||||
|
|
||||||
|
- **`N8N_ENCRYPTION_KEY`** darf nach dem ersten Start **nie geändert** werden — eine Änderung macht alle gespeicherten Credentials unbrauchbar. Key steht in `.env`.
|
||||||
|
- **`.env`** nie committen (steht in `.gitignore`).
|
||||||
|
- Backup vor jedem Update läuft automatisch via `update-n8n.sh`.
|
||||||
|
|
||||||
|
## URLs und Zugangspfade
|
||||||
|
|
||||||
|
| Was | Wert |
|
||||||
|
|---|---|
|
||||||
|
| n8n Web-UI | https://n8n.linix.de |
|
||||||
|
| Erster Login | Beim ersten Aufruf Owner-Account anlegen |
|
||||||
|
| Secrets-Datei | `./.env` (Rechte 600) |
|
||||||
|
| Backup-Verzeichnis | `./backups/` |
|
||||||
|
| nginx lokal | `/etc/nginx/sites-available/n8n` (Port 8088) |
|
||||||
|
| YunoHost nginx | `/etc/nginx/conf.d/n8n.linix.de.conf` |
|
||||||
|
|
||||||
|
## To-do (manuell auf YunoHost)
|
||||||
|
|
||||||
|
- [ ] DNS: `n8n.linix.de` → `92.50.108.218` (A-Record beim DNS-Provider)
|
||||||
|
- [ ] YunoHost: Domain hinzufügen: `sudo yunohost domain add n8n.linix.de`
|
||||||
|
- [ ] YunoHost: Let's Encrypt: `sudo yunohost domain cert install n8n.linix.de`
|
||||||
|
- [ ] YunoHost: `docs/yunohost-nginx-n8n.conf` → `/etc/nginx/conf.d/n8n.linix.de.conf` kopieren, dann `sudo nginx -t && sudo systemctl reload nginx`
|
||||||
|
- [ ] SMTP-Credentials in `.env` eintragen (`SMTP_USER`, `SMTP_PASSWORD`)
|
||||||
|
- [ ] Ersten Owner-Account in n8n anlegen (https://n8n.linix.de beim ersten Aufruf)
|
||||||
|
|
|
||||||
118
compose/docker-compose.yml
Normal file
118
compose/docker-compose.yml
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
name: n8n-stack
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
postgres:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: ${POSTGRES_DB}
|
||||||
|
POSTGRES_USER: ${POSTGRES_USER}
|
||||||
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- ../data/postgres:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
networks:
|
||||||
|
- n8n-internal
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
command: redis-server --requirepass ${REDIS_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- ../data/redis:/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
networks:
|
||||||
|
- n8n-internal
|
||||||
|
|
||||||
|
n8n:
|
||||||
|
image: n8nio/n8n:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:5678:5678"
|
||||||
|
environment:
|
||||||
|
# URL & Protokoll
|
||||||
|
N8N_HOST: ${N8N_HOST}
|
||||||
|
N8N_PORT: 5678
|
||||||
|
N8N_PROTOCOL: ${N8N_PROTOCOL}
|
||||||
|
WEBHOOK_URL: ${WEBHOOK_URL}
|
||||||
|
# Datenbank
|
||||||
|
DB_TYPE: postgresdb
|
||||||
|
DB_POSTGRESDB_HOST: postgres
|
||||||
|
DB_POSTGRESDB_PORT: 5432
|
||||||
|
DB_POSTGRESDB_DATABASE: ${POSTGRES_DB}
|
||||||
|
DB_POSTGRESDB_USER: ${POSTGRES_USER}
|
||||||
|
DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
|
||||||
|
# Encryption
|
||||||
|
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
|
||||||
|
# Queue / Redis
|
||||||
|
EXECUTIONS_MODE: queue
|
||||||
|
QUEUE_BULL_REDIS_HOST: redis
|
||||||
|
QUEUE_BULL_REDIS_PORT: 6379
|
||||||
|
QUEUE_BULL_REDIS_PASSWORD: ${REDIS_PASSWORD}
|
||||||
|
# SMTP
|
||||||
|
N8N_EMAIL_MODE: smtp
|
||||||
|
N8N_SMTP_HOST: ${SMTP_HOST}
|
||||||
|
N8N_SMTP_PORT: ${SMTP_PORT}
|
||||||
|
N8N_SMTP_USER: ${SMTP_USER}
|
||||||
|
N8N_SMTP_PASS: ${SMTP_PASSWORD}
|
||||||
|
N8N_SMTP_SENDER: ${SMTP_SENDER}
|
||||||
|
N8N_SMTP_SSL: "false"
|
||||||
|
# User Management
|
||||||
|
N8N_USER_MANAGEMENT_DISABLED: "false"
|
||||||
|
# Zeitzone
|
||||||
|
GENERIC_TIMEZONE: ${TZ}
|
||||||
|
TZ: ${TZ}
|
||||||
|
volumes:
|
||||||
|
- ../data/n8n:/home/node/.n8n
|
||||||
|
- ../local-files:/files
|
||||||
|
- ../imports:/imports
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
- n8n-internal
|
||||||
|
|
||||||
|
n8n-worker:
|
||||||
|
image: n8nio/n8n:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
command: worker
|
||||||
|
environment:
|
||||||
|
# Datenbank
|
||||||
|
DB_TYPE: postgresdb
|
||||||
|
DB_POSTGRESDB_HOST: postgres
|
||||||
|
DB_POSTGRESDB_PORT: 5432
|
||||||
|
DB_POSTGRESDB_DATABASE: ${POSTGRES_DB}
|
||||||
|
DB_POSTGRESDB_USER: ${POSTGRES_USER}
|
||||||
|
DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
|
||||||
|
# Encryption
|
||||||
|
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
|
||||||
|
# Queue / Redis
|
||||||
|
EXECUTIONS_MODE: queue
|
||||||
|
QUEUE_BULL_REDIS_HOST: redis
|
||||||
|
QUEUE_BULL_REDIS_PORT: 6379
|
||||||
|
QUEUE_BULL_REDIS_PASSWORD: ${REDIS_PASSWORD}
|
||||||
|
# Zeitzone
|
||||||
|
GENERIC_TIMEZONE: ${TZ}
|
||||||
|
TZ: ${TZ}
|
||||||
|
volumes:
|
||||||
|
- ../data/n8n:/home/node/.n8n
|
||||||
|
- ../local-files:/files
|
||||||
|
depends_on:
|
||||||
|
- n8n
|
||||||
|
networks:
|
||||||
|
- n8n-internal
|
||||||
|
|
||||||
|
networks:
|
||||||
|
n8n-internal:
|
||||||
|
driver: bridge
|
||||||
28
docs/nginx-local-n8n.conf
Normal file
28
docs/nginx-local-n8n.conf
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Lokale nginx-Konfiguration auf 192.168.179.124
|
||||||
|
# Ablegen als: /etc/nginx/sites-available/n8n
|
||||||
|
# Aktivieren mit: sudo ln -s /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/n8n
|
||||||
|
# Danach: sudo nginx -t && sudo systemctl reload nginx
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 8088;
|
||||||
|
server_name n8n.linix.de;
|
||||||
|
|
||||||
|
# n8n-Proxy
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:5678;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
|
||||||
|
# WebSocket-Support (n8n Editor + Push-Benachrichtigungen)
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
|
||||||
|
|
||||||
|
proxy_read_timeout 300s;
|
||||||
|
proxy_send_timeout 300s;
|
||||||
|
client_max_body_size 50m;
|
||||||
|
}
|
||||||
|
}
|
||||||
49
docs/yunohost-nginx-n8n.conf
Normal file
49
docs/yunohost-nginx-n8n.conf
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
# YunoHost nginx-Konfiguration (auf dem YunoHost-Server 192.168.179.10)
|
||||||
|
# Ablegen als: /etc/nginx/conf.d/n8n.linix.de.conf
|
||||||
|
# Danach: sudo nginx -t && sudo systemctl reload nginx
|
||||||
|
#
|
||||||
|
# Voraussetzungen auf YunoHost:
|
||||||
|
# 1. Domain n8n.linix.de in YunoHost hinzufügen:
|
||||||
|
# sudo yunohost domain add n8n.linix.de
|
||||||
|
# 2. Let's Encrypt Zertifikat ausstellen:
|
||||||
|
# sudo yunohost domain cert install n8n.linix.de
|
||||||
|
# 3. Diese Datei ablegen und nginx neu laden.
|
||||||
|
#
|
||||||
|
# Cert-Pfad prüfen mit: ls /etc/yunohost/certs/
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
listen [::]:443 ssl;
|
||||||
|
server_name n8n.linix.de;
|
||||||
|
|
||||||
|
ssl_certificate /etc/yunohost/certs/n8n.linix.de/crt.pem;
|
||||||
|
ssl_certificate_key /etc/yunohost/certs/n8n.linix.de/key.pem;
|
||||||
|
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://192.168.179.124:8088;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
|
||||||
|
# WebSocket-Support
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto https;
|
||||||
|
|
||||||
|
proxy_read_timeout 300s;
|
||||||
|
proxy_send_timeout 300s;
|
||||||
|
client_max_body_size 50m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
server_name n8n.linix.de;
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
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