Files
leocrm/DEPLOY.md
T

6.8 KiB

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)

# 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)

# 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)

# .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:

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:

# 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:

docker logs <container-name> --tail 50

Migration fehlgeschlagen:

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)

# 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)

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)

# 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)

# /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.