mirror of
https://github.com/complexcaresolutions/cms.c2sgmbh.git
synced 2026-03-17 20:54:11 +00:00
Tests: - Update frontend.e2e.spec.ts with locale testing - Add search.e2e.spec.ts for search functionality - Add i18n.int.spec.ts for localization tests - Add search.int.spec.ts for search integration - Update playwright.config.ts Documentation: - Add CLAUDE.md with project instructions - Add docs/ directory with detailed documentation - Add scripts/ for utility scripts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
8.1 KiB
8.1 KiB
Payload CMS Multi-Tenant Infrastructure
Übersicht
Diese Dokumentation beschreibt die Infrastruktur eines Payload CMS 3.x Multi-Tenant-Systems für den Betrieb mehrerer Websites unter einer zentralen CMS-Instanz.
Architektur
┌─────────────────────────────────────────────────────────────────┐
│ INTERNET │
│ │ │
│ 37.24.237.181 (Public IP) │
│ │ │
│ NAT (Proxmox) │
│ Port 80, 443 │
└────────────────────────────┼────────────────────────────────────┘
│
┌────────────────────────────┼────────────────────────────────────┐
│ VLAN 181 │
│ 10.10.181.0/24 │
│ │ │
│ ┌───────────────────────┴───────────────────────┐ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ LXC 700 │ │ LXC 701 │ │
│ │ sv-payload │ │ sv-postgres │ │
│ │ 10.10.181.100 │────────────────▶│ 10.10.181.101 │ │
│ │ │ Port 5432 │ │ │
│ │ - Caddy (80/443) │ │ - PostgreSQL 17 │ │
│ │ - Node.js 22 │ │ │ │
│ │ - Payload CMS │ │ │ │
│ │ - PM2 │ │ │ │
│ └─────────────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Server-Details
LXC 700 - sv-payload (Application Server)
| Eigenschaft | Wert |
|---|---|
| IP | 10.10.181.100 |
| Öffentlich | 37.24.237.181 (via NAT) |
| OS | Debian 13 (Trixie) |
| CPU | 4 Cores |
| RAM | 4 GB |
| Disk | 40 GB |
| Domain | pl.c2sgmbh.de |
Installierte Software:
- Node.js 22 LTS (via NodeSource)
- pnpm (Package Manager)
- Caddy 2.10.2 (Reverse Proxy mit automatischem SSL)
- PM2 (Process Manager)
- Payload CMS 3.x mit Next.js 15.4.7
Dienste:
- Caddy läuft als systemd service auf Port 80/443
- Payload läuft via PM2 auf Port 3000
LXC 701 - sv-postgres (Database Server)
| Eigenschaft | Wert |
|---|---|
| IP | 10.10.181.101 |
| Öffentlich | Nein (nur intern) |
| OS | Debian 13 (Trixie) |
| CPU | 2 Cores |
| RAM | 2 GB |
| Disk | 20 GB |
Datenbank:
- PostgreSQL 17
- Database: payload_db
- User: payload
- Passwort: Finden55
- Nur erreichbar von 10.10.181.100
Verzeichnisstruktur auf sv-payload
/home/payload/
├── payload-cms/ # Hauptanwendung
│ ├── src/
│ │ ├── collections/
│ │ │ ├── Users.ts
│ │ │ ├── Media.ts
│ │ │ └── Tenants.ts
│ │ ├── payload.config.ts
│ │ └── payload-types.ts
│ ├── .env # Umgebungsvariablen
│ ├── ecosystem.config.cjs # PM2 Konfiguration
│ ├── package.json
│ └── .next/ # Next.js Build Output
├── logs/
│ ├── error-0.log
│ └── out-0.log
└── ecosystem.config.cjs # PM2 Config (Symlink)
Konfigurationsdateien
.env (/home/payload/payload-cms/.env)
DATABASE_URI=postgresql://payload:Finden55@10.10.181.101:5432/payload_db
PAYLOAD_SECRET=a53b254070d3fffd2b5cfcc3
PAYLOAD_PUBLIC_SERVER_URL=https://pl.c2sgmbh.de
NEXT_PUBLIC_SERVER_URL=https://pl.c2sgmbh.de
NODE_ENV=production
PORT=3000
Caddyfile (/etc/caddy/Caddyfile)
{
email deine-email@c2sgmbh.de
}
pl.c2sgmbh.de {
reverse_proxy localhost:3000
request_body {
max_size 100MB
}
header {
X-Content-Type-Options nosniff
X-Frame-Options SAMEORIGIN
-Server
}
encode gzip zstd
}
PM2 Konfiguration (/home/payload/payload-cms/ecosystem.config.cjs)
module.exports = {
apps: [{
name: 'payload',
cwd: '/home/payload/payload-cms',
script: 'pnpm',
args: 'start',
env: {
NODE_ENV: 'production',
PORT: 3000
},
instances: 1,
autorestart: true,
max_memory_restart: '1G',
error_file: '/home/payload/logs/error.log',
out_file: '/home/payload/logs/out.log'
}]
}
Multi-Tenant Konzept
Das System verwendet @payloadcms/plugin-multi-tenant für die Mandantenfähigkeit.
Tenants (Mandanten)
Jeder Tenant repräsentiert eine separate Website:
| Tenant | Slug | Domains |
|---|---|---|
| porwoll.de | porwoll | porwoll.de, www.porwoll.de |
| Complex Care Solutions GmbH | c2s | complexcaresolutions.de |
| Gunshin | gunshin | gunshin.de |
| Zweitmeinung | zweitmeinung | zweitmein.ng |
Datenisolation
- Jeder Content (Media, Pages, Posts etc.) gehört zu genau einem Tenant
- User werden Tenants zugewiesen und sehen nur deren Inhalte
- Die Domain-Erkennung erfolgt automatisch durch das Plugin
Datenbank-Tabellen
tenants - Mandanten-Stammdaten
tenants_domains - Domain-Zuordnungen
users_tenants - User-Mandanten-Beziehung (N:M)
Netzwerk & Firewall
UFW Regeln auf sv-payload
22/tcp ALLOW 10.10.181.0/24 # SSH aus VLAN
80/tcp ALLOW Anywhere # HTTP (ACME)
443/tcp ALLOW Anywhere # HTTPS
UFW Regeln auf sv-postgres
22/tcp ALLOW 10.10.181.0/24 # SSH aus VLAN
5432/tcp ALLOW 10.10.181.100 # PostgreSQL nur von Payload
DSGVO-Konformität
Die Architektur wurde bewusst ohne Cloudflare designed:
- Keine US-Dienste im Datenpfad für Admin-Zugriffe
- Direkte öffentliche IP statt Proxy
- Keine Auftragsverarbeiter-Verträge für CDN nötig
- Redakteur-IPs und Sessions bleiben in DE
Wichtige Befehle
Payload Management
# Als payload User
su - payload
cd ~/payload-cms
# Entwicklung
pnpm dev
# Build für Production
pnpm build
# Migrationen
pnpm payload migrate:create
pnpm payload migrate
# ImportMap generieren (nach Plugin-Änderungen)
pnpm payload generate:importmap
PM2 Management
pm2 status
pm2 logs payload
pm2 restart payload
pm2 stop payload
pm2 start ecosystem.config.cjs
Caddy Management
sudo systemctl status caddy
sudo systemctl restart caddy
sudo caddy validate --config /etc/caddy/Caddyfile
Datenbank
# Von sv-payload aus
PGPASSWORD=Finden55 psql -h 10.10.181.101 -U payload -d payload_db
# Tabellen anzeigen
\dt
# Tenants abfragen
SELECT * FROM tenants;
SELECT * FROM users_tenants;
Zugriff
- Admin Panel: https://pl.c2sgmbh.de/admin
- API: https://pl.c2sgmbh.de/api
- SSH Payload Server: ssh root@10.10.181.100 (aus VLAN 181)
- SSH Postgres Server: ssh root@10.10.181.101 (aus VLAN 181)