# Deployment-Guide: Risk Intelligence Platform

## 📋 Inhaltsverzeichnis

1. [Übersicht](#übersicht)
2. [Voraussetzungen](#voraussetzungen)
3. [Docker Deployment](#docker-deployment)
4. [Kubernetes Deployment](#kubernetes-deployment)
5. [Production Checklist](#production-checklist)
6. [Environment Configuration](#environment-configuration)
7. [Database Migration](#database-migration)
8. [Monitoring & Logging](#monitoring--logging)
9. [Backup & Recovery](#backup--recovery)
10. [Rollback-Strategie](#rollback-strategie)
11. [Troubleshooting](#troubleshooting)

---

## Übersicht

Die Risk Intelligence Platform kann auf verschiedene Arten deployed werden:

- **Docker** - Standalone Container oder Docker Compose
- **Kubernetes** - Production-ready mit CronJobs für Scheduled Tasks
- **Traditional** - Apache/Nginx + PHP-FPM auf Linux-Server

### Deployment-Architektur

```
┌─────────────────────────────────────────────────────────────┐
│                    Production Environment                    │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐     │
│  │   Nginx      │  │  PHP-FPM     │  │  Supervisor  │     │
│  │  (Port 80)   │  │  (Laravel)   │  │  (Queue)     │     │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘     │
│         │                 │                 │              │
│         └─────────────────┴─────────────────┘              │
│                          │                                  │
│                          ▼                                  │
│         ┌────────────────────────────────┐                 │
│         │   PostgreSQL Database          │                 │
│         │   (Public + Backend Schema)    │                 │
│         └────────────────────────────────┘                 │
│                                                              │
│  ┌────────────────────────────────────────────────────┐    │
│  │   Kubernetes CronJob (Laravel Scheduler)           │    │
│  │   - SyncBackendDataPool (every 6h)                 │    │
│  │   - TransformDataPool (every 6h at :30)            │    │
│  └────────────────────────────────────────────────────┘    │
│                                                              │
└─────────────────────────────────────────────────────────────┘
```

---

## Voraussetzungen

### System Requirements

| Komponente | Minimum | Empfohlen |
|------------|---------|-----------|
| **CPU** | 2 Cores | 4 Cores |
| **RAM** | 2 GB | 4 GB |
| **Disk** | 20 GB | 50 GB SSD |
| **OS** | Linux (Ubuntu 22.04+) | Alpine Linux 3.22 |

### Software Requirements

| Software | Version | Zweck |
|----------|---------|-------|
| **PHP** | 8.2+ | Runtime |
| **Composer** | 2.0+ | Dependencies |
| **Node.js** | 18+ | Asset Building |
| **PostgreSQL** | 14+ | Database |
| **Nginx** | 1.24+ | Web Server |
| **Supervisor** | 4.0+ | Process Management |
| **Docker** | 24.0+ | Containerization (optional) |
| **Kubernetes** | 1.28+ | Orchestration (optional) |

---

## Docker Deployment

### Multi-Stage Dockerfile

Die Applikation nutzt einen **Multi-Stage Build** für optimale Image-Größe.

```dockerfile
# Stage 1: Composer Dependencies
FROM composer:2 AS vendor
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader

# Stage 2: Runtime
FROM alpine:3.22
# Install PHP 8.2, Nginx, Supervisor, PostgreSQL Client
RUN apk add --no-cache \
    nginx supervisor php82 php82-fpm \
    php82-pgsql php82-pdo_pgsql \
    nodejs npm

# Copy vendor from build stage
COPY --from=vendor /app/vendor ./vendor
COPY . ./

# Build frontend assets
RUN npm ci && npm run build

# Optimize Laravel
RUN php artisan config:cache && \
    php artisan route:cache && \
    php artisan view:cache

EXPOSE 80
CMD ["supervisord", "-c", "/etc/supervisor/supervisord.conf"]
```

### Build & Run

```bash
# Build Image
docker build -t risk-platform:latest .

# Run Container
docker run -d \
  --name risk-platform \
  -p 8080:80 \
  -v $(pwd)/.env:/var/www/html/.env \
  -v $(pwd)/storage:/var/www/html/storage \
  risk-platform:latest
```

### Docker Compose

```yaml
# docker-compose.yml
version: "3.9"

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: risk-platform
    restart: unless-stopped
    ports:
      - "8080:80"
    volumes:
      - .env:/var/www/html/.env
      - ./storage:/var/www/html/storage
    depends_on:
      - postgres
    networks:
      - risk-net

  postgres:
    image: postgres:16-alpine
    container_name: risk-postgres
    restart: unless-stopped
    environment:
      POSTGRES_DB: risk_platform_db
      POSTGRES_USER: risk_user
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - postgres-data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    networks:
      - risk-net

  scheduler:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: risk-scheduler
    restart: unless-stopped
    command: ["php", "artisan", "schedule:work"]
    volumes:
      - .env:/var/www/html/.env
    depends_on:
      - postgres
    networks:
      - risk-net

volumes:
  postgres-data:

networks:
  risk-net:
    driver: bridge
```

**Starten:**
```bash
docker-compose up -d
```

---

## Kubernetes Deployment

### Namespace erstellen

```yaml
# namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: risk-platform
```

```bash
kubectl apply -f namespace.yaml
```

### ConfigMap für Environment

```yaml
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: risk-platform-config
  namespace: risk-platform
data:
  env: |
    APP_NAME="Risk Intelligence Platform"
    APP_ENV=production
    APP_KEY=base64:xxx
    APP_DEBUG=false
    APP_URL=https://risk.example.com

    DB_CONNECTION2=pgsql
    DB_HOST2=postgres-service
    DB_PORT2=5432
    DB_DATABASE2=risk_platform_db
    DB_USERNAME2=risk_user
    DB_PASSWORD2=xxx

    CACHE_STORE=redis
    SESSION_DRIVER=redis
    QUEUE_CONNECTION=redis

    REDIS_HOST=redis-service
    REDIS_PORT=6379
```

```bash
kubectl apply -f configmap.yaml
```

### Deployment

```yaml
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: risk-platform
  namespace: risk-platform
  labels:
    app: risk-platform
spec:
  replicas: 2
  selector:
    matchLabels:
      app: risk-platform
  template:
    metadata:
      labels:
        app: risk-platform
    spec:
      containers:
      - name: app
        image: registry.example.com/risk-platform:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 80
          name: http
        env:
        - name: APP_ENV
          value: "production"
        volumeMounts:
        - name: config
          mountPath: /var/www/html/.env
          subPath: env
        - name: storage
          mountPath: /var/www/html/storage
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 10
          periodSeconds: 5
      volumes:
      - name: config
        configMap:
          name: risk-platform-config
      - name: storage
        persistentVolumeClaim:
          claimName: risk-platform-storage
```

```bash
kubectl apply -f deployment.yaml
```

### Service

```yaml
# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: risk-platform-service
  namespace: risk-platform
spec:
  selector:
    app: risk-platform
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP
```

### Ingress (Optional)

```yaml
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: risk-platform-ingress
  namespace: risk-platform
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - risk.example.com
    secretName: risk-platform-tls
  rules:
  - host: risk.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: risk-platform-service
            port:
              number: 80
```

### CronJob für Laravel Scheduler

```yaml
# cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: sync-backend-data-pool
  namespace: risk-platform
spec:
  schedule: "0 */6 * * *"  # Every 6 hours
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 3
  concurrencyPolicy: Forbid
  jobTemplate:
    spec:
      template:
        metadata:
          labels:
            app: sync-backend-data-pool
        spec:
          restartPolicy: OnFailure
          containers:
          - name: sync
            image: registry.example.com/risk-platform:latest
            command: ["php", "artisan", "schedule:run"]
            volumeMounts:
            - name: config
              mountPath: /var/www/html/.env
              subPath: env
          volumes:
          - name: config
            configMap:
              name: risk-platform-config
```

```bash
kubectl apply -f cronjob.yaml
```

### Alle Ressourcen deployen

```bash
# Complete Deployment
kubectl apply -f namespace.yaml
kubectl apply -f configmap.yaml
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml
kubectl apply -f cronjob.yaml

# Status prüfen
kubectl get all -n risk-platform

# Logs anschauen
kubectl logs -f deployment/risk-platform -n risk-platform
```

---

## Production Checklist

### Pre-Deployment

- [ ] **Environment Configuration**
  - [ ] `.env` auf `production` gesetzt
  - [ ] `APP_DEBUG=false`
  - [ ] `APP_KEY` generiert
  - [ ] Sichere Passwörter für DB

- [ ] **Database**
  - [ ] PostgreSQL läuft
  - [ ] Schemas erstellt (public, backend)
  - [ ] User-Rechte vergeben
  - [ ] Backup-Strategie definiert

- [ ] **Dependencies**
  - [ ] `composer install --no-dev --optimize-autoloader`
  - [ ] `npm ci && npm run build`

- [ ] **Laravel Optimization**
  - [ ] `php artisan config:cache`
  - [ ] `php artisan route:cache`
  - [ ] `php artisan view:cache`
  - [ ] `php artisan event:cache`

- [ ] **Security**
  - [ ] HTTPS aktiviert (SSL/TLS)
  - [ ] Firewall konfiguriert
  - [ ] `.env` nicht im Git
  - [ ] Secrets in Vault/ConfigMap

### Post-Deployment

- [ ] **Migrations**
  - [ ] `php artisan migrate --force`
  - [ ] Backup vor Migration

- [ ] **Tests**
  - [ ] Health Check (`/`)
  - [ ] Login funktioniert
  - [ ] Database Connection
  - [ ] Scheduled Jobs

- [ ] **Monitoring**
  - [ ] Logs werden geschrieben
  - [ ] Metrics werden gesammelt
  - [ ] Alerts konfiguriert

- [ ] **Performance**
  - [ ] OPcache aktiviert
  - [ ] Redis für Cache/Session
  - [ ] Database Indizes

---

## Environment Configuration

### Production .env

```ini
# Application
APP_NAME="Risk Intelligence Platform"
APP_ENV=production
APP_KEY=base64:xxx  # Generate with: php artisan key:generate
APP_DEBUG=false
APP_URL=https://risk.example.com

# Locale
APP_LOCALE=de
APP_FALLBACK_LOCALE=en

# Database (PostgreSQL)
DB_CONNECTION2=pgsql
DB_HOST2=postgres-host
DB_PORT2=5432
DB_DATABASE2=risk_platform_db
DB_USERNAME2=risk_user
DB_PASSWORD2=xxx  # Use strong password!

# Cache & Session (Redis)
CACHE_STORE=redis
SESSION_DRIVER=redis
SESSION_LIFETIME=120

# Queue
QUEUE_CONNECTION=redis

# Redis
REDIS_HOST=redis-host
REDIS_PASSWORD=null
REDIS_PORT=6379

# Mail
MAIL_MAILER=smtp
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_USERNAME=noreply@example.com
MAIL_PASSWORD=xxx
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=noreply@example.com
MAIL_FROM_NAME="${APP_NAME}"

# Logging
LOG_CHANNEL=stack
LOG_LEVEL=error  # Production: error, nicht debug!

# Security
SESSION_SECURE_COOKIE=true
SESSION_SAME_SITE=strict
```

### Secrets Management

**Kubernetes Secrets:**
```bash
# Create Secret
kubectl create secret generic risk-platform-secrets \
  --from-literal=APP_KEY=base64:xxx \
  --from-literal=DB_PASSWORD=xxx \
  --from-literal=REDIS_PASSWORD=xxx \
  -n risk-platform

# Use in Deployment
env:
- name: APP_KEY
  valueFrom:
    secretKeyRef:
      name: risk-platform-secrets
      key: APP_KEY
```

---

## Database Migration

### Pre-Migration Backup

```bash
# PostgreSQL Backup
pg_dump -h localhost -U risk_user -d risk_platform_db > backup_$(date +%Y%m%d_%H%M%S).sql

# Verify Backup
psql -h localhost -U risk_user -d risk_platform_db_test < backup_xxx.sql
```

### Run Migrations

```bash
# Production Migration
php artisan migrate --force

# With Output
php artisan migrate --force --verbose

# Rollback (if needed)
php artisan migrate:rollback --force
```

### Zero-Downtime Migration

```bash
# 1. Maintenance Mode
php artisan down --message="Updating..." --retry=60

# 2. Pull latest code
git pull origin main

# 3. Update dependencies
composer install --no-dev --optimize-autoloader

# 4. Run migrations
php artisan migrate --force

# 5. Clear & cache
php artisan optimize:clear
php artisan config:cache
php artisan route:cache
php artisan view:cache

# 6. Restart services
sudo supervisorctl restart all

# 7. Exit maintenance mode
php artisan up
```

---

## Monitoring & Logging

### Application Logs

```bash
# Laravel Logs
tail -f storage/logs/laravel.log

# Nur Errors
tail -f storage/logs/laravel.log | grep ERROR

# Mit Laravel Pail
php artisan pail --filter=error
```

### Nginx Logs

```bash
# Access Log
tail -f /var/log/nginx/access.log

# Error Log
tail -f /var/log/nginx/error.log
```

### Kubernetes Logs

```bash
# Pod Logs
kubectl logs -f deployment/risk-platform -n risk-platform

# Alle Pods
kubectl logs -f -l app=risk-platform -n risk-platform

# CronJob Logs
kubectl logs -f cronjob/sync-backend-data-pool -n risk-platform
```

### Health Checks

```bash
# Application Health
curl https://risk.example.com/

# Database Connection
php artisan tinker
>>> DB::connection()->getPdo()

# Queue Status
php artisan queue:monitor

# Scheduler Status
php artisan schedule:list
```

### Monitoring-Tools (Optional)

**Laravel Telescope:**
```bash
composer require laravel/telescope --dev
php artisan telescope:install
php artisan migrate
```

**Prometheus + Grafana:**
- Metrics-Export via Laravel Package
- Custom Dashboards für Transactions, Companies
- Alerts bei hoher Error-Rate

---

## Backup & Recovery

### Automated Backup Script

```bash
#!/bin/bash
# backup.sh

DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backups"
DB_NAME="risk_platform_db"

# Database Backup
pg_dump -h localhost -U risk_user $DB_NAME > $BACKUP_DIR/db_$DATE.sql

# Storage Backup
tar -czf $BACKUP_DIR/storage_$DATE.tar.gz storage/

# Keep only last 7 days
find $BACKUP_DIR -type f -mtime +7 -delete

echo "Backup completed: $DATE"
```

**Crontab:**
```bash
# Daily backup at 2 AM
0 2 * * * /path/to/backup.sh >> /var/log/backup.log 2>&1
```

### Kubernetes Backup

```yaml
# backup-cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: database-backup
  namespace: risk-platform
spec:
  schedule: "0 2 * * *"  # Daily at 2 AM
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: postgres:16-alpine
            command:
            - /bin/sh
            - -c
            - |
              pg_dump -h postgres-service -U risk_user risk_platform_db > /backup/db_$(date +%Y%m%d).sql
            volumeMounts:
            - name: backup-storage
              mountPath: /backup
          volumes:
          - name: backup-storage
            persistentVolumeClaim:
              claimName: backup-pvc
          restartPolicy: OnFailure
```

### Recovery Procedure

```bash
# 1. Stop Application
kubectl scale deployment risk-platform --replicas=0 -n risk-platform

# 2. Restore Database
psql -h localhost -U risk_user -d risk_platform_db < backup_xxx.sql

# 3. Verify Data
psql -h localhost -U risk_user -d risk_platform_db
\dt
SELECT COUNT(*) FROM companies;

# 4. Restart Application
kubectl scale deployment risk-platform --replicas=2 -n risk-platform
```

---

## Rollback-Strategie

### Git-based Rollback

```bash
# 1. Identify previous version
git log --oneline -10

# 2. Checkout previous version
git checkout <commit-hash>

# 3. Rebuild & Deploy
docker build -t risk-platform:rollback .
docker push registry.example.com/risk-platform:rollback

# 4. Update Kubernetes
kubectl set image deployment/risk-platform \
  app=registry.example.com/risk-platform:rollback \
  -n risk-platform
```

### Database Rollback

```bash
# Rollback last migration
php artisan migrate:rollback --step=1 --force

# Rollback specific batch
php artisan migrate:rollback --batch=3 --force

# Full rollback to fresh state (CAUTION!)
php artisan migrate:fresh --force
```

### Blue-Green Deployment

```yaml
# deployment-blue.yaml (current)
metadata:
  name: risk-platform-blue
  labels:
    app: risk-platform
    version: blue

# deployment-green.yaml (new version)
metadata:
  name: risk-platform-green
  labels:
    app: risk-platform
    version: green

# Switch Traffic
# Change service selector from blue to green
kubectl patch service risk-platform-service \
  -p '{"spec":{"selector":{"version":"green"}}}' \
  -n risk-platform
```

---

## Troubleshooting

### Problem: Container startet nicht

**Diagnose:**
```bash
docker logs risk-platform
kubectl logs deployment/risk-platform -n risk-platform
```

**Häufige Ursachen:**
- `.env` fehlt oder ungültig
- Database Connection fehlgeschlagen
- Permissions auf `storage/` fehlen

**Lösung:**
```bash
# Check .env
docker exec -it risk-platform cat /var/www/html/.env

# Fix permissions
docker exec -it risk-platform chown -R nginx:nginx storage
```

---

### Problem: "500 Internal Server Error"

**Diagnose:**
```bash
# Laravel Logs
tail -f storage/logs/laravel.log

# Nginx Error Log
tail -f /var/log/nginx/error.log
```

**Häufige Ursachen:**
- `APP_KEY` nicht gesetzt
- Config Cache veraltet
- Database Connection Error

**Lösung:**
```bash
# Generate APP_KEY
php artisan key:generate --force

# Clear caches
php artisan optimize:clear

# Test DB connection
php artisan tinker
>>> DB::connection()->getPdo()
```

---

### Problem: Scheduled Jobs laufen nicht

**Diagnose:**
```bash
# Check CronJob Status
kubectl get cronjobs -n risk-platform

# Check Job History
kubectl get jobs -n risk-platform

# Check Logs
kubectl logs job/sync-backend-data-pool-xxx -n risk-platform
```

**Lösung:**
```bash
# Test Schedule manually
php artisan schedule:run

# Test specific Job
php artisan backend:sync-data-pool --incremental
```

---

### Problem: High Memory Usage

**Diagnose:**
```bash
# Container Stats
docker stats risk-platform

# Pod Resource Usage
kubectl top pod -n risk-platform
```

**Lösung:**
- Reduce batch size in Jobs
- Increase memory limits
- Enable OPcache
- Use Redis for cache/session

---

## Performance Optimization

### OPcache Configuration

```ini
; /etc/php82/conf.d/opcache.ini
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.revalidate_freq=60
opcache.fast_shutdown=1
```

### Redis Configuration

```yaml
# redis.conf
maxmemory 512mb
maxmemory-policy allkeys-lru
```

### Database Optimization

```sql
-- Index on frequently queried columns
CREATE INDEX idx_transactions_status ON transactions(status);
CREATE INDEX idx_transactions_risk_score ON transactions(risk_score);
CREATE INDEX idx_companies_kyc_risk_level ON companies(kyc_risk_level);

-- Vacuum regularly
VACUUM ANALYZE companies;
VACUUM ANALYZE transactions;
```

---

## Security Best Practices

### SSL/TLS

```yaml
# ingress.yaml with TLS
spec:
  tls:
  - hosts:
    - risk.example.com
    secretName: risk-platform-tls
```

### Firewall Rules

```bash
# Allow HTTP/HTTPS only
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
```

### Security Headers

```nginx
# nginx.conf
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
```

---

## Zusammenfassung

### Deployment-Optionen

| Option | Komplexität | Skalierbarkeit | Empfohlen für |
|--------|-------------|----------------|---------------|
| **Docker** | Niedrig | Mittel | Development, Small Production |
| **Kubernetes** | Hoch | Hoch | Production, Enterprise |
| **Traditional** | Mittel | Niedrig | Legacy Systems |

### Checkliste für Production

✅ Environment auf `production` gesetzt
✅ `APP_DEBUG=false`
✅ HTTPS aktiviert
✅ Database-Backup automatisiert
✅ Monitoring & Logging konfiguriert
✅ Scheduled Jobs laufen
✅ Health Checks aktiv
✅ Secrets sicher gespeichert
✅ Rollback-Strategie getestet

---

**Erstellt:** 2025-11-24
**Version:** 1.0
**Autor:** Risk Intelligence Platform Team
