Files
leocrm/COOLIFY_SETUP.md
T

242 lines
7.2 KiB
Markdown
Raw Normal View History

# Coolify Setup — LeoCRM
2026-06-03 23:52:01 +00:00
Production deployment guide for LeoCRM to the Coolify PaaS instance
at `server.media-on.de`.
2026-06-03 23:52:01 +00:00
## Architektur
2026-06-03 23:52:01 +00:00
LeoCRM läuft als **einzelner docker-compose Stack** in einer Coolify Application.
Coolify liest die `docker-compose.yaml` aus dem Git-Repo und startet alle 4
Container (postgres, redis, crm_app, crm_worker) in einem gemeinsamen Stack.
2026-06-03 23:52:01 +00:00
```
Coolify Application (build_pack=dockercompose)
├── postgres (pgvector/pgvector:pg16)
├── redis (redis:7-alpine)
├── crm_app (FastAPI API Server, Port 8000)
└── crm_worker (ARQ Background Worker)
2026-06-03 23:52:01 +00:00
```
Alle Container teilen sich ein Docker-Netzwerk. Service-Namen funktionieren
als DNS-Namen (z.B. `postgres`, `redis`, `crm_app`, `crm_worker`).
**Keine separaten Coolify Services** für DB/Redis/Worker. Das funktioniert nicht,
weil Coolify jedem Service ein eigenes Netzwerk gibt und die Container sich
nicht per DNS erreichen können.
2026-06-03 23:52:01 +00:00
---
## 1. Voraussetzungen
2026-06-03 23:52:01 +00:00
- Coolify server reachable at `https://server.media-on.de`, API token created
in *Keys & Tokens → API tokens* (Bearer token, scope: `*`).
- DNS **A record** for die App-Domain (z.B. `crm.media-on.de`) zeigt auf die
öffentliche IP des Coolify-Servers.
- LeoCRM source code in Forgejo repository:
`https://forgejo.media-on.de/Leopoldadmin/leocrm.git` (branch `main`).
- Ein **Private Deploy Key** in Coolify hinterlegt (für Git-Zugriff).
- Python 3.12+ mit `httpx` für das deploy script.
2026-06-03 23:52:01 +00:00
---
## 2. Initial Deployment (automatisiert)
2026-06-03 23:52:01 +00:00
### 2.1 Umgebungsvariablen setzen
2026-06-03 23:52:01 +00:00
```bash
export COOLIFY_API_TOKEN="dein-token"
export APP_DOMAIN="https://crm.media-on.de"
export APP_NAME="leocrm"
export DB_PASSWORD="<sicheres-passwort>"
export REDIS_PASSWORD="<sicheres-passwort>"
export SECRET_KEY="<mindestens-32-zeichen>"
export COOLIFY_PROJECT_UUID="<project-uuid>"
export COOLIFY_SERVER_UUID="<server-uuid>"
export COOLIFY_PRIVATE_KEY_UUID="<private-key-uuid>"
export COOLIFY_ENVIRONMENT="production" # optional
export ADMIN_EMAIL="admin@media-on.de" # optional
export ADMIN_PASSWORD="Admin123!" # optional
```
2026-06-03 23:52:01 +00:00
### 2.2 Deploy starten
2026-06-03 23:52:01 +00:00
```bash
python scripts/deploy.py --initial
```
2026-06-03 23:52:01 +00:00
Das Script führt einen **2-Phase Deploy** durch:
2026-06-03 23:52:01 +00:00
1. **Phase 1**: Application via `private-deploy-key` erstellen, build_pack auf
`dockercompose` setzen, ENV-Variablen setzen, erster Deploy **ohne Domain**.
Coolify liest `docker-compose.yaml` aus dem Git-Repo und baut alle Container.
2026-06-03 23:52:01 +00:00
2. **Phase 2**: `docker_compose_domains` setzen (für Traefik-Labels), dann
Redeploy. Jetzt ist die App unter der Domain erreichbar.
2026-06-03 23:52:01 +00:00
### 2.3 Warum 2-Phase Deploy?
Coolify muss zuerst die `docker-compose.yaml` aus dem Git-Repo lesen, um die
Service-Namen zu kennen. Erst dann kann `docker_compose_domains` korrekt
zugeordnet werden. Ein Deploy ohne vorherigen Read der Compose-Datei führt zu
fehlenden Traefik-Labels → 503 Fehler.
2026-06-03 23:52:01 +00:00
---
## 3. Redeploy (bestehende Anwendung)
2026-06-03 23:52:01 +00:00
```bash
export COOLIFY_API_TOKEN="dein-token"
export APP_DOMAIN="https://crm.media-on.de"
export COOLIFY_APP_UUID="dx4pqdziu4uj6x9fxs1u5z0x" # optional
2026-06-03 23:52:01 +00:00
python scripts/deploy.py
2026-06-03 23:52:01 +00:00
```
Triggert `/api/v1/deploy` für die bestehende Coolify Application und wartet auf
Erfolg. Danach läuft automatisch die Verifikation (HTTP, Login, Alembic, RLS).
2026-06-03 23:52:01 +00:00
---
## 4. Verifikation
2026-06-03 23:52:01 +00:00
```bash
python scripts/deploy.py --verify-only
```
2026-06-03 23:52:01 +00:00
Prüft:
- HTTP Health (`/api/v1/health`)
- Login (optional, wenn LOGIN_EMAIL/LOGIN_PASSWORD gesetzt)
- Alembic Migration Head (via SSH in den postgres Container)
- RLS-Tabellen-Anzahl (via SSH)
2026-06-03 23:52:01 +00:00
---
## 5. Wichtige Hinweise
2026-06-03 23:52:01 +00:00
### 5.1 Service-Namen mit Unterstrichen
2026-06-03 23:52:01 +00:00
In `docker-compose.yaml` müssen Service-Namen **Unterstriche** verwenden:
`crm_app`, `crm_worker` — nicht `crm-app`, `crm-worker`.
2026-06-03 23:52:01 +00:00
Coolify konvertiert Bindestriche zu Unterstrichen in `docker_compose_domains`.
Bei Bindestrichen in der Compose-Datei gibt es keinen Match → keine
Traefik-Labels → 503 Fehler.
2026-06-03 23:52:01 +00:00
### 5.2 docker-compose.yaml (nicht .yml)
2026-06-03 23:52:01 +00:00
Coolify sucht nach `docker-compose.yaml` (mit `.yaml`). Eine Datei namens
`docker-compose.yml` wird nicht gefunden.
2026-06-03 23:52:01 +00:00
### 5.3 Domain ohne :443
2026-06-03 23:52:01 +00:00
In `docker_compose_domains` darf die Domain **kein** `:443` am Ende haben:
```
✅ https://crm.media-on.de
❌ https://crm.media-on.de:443
```
Das `:443` führt zu leeren `Host()` Traefik-Labels.
2026-06-03 23:52:01 +00:00
### 5.4 Kein connect_to_docker_network
2026-06-03 23:52:01 +00:00
Innerhalb eines docker-compose Stacks kümmert sich Coolify selbst um das
Netzwerk. `connect_to_docker_network=True` ist nicht nötig und sollte nicht
gesetzt werden.
2026-06-03 23:52:01 +00:00
---
## 6. Mehrere Instanzen
2026-06-03 23:52:01 +00:00
```bash
# Test-Instanz
APP_NAME=leocrm-test APP_DOMAIN=https://crm-test.media-on.de \
python scripts/deploy.py --initial
2026-06-03 23:52:01 +00:00
# Produktions-Instanz
APP_NAME=leocrm APP_DOMAIN=https://crm.media-on.de \
python scripts/deploy.py --initial
```
2026-06-03 23:52:01 +00:00
Jede Instanz hat eigene DB, Redis, Container und Domain. Alle Parameter werden
aus `APP_NAME` und `APP_DOMAIN` abgeleitet.
2026-06-03 23:52:01 +00:00
---
## 7. Environment-Variablen in Coolify
Das `--initial` Script setzt automatisch folgende ENV-Variablen in Coolify:
| Key | Wert | Quelle |
|-----|------|--------|
| `POSTGRES_USER` | `crm_user` | Default |
| `POSTGRES_DB` | `crm_db` | Default |
| `DB_PASSWORD` | * | ENV |
| `REDIS_PASSWORD` | * | ENV |
| `SECRET_KEY` | * | ENV |
| `ENVIRONMENT` | `production` | Default |
| `LOG_LEVEL` | `INFO` | Default |
| `SESSION_COOKIE_SECURE` | `true` | Default |
| `STORAGE_PATH` | `/data/storage` | Default |
| `CORS_ORIGINS` | APP_DOMAIN | ENV |
| `FRONTEND_URL` | APP_DOMAIN | ENV |
| `APP_DOMAIN` | APP_DOMAIN | ENV |
| `ADMIN_EMAIL` | `admin@media-on.de` | ENV (optional) |
| `ADMIN_PASSWORD` | `Admin123!` | ENV (optional) |
Die `docker-compose.yaml` verwendet `${VARIABLE}` Syntax — Coolify substituiert
aus diesen ENV-Variablen.
2026-06-03 23:52:01 +00:00
---
## 8. Healthcheck
2026-06-03 23:52:01 +00:00
In **Coolify → Application → Advanced → Healthcheck**:
2026-07-25 21:03:46 +02:00
- **Healthcheck path**: `/api/v1/health`
- **Healthcheck method**: `GET`
- **Healthcheck interval**: `30s`
- **Healthcheck timeout**: `10s`
- **Healthcheck retries**: `3`
- **Healthcheck start period**: `15s`
2026-07-25 21:03:46 +02:00
---
2026-07-25 21:03:46 +02:00
## 9. Going forward — Redeploys
2026-07-25 21:03:46 +02:00
- **Code change** → push to `main` auf Forgejo → `python scripts/deploy.py`
(oder Coolify UI → Deployments → Deploy).
- **Environment variable change** → Coolify UI (oder API `PATCH .../envs/bulk`)
→ Deploy (Coolify startet nicht automatisch bei ENV-Änderung neu).
- **Domain change** → API (`PATCH /api/v1/applications/{uuid}` mit
`docker_compose_domains`) — reproduzierbar, UI als Fallback.
2026-07-25 21:03:46 +02:00
---
2026-07-25 21:03:46 +02:00
## 10. Troubleshooting
2026-07-25 21:03:46 +02:00
**503 Fehler (Traefik):**
- Domain ohne `:443` in `docker_compose_domains`
- Service-Namen mit Unterstrichen in docker-compose.yaml
- `docker-compose.yaml` (nicht `.yml`)
2026-07-25 21:03:46 +02:00
**Container können sich nicht erreichen (DNS):**
- Alles in einem docker-compose Stack (nicht separate Coolify Services)
- Kein `connect_to_docker_network` setzen
2026-07-25 21:03:46 +02:00
**"Docker Compose file not found":**
- Datei heißt `docker-compose.yaml` (nicht `.yml`)
2026-07-25 21:03:46 +02:00
**Migration fehlgeschlagen:**
```bash
docker exec <postgres-container> psql -U crm_user -d crm_db -c "SELECT version_num FROM alembic_version"
docker exec <api-container> alembic upgrade head
```
2026-07-25 21:03:46 +02:00
---
2026-07-25 21:03:46 +02:00
## 11. Referenzen
2026-07-25 21:03:46 +02:00
- Coolify v4 API — `/a0/usr/plugins/coolify_control/help/coolify-control/help.md`
- App architecture — `architecture.md`
- Deploy script — `scripts/deploy.py`
- Install guide — `docs/INSTALL.md`