cms.c2sgmbh/docs/DEPLOYMENT.md
2026-02-14 17:56:16 +00:00

11 KiB

Deployment Guide - Payload CMS Multi-Tenant

Letzte Aktualisierung: 17. Januar 2026

Wichtig: Für die vollständige Deployment-Strategie siehe DEPLOYMENT_STRATEGY.md

Übersicht

Dieses Dokument beschreibt den Deployment-Prozess für das Payload CMS Multi-Tenant-System.

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   DEVELOPMENT   │     │     STAGING     │     │   PRODUCTION    │
│                 │     │                 │     │                 │
│  sv-frontend    │────▶│   sv-payload    │────▶│   Hetzner 3     │
│  Local Dev      │     │ pl.porwoll.tech │     │ cms.c2sgmbh.de  │
│                 │     │                 │     │                 │
│  develop branch │     │  develop branch │     │   main branch   │
└─────────────────┘     └─────────────────┘     └─────────────────┘

Umgebungen

Umgebung Server URL Branch Zweck
Development sv-payload (LXC 700) https://pl.porwoll.tech develop Entwicklung & Testing
Production Hetzner 3 https://cms.c2sgmbh.de main Live-System

Git Branching Workflow

Regel: Immer auf develop entwickeln, nach Freigabe mit main mergen.

Workflow

# 1. Auf develop entwickeln
git checkout develop
git pull origin develop
# ... Code ändern ...
git add .
git commit -m "feat: neue Funktion"
git push origin develop
# → Automatisches Deployment auf Staging (pl.porwoll.tech)

# 2. Nach Test & Freigabe: Merge in main
git checkout main
git pull origin main
git merge develop
git push origin main
# → Manuelles Deployment auf Production (cms.c2sgmbh.de)

# 3. develop aktuell halten (nach Hotfixes auf main)
git checkout develop
git merge main
git push origin develop

Commit-Konventionen

Prefix Verwendung
feat: Neue Features
fix: Bug-Fixes
docs: Dokumentation
refactor: Code-Refactoring

Staging Deployment (Development → pl.porwoll.tech)

Automatisch via GitHub Actions

Bei jedem Push auf develop wird automatisch deployed:

# .github/workflows/deploy-staging.yml
on:
  push:
    branches: [develop]

Ablauf:

  1. Pre-deployment Checks (Lint, Tests)
  2. SSH-Verbindung zu sv-payload
  3. git pull origin develop
  4. pnpm install
  5. pnpm payload migrate
  6. pnpm build
  7. pm2 restart payload
  8. Health Check

Manuell auf sv-payload

# SSH zum Server
ssh payload@10.10.181.100

# Ins Projektverzeichnis
cd /home/payload/payload-cms

# Änderungen holen
git pull origin develop

# Dependencies aktualisieren
pnpm install

# Migrationen ausführen (falls vorhanden)
pnpm payload migrate

# Build erstellen
pnpm build

# PM2 neustarten
pm2 restart payload

# Logs prüfen
pm2 logs payload --lines 20

Mit Deploy-Script

# Auf sv-payload
./scripts/deploy-staging.sh

# Optionen:
./scripts/deploy-staging.sh --skip-build      # Nur Code-Update
./scripts/deploy-staging.sh --skip-migrations # Ohne Migrationen

Production Deployment (main → cms.c2sgmbh.de)

Option A: Via GitHub Actions (Empfohlen)

  1. develop in main mergen und pushen

    git checkout main
    git pull origin main
    git merge develop
    git push origin main
    
  2. GitHub Actions Workflow starten

    • Gehe zu: Actions → "Deploy to Production" → "Run workflow"
    • Oder via CLI:
      gh workflow run deploy-production.yml
      
  3. Der Workflow führt automatisch aus:

    • Pre-flight Checks
    • Tests (optional)
    • Datenbank-Backup
    • Deployment
    • Health Check
    • Bei Fehler: Automatischer Rollback

Option B: Via Deploy-Script auf Server

# SSH zum Production-Server
ssh payload@162.55.85.18

# Deploy-Script ausführen (mit Backup, Health Check, Rollback-Fähigkeit)
cd ~/payload-cms
./scripts/deploy-production.sh

