Save products you love by clicking the heart icon.
Designing systems that prompt AI agents instead of prompting them yourself — automations, worktrees, skills, MCP connectors, subagents, and the state file that makes loops durable.
Eine gründliche Evaluierung von SOGo 6, der Next.js/Flask-Groupware-Suite, betrieben mit Stalwart Mailserver und OpenLDAP via Docker Compose. Behandelt Architektur, Feature-Implementierung, SSO, MFA und >1.800 bestandene Tests.
SOGo 6 ist ein grundlegender Neubau der SOGo-Groupware-Suite. Nach 20 Jahren AngularJS und Objective-C in SOGo 5 liefert die neue Version ein Python/Flask-REST-API-Backend, ein Next.js-16-Frontend, PostgreSQL für Persistenz, Redis für Caching und Task-Queues sowie eine richtige Admin-API, die das alte sogo-tool-CLI ersetzt. Die erste öffentliche Beta ist für Sommer 2026 geplant.
Dieser Artikel beschreibt einen produktionsnahen Docker-Compose-Stack, der SOGo 6 mit Stalwart (einem All-in-One-IMAP/SMTP/Sieve-Mailserver) und OpenLDAP (für Benutzerauthentifizierung) verbindet. Der vollständige Quellcode befindet sich unter github.com/tobias-weiss-ai-xr/sogo6-stalwart-openldap-dockerized.
Der Stack umfasst acht Services auf einem gemeinsamen Docker-Netzwerk:
┌──────────────────┐ ┌──────────────────┐
│ SOGo 6 UI │ │ SOGo 6 Server │
│ Next.js :3000 │◄───►│ Flask :5000 │
└──────────────────┘ └──────┬───────────┘
│
┌───────────────────────┼───────────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ PostgreSQL │ │ Redis │ │ OpenLDAP │
│ :5432 │ │ :6379 │ │ :389 │
└──────────────┘ └──────────────┘ └──────┬───────┘
│
▼
┌──────────────┐
│ Stalwart │
│ IMAP/SMTP │
│ /Sieve │
└──────────────┘
Ein Nginx-Reverse-Proxy terminiert TLS auf den Ports 80/443, leitet /api/ an das Flask-Backend weiter und alles andere an das Next.js-Frontend. Ein MailDev-Container fängt ausgehende E-Mails während des Tests ab.
Jeder Service hat Ressourcen-Limits, Health Checks und Abhängigkeitsreihenfolge in der docker-compose.yaml. Der gesamte Speicherbedarf liegt bei etwa 2 GB.
Das Backend ist eine Gunicorn/Flask-Anwendung mit einer RESTful-API. Sie verbindet sich mit PostgreSQL für Datenpersistenz (Kalender, Adressbücher, Benutzereinstellungen), Redis für Session-Caching und die Celery-Task-Queue sowie OpenLDAP für die Authentifizierung.
Wichtige Umgebungsvariablen:
SOGO_DB_URI: postgresql://sogo:sogo@sogo6-postgres:5432/sogo
SOGO_REDIS_URI: redis://sogo6-redis:6379/0
SOGO_LDAP_URI: ldap://sogo6-ldap:389
SOGO_LDAP_BASE_DN: dc=example,dc=org
SOGO_LDAP_BIND_DN: cn=admin,dc=example,dc=org
SOGO_SMTP_SERVER: sogo6-stalwart
SOGO_SMTP_PORT: 20025
SOGo 6 teilt die Konfiguration in zwei Ebenen:
process.conf-Datei. Der Container mountet diese read-only unter /etc/sogo/process.conf.Der Server bietet zwei API-Bereiche:
| API | Basis-Pfad | Zweck |
|---|---|---|
| Benutzer-API | /api/user/v1/ | E-Mail, Kalender, Kontakte für authentifizierte Nutzer |
| Admin-API | /api/admin/v1/ | Systemkonfiguration, Nutzerquellen-Verwaltung, Domain-Einst. |
Das Frontend ist eine Next.js-16-Anwendung (React 19, TypeScript, Tailwind CSS). Die einzige Konfiguration ist die API-Basis-URL — sie leitet alle Datenanfragen an das Flask-Backend weiter. Der UI-Container ist zustandslos und unabhängig skalierbar.
Stalwart ist ein in Rust geschriebener All-in-One-Mailserver. Er ersetzt den klassischen Stack aus Postfix + Dovecot + Rspamd durch eine einzige Binärdatei, die alle gängigen Mail-Protokolle unterstützt:
In diesem Stack verwendet Stalwart PostgreSQL als Storage-Backend (separate Datenbank von SOGo). Die Konfiguration ist eine einzelne JSON-Datei:
{
"@type": "PostgreSql",
"host": "sogo6-postgres",
"port": 5432,
"database": "stalwart",
"authUsername": "stalwart",
"authSecret": {
"@type": "Value",
"secret": "stalwart_sogo6_2026"
}
}
Stalwart v0.16 (hier verwendet) führte eine vereinheitlichte JMAP-basierte Management-API und einen stalwart-cli apply-Befehl für deklarative Konfiguration ein — passt natürlich zu Infrastructure-as-Code-Workflows.
Port-Mappings exposen alle Mail-Protokolle zum Host für Client-Tests:
| Interner Port | Host-Port | Protokoll |
|---|---|---|
| 25 | 20025 | SMTP |
| 465 | 20465 | SMTPS |
| 587 | 20587 | Submission |
| 143 | 20143 | IMAP |
| 993 | 20993 | IMAPS |
| 4190 | 24190 | ManageSieve |
OpenLDAP stellt das Benutzerverzeichnis bereit. Das Docker-Image wird mit eingebauten Seed-Daten gebaut — drei Testnutzer (zwei Standard, ein Admin) werden aus einer LDIF-Datei beim ersten Start geladen.
dn: uid=testuser@example.org,ou=users,dc=example,dc=org
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: testuser@example.org
cn: Test User
sn: User
mail: testuser@example.org
userPassword: password123
Der Health Check führt eine LDAP-Suche gegen den Base-DN durch, um zu verifizieren, dass slapd reagiert.
Ein Hinweis: Die ch_calloc-Assertion von OpenLDAP schlägt fehl, wenn Docker ein hohes ulimit -n setzt. Das Custom-Entrypoint-Skript umgeht dies, indem es ulimit -n 1024 vor dem Start von slapd setzt.
Nginx terminiert TLS (selbstsignierte Zertifikate, generiert vom mitgelieferten gen-certs.sh-Skript) und leitet Traffic weiter:
/api/* → sogo6-server:5000 (Flask-Backend)/* → sogo6-ui:3000 (Next.js-Frontend)Die Konfiguration unterstützt WebSocket-Upgrade-Header für Server-Sent Events und zukünftige Echtzeit-Features.
/api/user/v1/auth/loginSOGO_LDAP_BIND_DN und verifiziert das Passwort gegen den inetOrgPerson-EintragAuthorization: Bearer-Headersogo6-stalwart:25)http://localhost:1080 zur Inspektion bereitSOGo 6 implementiert CalDAV- und CardDAV-Server. Kalenderereignisse und Adressbucheinträge werden in PostgreSQL gespeichert. LDAP-Kontakte werden in Echtzeit aus OpenLDAP gelesen.
git clone https://github.com/tobias-weiss-ai-xr/sogo6-stalwart-openldap-dockerized.git
cd sogo6-stalwart-openldap-dockerized
bash sogo6/scripts/setup.sh
Das Setup-Skript:
secrets/sogo6.vault.env, gitignored)sogo6/nginx/certs/)docker compose up -d
Docker Compose startet Services in Abhängigkeitsreihenfolge — PostgreSQL, Redis, LDAP und Stalwart werden healthy, bevor das Flask-Backend startet, und das Backend muss healthy sein, bevor das Next.js-Frontend startet.
bash sogo6/scripts/init-sogo6.sh
Dieses Skript ruft die Admin-API auf, um Folgendes zu konfigurieren:
example.orgdocker compose ps # Alle 8 Services healthy
curl http://localhost:3000/env # Next.js-Frontend antwortet
curl http://localhost:5001/api/user/v1/system # Flask-API antwortet
curl http://localhost:1080 # MailDev-Web-UI
| Service | URL |
|---|---|
| SOGo 6 UI | http://localhost:3000 |
| Benutzer-API | http://localhost:5001/api/user/v1/system |
| Admin-API | http://localhost:5001/api/admin/v1/auth/login |
| Swagger (Benutzer) | http://localhost:5001/swagger-basic |
| Swagger (Admin) | http://localhost:5001/swagger-admin |
| MailDev | http://localhost:1080 |
| Nginx (TLS) | https://localhost |
| Benutzername | Passwort | Rolle |
|---|---|---|
testuser@example.org | password123 | Standardnutzer |
testadmin@example.org | password123 | Admin (sogoAdminRole) |
testuser2@example.org | password123 | Standardnutzer |
Das Repository liefert 129 shell-basierte Integrationstests, die nichts weiter als bash, curl und openssl benötigen. Sie umfassen:
| Suite | Prüfungen | Was validiert wird |
|---|---|---|
docker-test.sh | 6 | Container-Health, Restarts, Uptime, Netzwerkverbindung |
api-test.sh | 15 | API-Health, Swagger, Auth (alle 3 Nutzer), Negativtests |
smtp-test.sh | 14 | SMTP EHLO, Submission, IMAP-Login, Sieve, TLS-Protokoll |
ldap-test.sh | 6 | LDAP-Ereichbarkeit, Nutzer vorhanden, Mail-Attribute |
postgres-test.sh | 6 | DB-Verbindung, Schema, Server-Version |
nginx-test.sh | 8 | HTTP/HTTPS-Proxy, TLS-Zertifikat, Security Headers |
redis-test.sh | 7 | PING, SET/GET, Speicher, verbundene Clients |
integration-test.sh | 9 | Cross-Service-Token-Flow, CORS, DNS-Auflösung |
security-test.sh | 12 | Port-Exposition, Container-User, TLS-Gültigkeit, Secrets |
script-test.sh | 15 | Config-Integrität, Shebangs, JSON-Gültigkeit, Cert-Key |
Alles ausführen mit bash tests/run-all-tests.sh. Python-Integrationstests (pytest + psycopg2) und Playwright-E2E-Tests sind als optionale Extras verfügbar.
bash sogo6/scripts/manage-secrets.sh # Vault generieren
bash sogo6/scripts/manage-secrets.sh --list # Secrets maskiert auflisten
bash sogo6/scripts/manage-secrets.sh --env-file # Export für docker-compose
bash sogo6/scripts/backup.sh
Erstellt ein zeitgestempeltes Archiv aller Docker-Volumes (PostgreSQL, Redis, Stalwart, LDAP-Daten und -Konfiguration) in ./backups/.
docker compose down -v
docker compose up -d
bash sogo6/scripts/init-sogo6.sh
Für Produktions-Tests die selbstsignierten Zertifikate in sogo6/nginx/certs/ durch echte Zertifikate ersetzen und neu generieren:
bash sogo6/scripts/gen-certs.sh
| Aspekt | SOGo 5 | SOGo 6 |
|---|---|---|
| Frontend | AngularJS | Next.js 16, React 19, TypeScript |
| Backend | Objective-C / GNUstep | Python 3.10+, Flask, Gunicorn |
| Konfiguration | sogo.conf-Datei | Prozess-Einstellungen (Env/Datei) + dynamische Einst. (DB + API) |
| Cache | Memcached | Redis (Session-Cache + Celery-Task-Queue) |
| Datenbank | MySQL/MariaDB/PostgreSQL | PostgreSQL erforderlich |
| Admin-Tool | sogo-tool-CLI | RESTful Admin-API + Web-UI |
| Mobile-Sync | ActiveSync | MAPI over HTTP (ActiveSync geplant nach Release) |
| Architektur | Monolithisch | Modular (API → Interface → Module → Manager) |
| Deployment | Einzelner Container | Minimum drei Container (UI, Server, Agent) |
| Migration | — | Skripte bereitgestellt; alte sogo.conf via Admin-API importierbar |
Das SOGo-Team kündigte auf der FOSDEM 2026 an, dass die öffentliche Beta für Sommer 2026 geplant ist. Das erste Release umfasst die vollständige Web-Anwendung (E-Mail, Kalender, Kontakte), wird aber zunächst keinen Desktop-Sync-Server enthalten.
Der gesamte Code ist Open Source unter der MIT-Lizenz: