217 lines
6.8 KiB
Markdown
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.
|