cms.c2sgmbh/docs/DEPLOYMENT.md
Martin Porwoll 9c9ae86d99 docs: add comprehensive DEPLOYMENT.md guide
- Create docs/DEPLOYMENT.md with full deployment documentation
- Document staging (pl.porwoll.tech) and production (cms.c2sgmbh.de) workflows
- Add rollback procedures and migration handling
- Include PM2 configuration and health checks
- Add troubleshooting section and deployment checklists
- Update TODO.md to mark task as completed
- Add DEPLOYMENT.md to CLAUDE.md documentation references

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 15:53:41 +00:00

9.6 KiB

Deployment Guide - Payload CMS Multi-Tenant

Letzte Aktualisierung: 18. Dezember 2025

Ü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

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)

Schritt 1: Merge zu main

# Auf dem Development-Server oder lokal
git checkout main
git pull origin main
git merge develop
git push origin main

Schritt 2: Deploy auf Hetzner 3

# SSH zum Production-Server
ssh payload@162.55.85.18

# Deploy-Script ausführen
~/deploy.sh

Deploy-Script (~/deploy.sh)

#!/bin/bash
set -e

cd ~/payload-cms

echo "📥 Pulling latest changes..."
git pull origin main

echo "📦 Installing dependencies..."
pnpm install

echo "🔄 Running migrations..."
pnpm payload migrate

echo "🏗️ Building..."
pnpm build

echo "🔄 Restarting PM2..."
pm2 restart payload

echo "✅ Deployment complete!"
pm2 status

Manuelles Deployment

ssh payload@162.55.85.18
cd ~/payload-cms
git pull origin main
pnpm install
pnpm payload migrate
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: './scripts/run-queue-worker.ts',
      interpreter: 'node',
      interpreter_args: '--import tsx',
      cwd: '/home/payload/payload-cms',
      instances: 1,
      max_memory_restart: '500M'
    }
  ]
}

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

# 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

# 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
security.yml Push/PR, Schedule Security Scanning
deploy-staging.yml Push auf develop Auto-Deploy zu Staging

Secrets (GitHub)

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

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 | 18.12.2025