# Optionen:
./scripts/deploy-production.sh -y              # Ohne Bestätigung
./scripts/deploy-production.sh --skip-backup   # Ohne Backup (nicht empfohlen)
./scripts/deploy-production.sh --skip-build    # Nur Service-Neustart
./scripts/deploy-production.sh --rollback      # Rollback zur vorherigen Version
./scripts/deploy-production.sh --dry-run       # Zeigt was passieren würde

Rollback bei Problemen

# Automatischer Rollback zur vorherigen Version
./scripts/deploy-production.sh --rollback

# Oder manuell zu spezifischem Commit
git log --oneline -10
git reset --hard <commit-sha>
pnpm install --frozen-lockfile
pnpm build
pm2 restart payload

Rollback

Auf vorherigen Commit zurücksetzen

# Letzten funktionierenden Commit finden
git log --oneline -10

# Zurücksetzen (VORSICHT: Ändert History nicht)
git checkout <commit-hash>
pnpm install
pnpm build
pm2 restart payload

# Oder: Hard Reset (VORSICHT: Ändert History)
git reset --hard <commit-hash>
git push --force origin main  # Nur im Notfall!

Datenbank-Rollback

# Backup wiederherstellen (nur bei Datenverlust)
gunzip -c ~/backups/payload_db_YYYY-MM-DD_HH-MM-SS.sql.gz | \
  psql -h localhost -U payload -d payload_db

Migrationen

Migration erstellen

# Auf Development-Server
pnpm payload migrate:create

# Generiert: src/migrations/YYYYMMDD_HHMMSS_<name>.ts

Migration ausführen

# Normale Ausführung
pnpm payload migrate

# Bei PgBouncer-Problemen: Direkte Verbindung
./scripts/db-direct.sh migrate

Migration-Status prüfen

pnpm payload migrate:status

Build-Konfiguration

Memory-Limits

Der Server hat 8GB RAM. Build-Einstellungen:

// package.json
{
  "scripts": {
    "build": "cross-env NODE_OPTIONS='--no-deprecation --max-old-space-size=2048' next build"
  }
}

Bei Memory-Problemen

# PM2 stoppen um Speicher freizugeben
pm2 stop payload

# Build mit reduziertem Memory
NODE_OPTIONS="--no-deprecation --max-old-space-size=1024" pnpm build

# PM2 wieder starten
pm2 start payload

PM2 Konfiguration

ecosystem.config.cjs

module.exports = {
  apps: [
    {
      name: 'payload',
      script: 'node_modules/.bin/next',
      args: 'start',
      cwd: '/home/payload/payload-cms',
      instances: 1,
      max_memory_restart: '2G',
      env: {
        NODE_ENV: 'production',
        PORT: 3000
      }
    },
    {
      name: 'queue-worker',
      script: 'node_modules/tsx/dist/cli.mjs',
      args: 'scripts/run-queue-worker.ts',
      exec_mode: 'fork',
      cwd: '/home/payload/payload-cms',
      instances: 1,
      max_memory_restart: '768M'
    }
  ]
}

PM2 Befehle

pm2 status              # Status aller Prozesse
pm2 logs payload        # Logs anzeigen
pm2 logs queue-worker   # Queue-Worker Logs
pm2 restart payload     # Neustart
pm2 restart all         # Alle neustarten
pm2 save                # Autostart-Konfiguration speichern
pm2 startup             # Systemd-Integration

Health Checks

Nach Deployment prüfen

# 1. PM2 Status
pm2 status

# 2. Logs auf Fehler prüfen
pm2 logs payload --lines 50

# 3. API erreichbar?
curl -I https://cms.c2sgmbh.de/api/users

# 4. Admin Panel erreichbar?
curl -I https://cms.c2sgmbh.de/admin

# 5. Redis verbunden?
redis-cli ping

Automatischer Health Check

#!/bin/bash
# health-check.sh

API_URL="https://cms.c2sgmbh.de/api"
ADMIN_URL="https://cms.c2sgmbh.de/admin"

# API Check
if curl -sf "$API_URL/users" > /dev/null; then
  echo "✅ API OK"
else
  echo "❌ API FAILED"
  exit 1
fi

