Files
leocrm/DEPLOY.md
T

217 lines
6.8 KiB
Markdown

# LeoCRM Deployment
## Architektur
LeoCRM läuft als **einzelner docker-compose Stack** in Coolify. Alle 4 Container
(PostgreSQL, Redis, API, Worker) werden aus der `docker-compose.yaml` im Git-Repo
gestartet und teilen sich ein Docker-Netzwerk.
```
┌─────────────────────────────────────────────┐
│ Coolify Application (docker-compose) │
│ ┌──────────┐ ┌──────────┐ │
│ │ postgres │ │ redis │ │
│ └────┬─────┘ └────┬─────┘ │
│ │ │ │
│ ┌────┴─────┐ ┌────┴─────┐ │
│ │ crm_app │ │crm_worker│ │
│ │ (API) │ │ (ARQ) │ │
│ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────┘
```
Keine separaten Coolify Services für DB/Redis/Worker. Alles in einem Stack.
## Quick Start
### Redeploy (bestehende Anwendung)
```bash
# Umgebungsvariablen setzen
export COOLIFY_API_TOKEN="dein-token"
export APP_DOMAIN="https://crm.media-on.de"
export COOLIFY_APP_UUID="xf7smknlger3hvkrsb910tui" # optional, wird via APP_NAME gesucht
# Redeploy via Coolify API
python scripts/deploy.py
# Verifikation nur
python scripts/deploy.py --verify-only
```
Das Script macht automatisch:
1. Coolify Application auflösen (via UUID oder Name)
2. Deploy via `/api/v1/deploy` triggern
3. Auf Deployment-Erfolg warten
4. HTTP Health-Check verifizieren
5. Login-Test (optional, wenn LOGIN_EMAIL/LOGIN_PASSWORD gesetzt)
6. Alembic-Migration-Head prüfen (via SSH)
7. RLS-Tabellen zählen (via SSH)
### Initial Deployment (neue Anwendung)
```bash
# Alle Umgebungsvariablen setzen
export COOLIFY_API_TOKEN="dein-token"
export APP_DOMAIN="https://crm.media-on.de"
export APP_NAME="leocrm" # Coolify Application Name
export DB_PASSWORD="..."
export REDIS_PASSWORD="..."
export SECRET_KEY="..."
export COOLIFY_PROJECT_UUID="..."
export COOLIFY_SERVER_UUID="..."
export COOLIFY_PRIVATE_KEY_UUID="..."
export COOLIFY_ENVIRONMENT="production" # optional, default: production
# Initial deployment
python scripts/deploy.py --initial
```
Das Script macht automatisch:
1. Coolify Application via `private-deploy-key` erstellen
2. Build Pack auf `dockercompose` setzen (liest docker-compose.yaml aus Git)
3. Environment-Variablen setzen (Secrets, Domain, Admin-Credentials)
4. Erster Deploy (ohne Domain — Coolify muss docker-compose.yaml lesen)
5. `docker_compose_domains` setzen + Redeploy (mit Traefik-Labels)
6. Verifikation (HTTP, Login, Alembic, RLS)
### Option B: Docker Compose (lokal / ohne Coolify)
```bash
# .env.docker erstellen
cp .env.docker.example .env.docker
$EDITOR .env.docker # SECRET_KEY, DB_PASSWORD, REDIS_PASSWORD etc. ausfüllen
# Starten (alle 4 Container: Postgres, Redis, App, Worker)
docker compose --env-file .env.docker up --build -d
# Health check
curl http://localhost:8000/api/v1/health
# Stoppen
docker compose down
```
**Container:**
- `postgres` — PostgreSQL 16 mit pgvector
- `redis` — Redis 7
- `crm_app` — FastAPI API Server
- `crm_worker` — ARQ Background Worker
Alle mit persistenten Volumes. Kein Datenverlust bei Redeploy.
## Voraussetzungen
- Python 3.12+
- `httpx` Python package
- Docker & Docker Compose (für Option B)
- Coolify v4+ (für Option A)
- SSH-Zugang zum Server (für Verifikation, Option A)
## Umgebungsvariablen
Siehe `.env.example` für alle Variablen. Wichtigste:
| Variable | Pflicht | Default | Beschreibung |
|---|---|---|---|
| `COOLIFY_API_TOKEN` | Ja | — | Coolify API Token |
| `APP_DOMAIN` | Ja | — | App-Domain (z.B. https://crm.media-on.de) |
| `COOLIFY_APP_UUID` | Nein | — | Application UUID (auto-resolved via APP_NAME) |
| `APP_NAME` | Nein | abgeleitet aus APP_DOMAIN | Coolify Application Name |
| `SSH_KEY` | Nein | `/a0/usr/workdir/.ssh/coolify-01-root` | SSH Key für Verifikation |
| `SERVER_IP` | Nein | `46.225.91.159` | Server IP für SSH |
| `LOGIN_EMAIL` | Nein | — | Login-Test Email (optional) |
| `LOGIN_PASSWORD` | Nein | — | Login-Test Passwort (optional) |
### Nur für `--initial`:
| Variable | Pflicht | Beschreibung |
|---|---|---|
| `DB_PASSWORD` | Ja | PostgreSQL Passwort |
| `REDIS_PASSWORD` | Ja | Redis Passwort |
| `SECRET_KEY` | Ja | Application Secret Key (min. 32 Zeichen) |
| `COOLIFY_PROJECT_UUID` | Ja | Coolify Project UUID |
| `COOLIFY_SERVER_UUID` | Ja | Coolify Server UUID |
| `COOLIFY_PRIVATE_KEY_UUID` | Ja | Coolify Private Deploy Key UUID |
| `COOLIFY_ENVIRONMENT` | Nein | Coolify Environment (default: production) |
## S3 Storage (optional)
Die App unterstützt S3-kompatiblen Storage. Setze:
```bash
STORAGE_BACKEND=s3
S3_ENDPOINT=https://s3.example.com
S3_BUCKET=leocrm
S3_ACCESS_KEY=...
S3_SECRET_KEY=...
```
## Mehrere Instanzen
Mehrere LeoCRM-Instanzen auf demselben Coolify-Server:
```bash
# Test-Instanz
APP_NAME=leocrm-test APP_DOMAIN=https://crm-test.media-on.de python scripts/deploy.py --initial
# Produktions-Instanz
APP_NAME=leocrm APP_DOMAIN=https://crm.media-on.de python scripts/deploy.py --initial
```
Jede Instanz hat eigene DB, Redis, Container und Domain.
## Troubleshooting
**Container nicht healthy:**
```bash
docker logs <container-name> --tail 50
```
**Migration fehlgeschlagen:**
```bash
docker exec <container> alembic upgrade head
```
**503 Fehler (Traefik):**
- Domain ohne `:443` in `docker_compose_domains` setzen
- Service-Namen mit Unterstrichen in docker-compose.yaml (crm_app, nicht crm-app)
- `docker-compose.yaml` (nicht `.yml`) als Dateiname
## Backup & Restore
### Backup (PostgreSQL)
```bash
# Full DB backup (run on the host or via docker exec)
docker exec <postgres-container> pg_dump -U crm_user -Fc crm_db > backup_$(date +%Y%m%d_%H%M%S).dump
```
### Backup (Redis — Sessions/Queues)
```bash
docker exec <redis-container> redis-cli -a "$REDIS_PASSWORD" SAVE
docker cp <redis-container>:/data/dump.rdb redis_backup_$(date +%Y%m%d).rdb
```
### Restore (PostgreSQL)
```bash
# Stop app containers
docker compose stop crm_app crm_worker
# Restore DB
docker exec -i <postgres-container> pg_restore -U crm_user -d crm_db --clean < backup_20260726.dump
# Restart app
docker compose start crm_app crm_worker
```
### Automatisierte Backups (Cron)
```bash
# /etc/cron.d/leocrm-backup
0 2 * * * root docker exec <postgres-container> pg_dump -U crm_user -Fc crm_db > /backups/leocrm_$(date +\%Y\%m\%d).dump
0 3 * * * root find /backups -name 'leocrm_*.dump' -mtime +30 -delete
```
**Empfehlung:** Tägliche DB-Backups, 30 Tage Aufbewahrung. Storage-Backup wöchentlich.