Dieses Handbuch richtet sich an Founder, die The-Y CRM selbst hosten. Es deckt den laufenden Betrieb ab: den Docker-Stack, Updates, Backup & Restore, die wichtigsten Umgebungsvariablen, Reverse-Proxy/TLS, Monitoring und die Lizenz. Für Erstinstallation & Server-Größe siehe Installation und Server-Anforderungen.
The-Y läuft als Docker-Compose-Stack. Die Dienste:
| Dienst | Zweck |
|---|---|
app | die Web-App (Next.js) — bindet intern auf Port 3000 |
worker | Hintergrund-Jobs (E-Mail-Abruf, Erinnerungen, Sweeps, Automatisierungs-Scheduler) |
postgres | Datenbank (alle Mandantendaten) |
redis | Job-Queue (BullMQ) |
minio | Datei-/Medien-Speicher (Anhänge, Aufnahmen) — S3-kompatibel |
caddy | Reverse-Proxy mit automatischem HTTPS |
watchtower | optionaler Auto-Updater (nächtlicher Image-Pull) |
optional: asterisk, coturn, piper | Telefonanlage, TURN (WebRTC), neuronale Sprachansagen |
Zwei Wege — beide ziehen die neuen Images von Docker Hub:
watchtower-Dienst im Self-Host-Bundle zieht nächtlich neue :latest-Images für app/worker und startet sie neu. Ein Banner in der App meldet neue Versionen (Update-Check gegen crm.the-y.at).cd ~/the-y-crm docker compose pull app worker docker compose up -d app worker
migrate vor start aus) — kein separater Schritt nötig.Sichere regelmäßig drei Dinge: die Postgres-Datenbank, das MinIO-Volume (Dateien/Medien) und deine .env (enthält u. a. den Verschlüsselungsschlüssel — ohne ihn sind verschlüsselte Secrets verloren!).
# 1) Datenbank-Dump cd ~/the-y-crm docker compose exec -T postgres pg_dump -U crm crm | gzip > db-$(date +%F).sql.gz # 2) MinIO-Volume (Dateien/Medien) docker run --rm -v the-y-crm_minio-data:/data -v "$PWD":/backup alpine \ tar czf /backup/minio-$(date +%F).tgz -C /data . # 3) .env sichern (enthält APP_ENCRYPTION_KEY!) cp .env env-$(date +%F).bak
Lege die drei Dateien an einen getrennten Ort (anderer Server/Storage). Automatisiere das per Cron.
# DB zurückspielen gunzip -c db-JJJJ-MM-TT.sql.gz | docker compose exec -T postgres psql -U crm crm # MinIO-Volume zurückspielen (Stack vorher stoppen) docker run --rm -v the-y-crm_minio-data:/data -v "$PWD":/backup alpine \ sh -c "rm -rf /data/* && tar xzf /backup/minio-JJJJ-MM-TT.tgz -C /data"
APP_ENCRYPTION_KEY (AES-256) verschlüsselt gespeichert. Ändert oder verlierst du diesen Schlüssel, sind alle bestehenden Secrets nicht mehr entschlüsselbar. Setze ihn einmal fest und sichere ihn (Teil deiner .env-Sicherung).Die wichtigsten Werte in deiner .env (Vorlage: .env.self-host.example). Kritische fett.
| Variable | Zweck |
|---|---|
APP_ENCRYPTION_KEY | Fester 32-Byte-Hex-Schlüssel (openssl rand -hex 32) für die Feld-Verschlüsselung. Nie ändern. |
DATABASE_URL | Postgres-Superuser-Verbindung (Migration/Skripte) |
APP_DATABASE_URL | App-Verbindung als Nicht-Superuser crm_app (erzwingt Row-Level-Security = Mandantentrennung) |
BASE_DOMAIN | deine Domain (z. B. crm.deinefirma.at) — u. a. fürs Softphone (WSS) |
TENANT_MODE | self-host: single (ein Mandant, kein Fremd-Signup) |
LICENSE_KEY | dein Founder-/Lizenzschlüssel; wird online validiert (14 Tage Offline-Toleranz) |
CONTROL_PLANE_URL | Lizenz-Prüf-Endpunkt (Standard: crm.the-y.at) |
S3_ENDPOINT / S3_BUCKET | MinIO-Anbindung (minio:9000 / crm-media) |
MINIO_ROOT_USER / _PASSWORD | MinIO-Zugangsdaten (generieren) |
PLATFORM_SMTP_* / PLATFORM_MAIL_FROM | optionaler System-Mailer (Passwort-Reset/Einladungen) ohne eigenes Postfach |
CRM_IMAGE/_WORKER_IMAGE/CRM_TAG | Docker-Hub-Images + Tag (Standard :latest) |
Telefonie: AMI_SECRET u. a. | nur bei aktivierter Telefonanlage |
Das Bundle bringt Caddy mit automatischem HTTPS mit (Let's Encrypt) — du zeigst nur deine Domain per DNS auf den Server. Betreibst du bereits nginx/Apache davor, proxie stattdessen auf die App (intern Port 3000) und terminiere TLS dort. Achte auf durchgereichte WebSocket-Verbindungen (Softphone/Realtime).
Der Endpunkt /api/public/health liefert einen einfachen Gesundheits-Status (HTTP 200 = gesund). Hänge ihn an dein Monitoring (Uptime-Check). Container-Status prüfst du mit docker compose ps, Logs mit docker compose logs -f app worker.
Der LICENSE_KEY wird regelmäßig online gegen die Control-Plane validiert; bei Ausfall gilt eine 14-Tage-Offline-Toleranz. Ist die Lizenz ungültig/abgelaufen, geht die Instanz in einen schonenden Nur-Lese-Zustand (kein harter Lockout, keine Datenlöschung). Der Funktionsumfang ist identisch zur gehosteten Version.
Fast immer hat sich der APP_ENCRYPTION_KEY geändert (z. B. neu generiert), wodurch bestehende verschlüsselte Secrets nicht mehr lesbar sind. Stelle den ursprünglichen Schlüssel aus deiner .env-Sicherung wieder her. Ist er endgültig weg, müssen die externen Secrets (Tokens/Passwörter) neu eingegeben werden.
Viele Cloud-Anbieter (Hetzner, netcup, DigitalOcean, AWS/GCP/Azure) blockieren ausgehende SMTP-Ports (25/465/587) standardmäßig als Spam-Schutz. Lass die Ports beim Anbieter freischalten (Support-Ticket) oder nutze einen HTTP-API-Mailversand. Details: Server-Anforderungen §5b.
Die Lizenzprüfung schlug fehl (ungültiger/abgelaufener Key oder länger als 14 Tage keine erfolgreiche Online-Prüfung). Prüfe LICENSE_KEY und die Erreichbarkeit der CONTROL_PLANE_URL.
docker compose logs app zeigt die Ursache. Häufig: falsche DB-Zugangsdaten, fehlender APP_ENCRYPTION_KEY oder ein belegter Port. Nach .env-Änderungen docker compose up -d --force-recreate app worker.