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

525 lines
9.6 KiB
Markdown

# 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:
```yaml
# .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
```bash
# 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
```bash
# 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
```bash
# 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
```bash
# SSH zum Production-Server
ssh payload@162.55.85.18
# Deploy-Script ausführen
~/deploy.sh
```
### Deploy-Script (~/deploy.sh)
```bash
#!/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
```bash
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
```bash
# 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
```bash
# 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
```bash
# Auf Development-Server
pnpm payload migrate:create
# Generiert: src/migrations/YYYYMMDD_HHMMSS_<name>.ts
```
### Migration ausführen
```bash
# Normale Ausführung
pnpm payload migrate
# Bei PgBouncer-Problemen: Direkte Verbindung
./scripts/db-direct.sh migrate
```
### Migration-Status prüfen
```bash
pnpm payload migrate:status
```
---
## Build-Konfiguration
### Memory-Limits
Der Server hat 8GB RAM. Build-Einstellungen:
```json
// package.json
{
"scripts": {
"build": "cross-env NODE_OPTIONS='--no-deprecation --max-old-space-size=2048' next build"
}
}
```
### Bei Memory-Problemen
```bash
# 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
```javascript
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
```bash
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
```bash
# 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
```bash
#!/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)
```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)
```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
```bash
# 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:
```bash
# 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
```bash
# Cache löschen
rm -rf .next
pnpm build
# Mit mehr Speicher
NODE_OPTIONS="--max-old-space-size=4096" pnpm build
```
### PM2 startet nicht
```bash
# 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
```bash
# 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
```bash
# 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*