Krayin CRM mit Docker installieren: Laravel-basiertes Vertriebs-CRM als HubSpot-Alternative
Krayin CRM ist ein Laravel-basiertes Open-Source-CRM mit 22.9k GitHub-Stars – kostenlose HubSpot-Alternative mit Lead-Management, Verkaufspipelines und KI-Inhaltsassistenz. Diese Anleitung zeigt dir, wie du es per Docker Compose in 15 Minuten auf jedem Linux-Host startest.

Krayin CRM ist ein vollständiges, Laravel-basiertes Open-Source-CRM-System, das von Webkul entwickelt wird und mit 22.9k GitHub-Stars zu den aktivsten CRM-Projekten im Self-Hosting-Bereich gehört. Es richtet sich an wachsende Vertriebsteams, die eine kostenlose Alternative zu HubSpot oder Pipedrive suchen – ohne SaaS-Zwang, ohne versteckte Kosten, MIT-lizenziert und auch für den kommerziellen Einsatz freigegeben. Der Funktionsumfang umfasst Lead- und Kontaktverwaltung, Verkaufspipelines, Aktivitätsverfolgung, E-Mail-Integration und eine KI-gestützte Inhaltsassistenz. Das offizielle All-in-One-Docker-Image webkul/krayin bringt Apache, MySQL 8.0, PHP 8.3 und Supervisor in einem einzigen Container mit – ideal für einen schnellen Start ohne komplexes Multi-Container-Setup.
Voraussetzungen
- Docker Engine 24.x oder neuer sowie das Docker Compose Plugin v2 (
docker compose, nicht das altedocker-compose) auf einem Linux-Host installiert – falls noch nicht geschehen, hilft die Anleitung Docker und Docker Compose auf Linux installieren. - Architektur: linux/amd64 (x86_64) zwingend – es gibt kein offizielles ARM64-Image. Auf Apple Silicon (M1/M2/M3) oder ARM-Servern ist ein Workaround mit
platform: linux/amd64und QEMU-Emulation möglich, aber deutlich langsamer und für Produktion nicht empfohlen. - Mindestens 3 GB RAM, empfohlen 4 GB oder mehr; mindestens 2 GB freier Speicherplatz für Image und Daten.
- Internetzugang für
docker pull– das Image ist ca. 732 MB groß. - Offene Firewall-Ports: Host-Port deiner Wahl (Standard in dieser Anleitung: 8080); für HTTPS-Betrieb einen Reverse Proxy (Traefik, Caddy, Nginx Proxy Manager) vorschalten.
- curl für die Verifikationsschritte (auf den meisten Linux-Systemen bereits installiert).
Schritt 1: Projektordner und .env-Datei anlegen
Lege einen dedizierten Projektordner an. Alle Konfigurationsdateien landen dort; Docker-Volumes werden separat von Docker selbst verwaltet.
mkdir -p /opt/krayin
cd /opt/krayinErstelle die .env-Datei mit einem sicheren Datenbankpasswort. Dieses Passwort wird beim ersten Start in die MySQL-Datenbank geschrieben – es lässt sich später ohne Datenverlust nur durch direktes Ändern im Container oder per Volume-Reset ändern.
# /opt/krayin/.env
# Dieses Passwort wird beim ersten Container-Start gesetzt.
# Mindestens 16 Zeichen, Sonderzeichen erlaubt.
KRAYIN_DB_PASSWORD=MeinSicheresPasswort123!Die .env-Datei darf nicht ins Git-Repository; lege sie im .gitignore aus und sichere sie gesondert.
Verifizieren: Datei vorhanden und Passwort gesetzt?
ls -la /opt/krayin/.env
# Erwartete Ausgabe: -rw------- 1 root root ... /opt/krayin/.envSchritt 2: compose.yaml erstellen
Das All-in-One-Image webkul/krayin:2.2.0 beinhaltet MySQL intern – es braucht keinen separaten Datenbank-Container. Für Produktion mit getrenntem MySQL-Backup empfiehlt sich das Build-Setup aus dem krayin-docker-Repository; für den schnellen Einstieg ist das folgende Setup die einfachste Wahl. Named Volumes sichern die Persistenz der MySQL-Daten (krayin_mysql) und der Anwendungsdaten wie Uploads und Logs (krayin_storage).
# /opt/krayin/compose.yaml
services:
krayin:
image: webkul/krayin:2.2.0
container_name: krayin
restart: unless-stopped
ports:
- "8080:80"
volumes:
- krayin_storage:/var/www/html/storage
- krayin_mysql:/var/lib/mysql
environment:
APP_URL: "http://localhost:8080"
APP_DEBUG: "false"
DB_DATABASE: krayin
DB_USERNAME: krayin
DB_PASSWORD: ${KRAYIN_DB_PASSWORD:-changeme_sicher}
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/admin/login"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
volumes:
krayin_storage:
krayin_mysql:Wichtig: APP_URL muss exakt der Adresse entsprechen, über die du Krayin erreichst – inklusive Port, falls dieser nicht 80 oder 443 ist. Bei Zugriff über eine eigene Domain oder IP einfach den Wert anpassen. Falsch gesetztes APP_URL führt zu kaputten Asset-URLs und fehlschlagenden Redirects.
Verifizieren: YAML-Syntax korrekt?
docker compose -f /opt/krayin/compose.yaml config
# Erwartete Ausgabe: die aufgelöste Konfiguration ohne FehlermeldungSchritt 3: Container starten
Starte Krayin CRM im Hintergrund. Beim allerersten Start lädt Docker das Image herunter (~732 MB) und führt automatisch die Laravel-Installationsroutine php artisan krayin-crm:install inklusive Datenbank-Migrationen und Seeding aus. Das dauert je nach Verbindungsgeschwindigkeit und Hardware 5–10 Minuten.
cd /opt/krayin
docker compose up -dVerifizieren: Läuft der Container und zeigt er „healthy"?
docker compose ps
# Erwartete Ausgabe (nach ca. 2-3 Minuten):
# NAME IMAGE COMMAND SERVICE STATUS PORTS
# krayin webkul/krayin:2.2.0 ... krayin Up (healthy) 0.0.0.0:8080->80/tcp
# Logs verfolgen (Strg+C zum Beenden):
docker compose logs -f krayin
# Warte auf Zeilen wie:
# "Krayin CRM installed successfully"
# "AH00558: apache2: ... httpd started"Sollte der Status noch starting zeigen, warte weitere 2–3 Minuten und führe docker compose ps erneut aus. Die Datenbank-Migration beim ersten Start benötigt etwas Zeit.
Schritt 4: HTTP-Erreichbarkeit prüfen
Bevor du den Browser öffnest, prüfe mit curl, ob der Container HTTP-Antworten liefert.
curl -I http://localhost:8080/admin/login
# Erwartete Ausgabe:
# HTTP/1.1 200 OK
# Content-Type: text/html; charset=UTF-8
# ...Ein HTTP/1.1 302 Found auf die Login-Seite ist ebenfalls korrekt – der Redirect leitet auf /admin/login weiter. Bekommst du curl: (7) Failed to connect, ist der Container noch nicht vollständig gestartet oder der Port ist belegt (siehe Troubleshooting).
Verifizieren: HTTP-Statuscode 200 oder 302 bei /admin/login – alles in Ordnung.
Schritt 5: Erst-Einrichtung im Browser
Öffne http://localhost:8080/admin/login (oder ersetze localhost durch die IP/Domain deines Servers) im Browser.
Die Standard-Zugangsdaten nach der Installation lauten:
| Feld | Wert |
|---|---|
| admin@example.com | |
| Passwort | admin123 |
Diese Zugangsdaten sind öffentlich bekannt – ändere das Passwort unmittelbar nach dem ersten Login! Navigiere nach dem Einloggen zu den Profil-Einstellungen und setze ein starkes Passwort. Alternativ per Artisan-Befehl im Container:
docker exec -it krayin php artisan tinker
# Im Tinker-Prompt:
# User::find(1)->update(['password' => bcrypt('DeinNeuesPasswort!')]);
# exitErkunde anschließend die wichtigsten Bereiche: Leads (Vertriebschancen anlegen), Contacts (Kontakte und Organisationen verwalten), Activities (Anrufe, Meetings, E-Mails protokollieren) und Settings (Pipelines, Nutzer, Rollen konfigurieren).
Verifizieren: Login erfolgreich, Dashboard lädt ohne Fehler, Passwort geändert.
Schritt 6: HTTPS und Reverse Proxy (empfohlen)
Das Standard-Image liefert nur HTTP. Für den Produktivbetrieb oder den Zugriff aus dem Internet ist HTTPS Pflicht. Schalte einen Reverse Proxy vor den Krayin-Container und setze APP_URL in der compose.yaml auf https://crm.deine-domain.de.
Eine bewährte Kombination ist Traefik mit automatischem HTTPS – die Einrichtung beschreibt die Anleitung Traefik als Docker-Reverse-Proxy mit automatischem HTTPS. Alternativ funktioniert auch Caddy oder Nginx Proxy Manager genauso gut.
Nach der Proxy-Konfiguration APP_URL in der .env oder direkt in der compose.yaml anpassen und Container neu starten:
cd /opt/krayin
docker compose up -d --force-recreateVerifizieren:
curl -I https://crm.deine-domain.de/admin/login
# Erwartete Ausgabe: HTTP/2 200 (oder 302) mit gültigem TLS-ZertifikatSchritt 7: Updates und Datensicherung
Neue Krayin-Versionen erscheinen als neuer Image-Tag auf Docker Hub. Vor jedem Update unbedingt die Datenbank sichern:
# MySQL-Dump aus dem laufenden Container erstellen:
docker exec krayin mysqldump -u krayin -p"${KRAYIN_DB_PASSWORD}" krayin > /opt/krayin/backup-$(date +%Y%m%d).sql
# Image aktualisieren (Tag in compose.yaml anpassen, z.B. auf 2.2.3):
# image: webkul/krayin:2.2.3
docker compose pull
docker compose up -d
# Laravel-Migrationen nach dem Update ausführen:
docker exec krayin php artisan migrate --forceNamed Volumes (krayin_storage und krayin_mysql) bleiben bei docker compose down erhalten – niemals docker compose down -v auf Produktionsdaten anwenden, da das Flag alle Volumes unwiderruflich löscht. Zur Backup-Strategie empfiehlt sich die Anleitung MySQL & PostgreSQL Backup automatisieren mit cron.
Verifizieren:
docker compose ps
# STATUS: Up (healthy)
docker exec krayin php artisan --version
# Erwartete Ausgabe: Laravel Framework 11.x.x (oder neuer)Eckdaten auf einen Blick
| Eigenschaft | Wert |
|---|---|
| Image | webkul/krayin:2.2.0 |
| Aktuelle stabile Version | 2.2.3 (Mai 2026) |
| Image-Größe | ca. 732 MB |
| Architektur | linux/amd64 only (kein ARM64) |
| Interner Port | 80 (HTTP) |
| Host-Port (Beispiel) | 8080 |
| PHP-Version im Image | 8.3 |
| MySQL-Version im Image | 8.0 |
| Lizenz | MIT |
| Setup-Zeit (All-in-One) | ca. 5–10 Minuten |
| Umgebungsvariable | Pflicht | Beschreibung |
|---|---|---|
| APP_URL | ja | Erreichbare URL inkl. Port (z.B. http://localhost:8080) |
| APP_DEBUG | nein | Debug-Modus; niemals true in Produktion |
| DB_DATABASE | ja | Datenbankname (Standard: krayin) |
| DB_USERNAME | ja | Datenbankbenutzer (Standard: krayin) |
| DB_PASSWORD | ja | Datenbankpasswort – sicher wählen! |
| Volume / Pfad im Container | Inhalt | Persistenz |
|---|---|---|
| /var/www/html/storage | Logs, Uploads, Cache | Named Volume krayin_storage |
| /var/lib/mysql | MySQL-Datenbankdaten | Named Volume krayin_mysql |
Troubleshooting / Typische Fehler
- „exec format error" / Container startet nicht auf ARM: Das Image ist nur für linux/amd64 gebaut. Auf Apple Silicon oder ARM-Servern:
platform: linux/amd64in dercompose.yamlunter dem Service ergänzen und QEMU aktivieren (docker run --privileged --rm tonistiigi/binfmt --install all). Für Produktion nicht empfohlen. - „port is already allocated" / Port 8080 belegt: Auf dem Host läuft bereits ein Dienst auf diesem Port. Anderen Host-Port wählen, z.B.
"9090:80", undAPP_URLentsprechend anpassen. - „SQLSTATE[HY000] [2002] Connection refused": MySQL im Container ist noch nicht bereit. Kurz warten und dann
docker compose restart krayinausführen. Der Healthcheck undstart_period: 60sin dercompose.yamlmildern dieses Problem ab. - HTTP 500 / „Permission denied" auf Storage: Fehlende Schreibrechte auf
/var/www/html/storage. Beheben mit:docker exec krayin bash -c "chmod -R 775 /var/www/html/storage && chown -R www-data:www-data /var/www/html/storage" - Asset-URLs kaputt / Redirect-Schleife:
APP_URLstimmt nicht mit der tatsächlich verwendeten Adresse überein. Wert in dercompose.yamlkorrigieren, danndocker compose up -d --force-recreate. - Datenverlust nach
docker compose down -v: Das-v-Flag löscht Named Volumes unwiderruflich. Niemals mit Produktionsdaten verwenden – nurdocker compose downohne Flags für normales Stoppen. - Composer „Allowed memory size exhausted" (nur Build-Variante): Bei VMs mit weniger als 1 GB RAM schlägt
composer installfehl. UmgebungsvariableCOMPOSER_MEMORY_LIMIT=-1im Container setzen. - setup.sh checkt veraltete Version aus (nur krayin-docker Build-Variante): Das offizielle
setup.shim krayin-docker-Repository checkt noch v2.0.1 aus. Für die aktuelle Version 2.2.x muss der Checkout-Befehl insetup.shauf den gewünschten Tag angepasst werden.
Häufige Fragen
Welches Setup soll ich wählen: All-in-One-Image oder Build-Variante?
Das All-in-One-Image webkul/krayin:2.2.0 ist die einfachste Wahl für Tests, kleine Teams oder den ersten produktiven Betrieb. Alles – Apache, MySQL, PHP – läuft in einem Container; keine externe Datenbank nötig. Die Build-Variante über das krayin-docker-Repository trennt PHP/Apache, MySQL und PHPMyAdmin in separate Container und bietet mehr Flexibilität: eigenes MySQL-Backup-Scheduling, separates Volume-Management, direkter PHPMyAdmin-Zugang. Für Produktion mit strengen Backup-Anforderungen ist die Build-Variante besser geeignet; für alle anderen Fälle reicht das All-in-One-Image.
Wie ändere ich das Admin-Passwort?
Nach dem ersten Login unter /admin/login mit den Standard-Zugangsdaten (admin@example.com / admin123) über die Profil-Einstellungen das Passwort ändern. Alternativ per Artisan-Tinker direkt im Container: docker exec -it krayin php artisan tinker, dann User::find(1)->update(['password' => bcrypt('NeuesPasswort!')]);
Kann ich eine externe MySQL-Datenbank verwenden?
Ja. Die Umgebungsvariablen DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME und DB_PASSWORD auf den externen Server setzen. Das Volume krayin_mysql dann nicht mounten. Der externe MySQL-Benutzer benötigt alle Rechte (GRANT ALL PRIVILEGES) auf die Krayin-Datenbank.
Läuft Krayin auf einem Raspberry Pi oder ARM-Server?
Nicht offiziell. Es gibt kein ARM64-Image. Mit platform: linux/amd64 und aktivierter QEMU-Emulation kann es starten, ist aber deutlich langsamer und für Produktion nicht empfohlen. Auf echter x86_64-Hardware oder einer amd64-VM ist Krayin die deutlich bessere Wahl.
Wie aktualisiere ich Krayin auf eine neue Version?
Image-Tag in der compose.yaml auf die neue Version anpassen (z.B. von 2.2.0 auf 2.2.3), dann docker compose pull && docker compose up -d. Anschließend Migrationen ausführen: docker exec krayin php artisan migrate --force. Vorher immer einen MySQL-Dump erstellen.
Wie sichere ich die Daten regelmäßig?
MySQL-Dump aus dem Container: docker exec krayin mysqldump -u krayin -p"${KRAYIN_DB_PASSWORD}" krayin > backup.sql. Named Volumes lassen sich außerdem mit docker run --rm -v krayin_mysql:/data -v $(pwd):/backup alpine tar czf /backup/krayin_mysql.tar.gz /data sichern. Die Anleitung MySQL & PostgreSQL Backup automatisieren mit cron zeigt, wie du das mit Rotation und Cloud-Sync vollautomatisch einrichtest.
Wie sichere ich den Zugang ab, wenn Krayin öffentlich erreichbar ist?
Neben dem sofortigen Passwort-Wechsel (Standard-Credentials sind öffentlich bekannt!): HTTPS über einen Reverse Proxy erzwingen, APP_DEBUG=false sicherstellen und den Admin-Port nicht direkt ohne Firewall-Schutz exponieren. Eine umfassende Härtung für selbstgehostete Dienste beschreibt die Anleitung Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only.
Fazit
Krayin CRM überzeugt als kostenlose, MIT-lizenzierte HubSpot-Alternative für Vertriebsteams, die ihre Daten lieber selbst verwalten als in eine SaaS-Abhängigkeit zu gehen. Das All-in-One-Docker-Image macht den Einstieg erfreulich unkompliziert: Ordner anlegen, .env mit Passwort befüllen, compose.yaml ablegen, docker compose up -d – nach 10 Minuten steht ein vollständiges CRM mit Lead-Management, Pipeline-Ansicht und KI-Inhaltsassistenz bereit. Die ehrlichen Einschränkungen: Nur amd64, das All-in-One-Image eignet sich nicht für High-Availability-Setups, und für Produktionsumgebungen mit strikten Backup-Anforderungen lohnt sich der Blick auf das Build-basierte Multi-Container-Setup. Wer eine schlankere Lösung für persönliche Kontakt- und Beziehungspflege sucht, findet mit Monica CRM eine gute Ergänzung aus der gleichen Kategorie.
Weiterführende Anleitungen und Quellen
- Docker und Docker Compose auf Linux installieren (Ubuntu/Debian)
- Traefik als Docker-Reverse-Proxy mit automatischem HTTPS einrichten
- MySQL & PostgreSQL Backup automatisieren mit cron
- Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only
- Monica CRM mit Docker installieren: Persönliches CRM für Kontakte
Offizielle Quellen: Krayin CRM Developer Docs – Docker | Krayin CRM GitHub Repository | krayin/krayin-docker auf GitHub | webkul/krayin auf Docker Hub