# Admin Check
if curl -sf "$ADMIN_URL" > /dev/null; then
  echo "✅ Admin OK"
else
  echo "❌ Admin FAILED"
  exit 1
fi

echo "✅ All checks passed"

Umgebungsvariablen

Production (.env)

# Datenbank
DATABASE_URI=postgresql://payload:***@localhost:5432/payload_db
PAYLOAD_SECRET=***

# URLs
PAYLOAD_PUBLIC_SERVER_URL=https://cms.c2sgmbh.de
NEXT_PUBLIC_SERVER_URL=https://cms.c2sgmbh.de

# Environment
NODE_ENV=production
PORT=3001

# Redis
REDIS_URL=redis://localhost:6379
REDIS_PASSWORD=***

# Security
CSRF_SECRET=***
TRUST_PROXY=true

Staging (.env)

# Datenbank (via PgBouncer)
DATABASE_URI=postgresql://payload:***@127.0.0.1:6432/payload_db
PAYLOAD_SECRET=***

# URLs
PAYLOAD_PUBLIC_SERVER_URL=https://pl.porwoll.tech
NEXT_PUBLIC_SERVER_URL=https://pl.porwoll.tech

# Environment
NODE_ENV=production
PORT=3000

# Redis
REDIS_URL=redis://localhost:6379
REDIS_PASSWORD=***

# Security
CSRF_SECRET=***
TRUST_PROXY=true

CI/CD Pipeline

GitHub Actions Workflows

Workflow Trigger Aktion
ci.yml Push/PR auf main, develop Lint, Test, Build, E2E
security.yml Push/PR, Schedule Security Scanning
deploy-staging.yml Push auf develop Auto-Deploy zu Staging
deploy-production.yml Manuell (workflow_dispatch) Production Deployment

Secrets (GitHub)

Secret Beschreibung
STAGING_SSH_KEY SSH Private Key für sv-payload
PRODUCTION_SSH_KEY SSH Private Key für Hetzner 3

Manuelles Deployment triggern

# Via GitHub CLI
gh workflow run deploy-staging.yml

# Mit skip_tests Option
gh workflow run deploy-staging.yml -f skip_tests=true

Backup vor Deployment

Automatisches Backup

Backups laufen täglich um 03:00 Uhr. Vor großen Deployments manuell:

# Auf Production
~/backup.sh

# Auf Staging
/home/payload/backups/postgres/backup-db.sh --verbose

Backup-Speicherorte

Server Lokal Offsite
Production ~/backups/ -
Staging /home/payload/backups/postgres/ s3://c2s/backups/postgres/

Troubleshooting

Build schlägt fehl

# Cache löschen
rm -rf .next
pnpm build

# Mit mehr Speicher
NODE_OPTIONS="--max-old-space-size=4096" pnpm build

PM2 startet nicht

# Logs prüfen
pm2 logs payload --lines 100

# Prozess komplett entfernen und neu starten
pm2 delete payload
pm2 start ecosystem.config.cjs

Datenbank-Verbindung fehlgeschlagen

# PgBouncer Status (Staging)
sudo systemctl status pgbouncer

# PostgreSQL Status (Production)
sudo systemctl status postgresql

# Verbindung testen
psql -h localhost -U payload -d payload_db -c "SELECT 1"

Migration fehlgeschlagen

# Status prüfen
pnpm payload migrate:status

# Bei PgBouncer-Problemen
./scripts/db-direct.sh migrate

# Einzelne Migration manuell
pnpm payload migrate --name 20251216_073000_add_video_collections

Checkliste

Vor dem Deployment

  • Alle Tests grün (pnpm test)
  • Build erfolgreich (pnpm build)
  • Migrationen getestet auf Staging
  • Backup erstellt (bei Datenbank-Änderungen)
  • CLAUDE.md/Docs aktualisiert (bei neuen Features)

Nach dem Deployment

  • pm2 status - Prozesse online
  • Admin Panel erreichbar
  • API funktioniert
  • Logs auf Fehler geprüft
  • Neue Features manuell getestet

Kontakte

Rolle Kontakt
Server Admin Martin Porwoll
Repository https://github.com/complexcaresolutions/cms.c2sgmbh

Dokumentation: Complex Care Solutions GmbH | 29.12.2025