Self-Hosted Installationsanleitung
Deploye MailDesk auf deiner eigenen Infrastruktur. Alle Daten bleiben auf deinen Servern.
Voraussetzungen
| Voraussetzung | Minimum |
|---|---|
| Docker Engine 24+ | |
| Docker Compose v2.20+ | |
| 4 GB RAM | |
| 20 GB Speicher (+ Anhang-Speicher) | |
| Beliebiges Linux mit Docker-Unterstützung | |
| Lizenzschlüssel von maildesk.cloud | |
1. Entpacken und laden
Paket entpacken:
tar xzf maildesk-selfhosted.tar.gz
cd maildeskDocker-Images laden:
docker load < maildesk-images.tar.gz2. Umgebung konfigurieren
./setup.shFühre ./setup.sh aus, um alle Secrets automatisch zu generieren. Dann editiere .env und setze deine APP_URL und den Lizenzschlüssel.
Öffne .env und setze folgende Werte:
Erforderliche Variablen
| Variable | Beschreibung |
|---|---|
| APP_URL | Öffentliche URL deiner Instanz (ohne abschließenden Slash) |
| MAILDESK_LICENSE_KEY | Dein Ed25519-signierter JWT-Lizenzschlüssel |
Auto-generiert durch setup.sh
Diese werden automatisch beim Ausführen von setup.sh generiert. Nicht ändern, außer bei Datenmigration.
| Variable | Beschreibung |
|---|---|
| BETTER_AUTH_SECRET | Session-Signierungsschlüssel, min. 32 Zeichen (auto-generiert) |
| CREDENTIAL_ENCRYPTION_KEY | AES-256-GCM-Schlüssel für IMAP/SMTP-Passwörter (auto-generiert) |
| POSTGRES_PASSWORD | PostgreSQL-Datenbankpasswort (auto-generiert) |
| REDIS_PASSWORD | Redis-Cache-Passwort (auto-generiert) |
| MAILDESK_MODE | Auf selfhosted gesetzt (automatisch durch setup.sh) |
Optionale Variablen
| Variable | Beschreibung |
|---|---|
| MAILDESK_LICENSE_SERVER_URL | Lizenzserver-URL für Online-Verifizierung (Standard: nur offline) |
| REGISTRATION_ENABLED | true (Standard) oder false um Selbstregistrierung zu deaktivieren |
| ALLOWED_REGISTER_IPS | Komma-getrennte IPs mit Zugriff auf /register |
| ENABLE_HSTS | true um HSTS-Header zu senden (aktivieren hinter TLS) |
| LOG_LEVEL | trace, debug, info (Standard), warn, error, fatal |
| METRICS_AUTH_TOKEN | Bearer-Token für /api/metrics Endpoint (versteckt wenn nicht gesetzt) |
| OPENAI_EMBEDDING_KEY | OpenAI API-Key für KB semantische Suche (optional) |
| MAX_ATTACHMENT_SIZE_MB | Max. Anhangsgröße in MB (Standard: 25) |
Beispiel .env für Self-Hosted
# Only these 2 lines need manual editing after running ./setup.sh:
APP_URL=https://tickets.example.com
MAILDESK_LICENSE_KEY=eyJhbGciOiJFZERTQSIs...your-key-here
# Everything else is auto-generated by ./setup.sh3. Starten
docker compose up -dDies startet 6 Services:
| Service | Zweck |
|---|---|
| migrate | Führt Datenbankmigrationen aus, dann beendet |
| app | Next.js Webanwendung (Port 3000) |
| worker | Hintergrund-Worker (IMAP/SMTP, E-Mail-Verarbeitung, Jobs) |
| postgres | PostgreSQL 17 mit pgvector-Erweiterung |
| redis | Redis 7 für Job-Queues und Pub/Sub |
| clamav | ClamAV Antivirus für Anhang-Scanning |
Der migrate-Service läuft automatisch bevor App und Worker starten. Er erstellt alle Tabellen idempotent — sicher für neue und bestehende Datenbanken.
4. Deployment verifizieren
# Check all services are healthy
docker compose ps
# Check app logs
docker compose logs app
# Check worker logs
docker compose logs worker
# Health check endpoint
curl http://localhost:3000/api/healthSobald alles healthy ist, öffne deine APP_URL im Browser. Du solltest die Login-/Registrierungsseite sehen.
5. Ersteinrichtung
- 1Registriere das erste Admin-Konto unter deine-domain.de/register
- 2Erstelle eine Organisation — das ist dein Workspace
- 3Füge eine Mailbox unter Einstellungen > Mailboxen hinzu (IMAP/SMTP-Zugangsdaten)
- 4Eingehende E-Mails erstellen automatisch Tickets
E-Mail-Verifizierung (Optional)
Konfiguriere SMTP, um E-Mail-Verifizierung für neue Benutzer zu aktivieren. Ohne SMTP werden neue Benutzer automatisch verifiziert und können sich sofort anmelden.
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=you@gmail.com
SMTP_PASS=your-app-password
SMTP_FROM=MailDesk <noreply@yourdomain.com>Reverse Proxy einrichten
MailDesk benötigt einen Reverse Proxy für TLS-Terminierung. Hier sind Beispiele für gängige Setups:
tickets.example.com {
handle /ws* {
reverse_proxy localhost:3002
}
handle {
reverse_proxy localhost:3000
}
}Lizenzschlüssel
Dein Lizenzschlüssel ist ein Ed25519-signiertes JWT, das deinen Plan, Limits und Feature-Flags enthält.
Was der Schlüssel steuert:
- Plan-Stufe (Free, Pro, Business)
- Limits: max. Agenten, Mailboxen, Tickets/Monat, Speicher
- Features: KI-Antworten, Wissensdatenbank, Auto-Übersetzung
Validierung:
- Der Schlüssel wird standardmäßig offline mit dem eingebetteten Ed25519 Public Key validiert — keine externen Aufrufe nötig
- Wenn MAILDESK_LICENSE_SERVER_URL gesetzt ist, verifiziert MailDesk den Schlüssel regelmäßig online (optional)
- Validierte Lizenzdaten werden 24 Stunden in Redis gecacht
- Bei Redis-Ausfall wird das JWT direkt verifiziert (Ed25519 braucht keinen Server)
Abgelaufener oder ungültiger Schlüssel:
- Die App wechselt in den Nur-Lesen-Modus — bestehende Daten bleiben zugänglich
- Ticket-Erstellung, Antworten senden und KI-Features sind deaktiviert
- Ein Banner zeigt "Lizenz abgelaufen" mit einem Verlängerungslink
Aktualisierung
# Load new images
docker load < maildesk-images.tar.gz
# Restart (migrations run automatically)
docker compose up -dMigrationen laufen automatisch bei jedem Start — kein manueller Migrationsschritt nötig.
Backup & Wiederherstellung
Backup
Datenbank
docker compose exec postgres pg_dump -U maildesk maildesk > backup_$(date +%Y%m%d).sqlAnhänge
docker compose cp worker:/data/attachments ./attachments-backupRedis (optional — nur Caches, kann neu aufgebaut werden)
docker compose exec redis redis-cli BGSAVEWiederherstellung
Datenbank
docker compose exec -T postgres psql -U maildesk maildesk < backup_20260317.sqlAnhänge
docker compose cp ./attachments-backup/. worker:/data/attachmentsFehlerbehebung
App startet nicht
docker compose logs app
docker compose logs migrateHäufige Ursachen:
- Datenbank nicht bereit — Der migrate-Service wartet auf den Postgres-Healthcheck. Prüfe docker compose ps auf unhealthy Services.
- Ungültige DATABASE_URL — Stelle sicher, dass der Connection-String zu den Postgres-Zugangsdaten passt.
- Port-Konflikt — Wenn Port 3000 belegt ist, ändere das Port-Mapping in docker-compose.yml.
Lizenz-Fehler
docker compose logs app | grep -i license- "License invalid" — Überprüfe ob MAILDESK_LICENSE_KEY korrekt in .env gesetzt ist (keine Zeilenumbrüche, keine Anführungszeichen um das JWT).
- "License expired" — Erneuere deine Lizenz auf maildesk.cloud.
ClamAV startet langsam
ClamAV lädt beim ersten Start Virendefinitionen herunter, was 3–5 Minuten dauern kann.
docker compose logs clamavWorker verarbeitet keine E-Mails
docker compose logs worker- Überprüfe ob die IMAP-Zugangsdaten in den Mailbox-Einstellungen korrekt sind
- Prüfe ob der Worker-Service healthy ist
- Stelle sicher, dass Redis erreichbar ist
Architekturübersicht
┌─────────────┐
│ Reverse │
│ Proxy │
│ (TLS) │
└──────┬──────┘
│ :3000
┌──────▼──────┐
│ App │
│ (Next.js) │
└──┬──────┬───┘
│ │
┌────────▼─┐ ┌─▼────────┐
│ Postgres │ │ Redis │
│ (pgvec) │ │ (queue) │
└────────▲─┘ └─▲────────┘
│ │
┌──┴──────┴───┐
│ Worker │
│ (IMAP/SMTP) │
└──────┬──────┘
│
┌──────▼──────┐
│ ClamAV │
│ (antivirus) │
└─────────────┘- App — App stellt die Web-UI und API-Routen bereit
- Worker — Worker verbindet sich per IMAP mit Mailboxen, sendet Antworten per SMTP, verarbeitet Hintergrund-Jobs
- Postgres — Postgres speichert alle Anwendungsdaten (mit pgvector für KI-Embeddings)
- Redis — Redis verwaltet Job-Queues (BullMQ) und Echtzeit-Pub/Sub (WebSocket)
- ClamAV — ClamAV scannt E-Mail-Anhänge auf Malware