SOGo 5.12.9 auf ARM64 mit Docker Compose und ISPConfig – Komplettanleitung

Warum SOGo selbst hosten?

SOGo (Scalable OpenGroupware.org) ist eine Open-Source-Groupware-Lösung mit Webmail, Kalender (CalDAV), Kontakten (CardDAV) und ActiveSync-Unterstützung. Perfekt als selbst-gehosteter Ersatz für Google Workspace oder Microsoft 365 – komplett unter eigener Kontrolle.

In dieser Anleitung baust du SOGo komplett von Source auf einem ARM64-Server (z.B. Raspberry Pi 5, Ampere, AWS Graviton) und integrierst es mit ISPConfig und deinem eigenen Mailserver – alles als Docker-Compose-Stack.

Architektur

                     ┌──────────────┐
                     │   Nginx      │ (SSL, Reverse Proxy)
                     │   :443       │
                     └──────┬───────┘
                            │
                     ┌──────▼───────┐
                     │   Apache     │ (SOGo VirtualHost)
                     │   :80        │
                     └──┬───────┬──┘
                        │       │
          ┌─────────────▼─┐  ┌──▼─────────────┐
          │ SOGo (sogod)  │  │ Static Files    │
          │ Port 20000    │  │ /WebServerRes. │
          └───────┬───────┘  └────────────────┘
                  │
    ┌─────────────┼─────────────┐
    │             │             │
┌───▼────┐  ┌────▼────┐  ┌─────▼──────┐
│PostgreSQL│ │Memcached│ │ Sphinx      │
│DB :5432  │ │ :11211  │ │ Fulltext    │
└──────────┘ └─────────┘ │ :9306/9312  │
                          └────────────┘

1. Voraussetzungen

  • ARM64-Server mit Ubuntu 24.04 LTS (Raspberry Pi 5, VPS, etc.)
  • Docker & Docker Compose installiert
  • ISPConfig (für Mailserver-Integration und User-Verwaltung)
  • Mailserver mit IMAP/SMTP/Sieve (z.B. Dovecot + Postfix)
  • Mindestens 5 GB freier Speicher

2. Multi-Stage Dockerfile (Source Build für ARM64)

Da es keine offiziellen SOGo ARM64-Binaries gibt, kompilieren wir SOPE und SOGo selbst. Das Multi-Stage-Dockerfile hält das finale Image schlank:

FROM ubuntu:24.04 AS builder

RUN apt-get update && apt-get install -y --no-install-recommends 
    build-essential gobjc gobjc++ gnustep-make gnustep-base-runtime 
    gnustep-base-common libgnustep-base-dev libxml2-dev libldap2-dev 
    libpq-dev default-libmysqlclient-dev libssl-dev libcurl4-openssl-dev 
    libsbjson-dev zlib1g-dev libsodium-dev libzip-dev uuid-dev 
    libmemcached-dev libytnef0-dev wget ca-certificates pkg-config

WORKDIR /build

# SOPE Framework
RUN wget -q https://packages.sogo.nu/sources/SOPE-5.12.9.tar.gz -O SOPE.tar.gz 
    && tar xzf SOPE.tar.gz 
    && cd SOPE-5.12.9 
    && . /usr/share/GNUstep/Makefiles/GNUstep.sh 
    && ./configure && make -j$(nproc) && make install && ldconfig

# SOGo Application
RUN wget -q https://packages.sogo.nu/sources/SOGo-5.12.9.tar.gz -O SOGo.tar.gz 
    && tar xzf SOGo.tar.gz 
    && cd SOGo-5.12.9 
    && . /usr/share/GNUstep/Makefiles/GNUstep.sh 
    && ./configure && make -j$(nproc) && make install


FROM ubuntu:24.04

RUN apt-get update && apt-get install -y --no-install-recommends 
    gnustep-base-runtime gnustep-base-common libgnustep-base-dev 
    libxml2-dev libpq-dev libssl-dev libcurl4-openssl-dev libmemcached-dev 
    apache2 cron curl sudo ca-certificates tzdata netcat-openbsd

# Copy compiled libs from builder
COPY --from=builder /usr/local/sbin/ /usr/local/sbin/
COPY --from=builder /usr/local/lib/ /usr/local/lib/
RUN ldconfig

# Fix DNS resolution for linked containers
COPY fix_bind.c /tmp/fix_bind.c
RUN gcc -shared -fPIC -o /usr/local/lib/fix_bind.so /tmp/fix_bind.c -ldl

# Enable Apache modules
RUN a2enmod proxy proxy_http rewrite headers expires setenvif

EXPOSE 80
ENTRYPOINT ["/entrypoint.sh"]

3. docker-compose.yml – Der Komplett-Stack

services:
  postgresql:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: sogo
      POSTGRES_PASSWORD: DEIN_SICHERES_PASSWORT
      POSTGRES_DB: sogo
      POSTGRES_INITDB_ARGS: --encoding=UTF8 --locale=en_US.UTF-8
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init-db.sql:/docker-entrypoint-initdb.d/01-init.sql:ro
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U sogo"]
      interval: 10s
      retries: 5
    restart: always

  sogo:
    image: sogo:5.12.9-ubuntu24
    depends_on:
      postgresql: { condition: service_healthy }
    volumes:
      - ./sogo.conf:/etc/sogo/sogo.conf:ro
      - ./apache-sogo.conf:/etc/apache2/sites-enabled/sogo.conf:ro
      - sogo_lib:/var/lib/sogo
      - sogo_log:/var/log/sogo
    ports:
      - "8080:80"
    restart: always
    healthcheck:
      test: ["CMD", "curl", "-f", "http://127.0.0.1:80/SOGo/"]
      interval: 15s
      retries: 5

  memcached:
    image: memcached:alpine
    command: memcached -m 256 -t 4 -c 1024
    restart: always

  sphinx:
    build:
      context: .
      dockerfile: sphinx-build/Dockerfile
    volumes:
      - sphinx_data:/var/lib/sphinx
    ports:
      - "9312:9312"
      - "9306:9306"
    restart: always

volumes:
  postgres_data: {}
  sogo_lib: {}
  sogo_log: {}
  sphinx_data: {}

4. SOGo Konfiguration (sogo.conf)

Die zentrale Konfigurationsdatei. Hier die wichtigsten Abschnitte:

Datenbank (PostgreSQL)

SOGoProfileURL = "postgresql://sogo:DEIN_PASSWORT@postgresql:5432/sogo";
OCSFolderInfoURL = "postgresql://sogo:DEIN_PASSWORT@postgresql:5432/sogo";
OCSSessionsFolderURL = "postgresql://sogo:DEIN_PASSWORT@postgresql:5432/sogo";

Wichtig: Der Connection-String endet auf /sogo (Datenbankname), nicht auf /sogo/table. Letzteres ist ein FATALER Fehler, der zum Crash führt!

IMAP und SMTP

SOGoIMAPServer = "imaps://mail.DEINE-DOMAIN.de:993";
SOGoSMTPServer = "smtp://mail.DEINE-DOMAIN.de:25";
SOGoSieveServer = "sieve://mail.DEINE-DOMAIN.de:4190";
SOGoForceExternalLoginWithEmail = YES;

Memcached und Performance

SOGoMemcachedHost = "memcached:11211";
WOWorkersCount = 10;
SOGoMaximumMessageSizeLimit = 102400;
WOMaxUploadSize = 102400;

ActiveSync (für Smartphones)

SOGoEnableActiveSync = YES;
SOGoMaximumPingInterval = 10;
SOGoMaximumSyncInterval = 30;
SOGoMaximumSyncWindowSize = 100;

Sicherheit

SOGoEncryptionKey = "DEIN_32_ZEICHEN_ZUFALLSSTRING";
SOGoXSRFValidationEnabled = YES;
SOGoEnableCookieSecure = YES;
WOSessionTimeout = 3600;

Generiere den Encryption Key mit: openssl rand -hex 16

Volltextsuche (Sphinx)

SOGoEnableFullTextSearch = YES;
SOGoFullTextSearchServer = "sphinx://sphinx:9306";

Optionale Features

SOGoEnableGroupware = YES;          // Kalender, Kontakte, Aufgaben
SOGoEnableSharedFolders = YES;      // Freigegebene Ordner
SOGoEnableDelegation = YES;         // Rechte delegieren
SOGoEnableEMailReceipts = YES;      // Lesebestätigungen
SOGoEnableTasksSupport = YES;       // Aufgabenverwaltung
SOGoVacationEnabled = YES;          // Abwesenheitsnotizen
SOGoForwardEnabled = YES;           // E-Mail-Weiterleitung
SOGoSieveScriptsEnabled = YES;      // Server-seitige Filter
SOGoMailComposeMessageType = html;  // HTML-E-Mails
SOGoLanguage = German;
SOGoTimeZone = "Europe/Berlin";

5. ISPConfig Integration – User aus MariaDB lesen

SOGo kann sich direkt mit der ISPConfig-Datenbank verbinden und User authentifizieren. Dazu musst du in ISPConfig einen MySQL-User mit Lesezugriff auf die dbispconfig-Datenbank anlegen:

CREATE USER 'sogoread'@'%' IDENTIFIED BY 'DEIN_PASSWORT';
GRANT SELECT ON dbispconfig.* TO 'sogoread'@'%';
FLUSH PRIVILEGES;

In sogo.conf:

SOGoUserSources = (
  {
    type = sql;
    id = users;
    viewURL = "mysql://sogoread:DEIN_PASSWORT@HOST_IP:3306/dbispconfig/sogo_users";
    canAuthenticate = YES;
    isAddressBook = YES;
    userPasswordAlgorithm = "sha512-crypt";
    loginFields = (c_uid);
    mailFieldNames = (c_mail);
    CNFieldName = c_cn;
    UIDFieldName = c_uid;
    displayName = "Benutzer";
  }
);

ISPConfig-Host-Erreichbarkeit: Falls ISPConfig auf dem Docker-Host läuft, verwende host.docker.internal (Docker Desktop) oder die Docker-Gateway-IP 172.17.0.1. Falls ISPConfig in einem anderen Container läuft, verwende den Container-Namen.

6. Apache als interner SOGo-Reverse-Proxy

Innerhalb des Containers läuft Apache als Reverse-Proxy vor SOGo:

<VirtualHost *:80>
    ServerName webmail.DEINE-DOMAIN.de
    ServerAlias webmail.DEINE-ZWEITE-DOMAIN.de

    Alias /SOGo/WebServerResources/ /usr/local/lib/GNUstep/SOGo/WebServerResources/

    <Directory /usr/local/lib/GNUstep/SOGo/>
        AllowOverride None
        Require all granted
    </Directory>

    <Location /SOGo>
        RequestHeader set "x-webobjects-server-port" "443"
        RequestHeader set "x-webobjects-server-name" "%{HOST}e"
        RequestHeader set "x-webobjects-server-url" "https://%{HOST}e"
        RequestHeader unset "x-webobjects-remote-user"
    </Location>

    ProxyPreserveHost On
    ProxyPass /Microsoft-Server-ActiveSync 
        http://127.0.0.1:20000/SOGo/Microsoft-Server-ActiveSync 
        retry=60 connectiontimeout=5 timeout=360
    ProxyPass /SOGo http://127.0.0.1:20000/SOGo retry=0 nocanon
    ProxyPassReverse /SOGo http://127.0.0.1:20000/SOGo

    # .well-known Redirects für CalDAV und CardDAV
    RewriteEngine On
    RewriteRule ^/.well-known/caldav/?$  /SOGo/dav [R=301]
    RewriteRule ^/.well-known/carddav/?$ /SOGo/dav [R=301]

    RedirectMatch ^/$ /SOGo
</VirtualHost>

7. Nginx Reverse Proxy (extern, vor dem Container)

Für SSL-Terminierung und Domain-Verwaltung setzt du einen Nginx-Reverse-Proxy VOR den Docker-Container. Beispiel-Serverblock:

server {
    listen 443 ssl http2;
    server_name webmail.DEINE-DOMAIN.de;

    ssl_certificate     /etc/ssl/DEINE-DOMAIN/fullchain.pem;
    ssl_certificate_key /etc/ssl/DEINE-DOMAIN/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        client_max_body_size 100M;
    }
}

8. Entrypoint-Skript

Das Skript startet Cron, Apache und sogod mit korrekten Umgebungsvariablen:

#!/bin/bash
set -e

# Pfade und Rechte
mkdir -p /var/spool/sogo
chown -R sogo:sogo /var/lib/sogo /var/log/sogo /var/run/sogo
chmod 750 /var/lib/sogo /var/log/sogo /var/run/sogo

# Services starten
service cron start
apachectl start

# LD_LIBRARY_PATH für selbst-kompilierte SOGo-Bibliotheken
export LD_LIBRARY_PATH="/usr/local/lib:/usr/local/lib/sogo:/usr/local/lib/GNUstep"
export LD_PRELOAD="/usr/local/lib/fix_bind.so"

# sogod starten
exec gosu sogo /usr/local/sbin/sogod 
    -WOWorkersCount 10 
    -WOListenQueueSize 500 
    -WOPidFile /var/run/sogo/sogo.pid 
    -WOLogFile /var/log/sogo/sogo.log 
    -WONoDetach YES 
    -WOApplicationBaseURL "https://webmail.DEINE-DOMAIN.de/SOGo" 
    -WOPort 20000 2>&1

Das LD_PRELOAD mit fix_bind.so behebt ein bekanntes DNS-Problem in SOGo-Containern bei der Auflösung anderer Container-Namen.

9. Datenbank-Initialisierung

PostgreSQL wird mit einer init-db.sql gestartet, die die benötigten Tabellen anlegt. SOGo verwaltet seine Tabellen über die OCS*FolderURL-Parameter automatisch. Für ISPConfig-Benutzer brauchst du eine View sogo_users in der dbispconfig-Datenbank:

CREATE VIEW sogo_users AS
  SELECT
    email AS c_uid,
    login AS c_uid,
    CONCAT(vorname, ' ', nachname) AS c_cn,
    email AS c_mail,
    password AS c_password
  FROM mail_user;

10. Bereit bekannte Fehler & Fixes

„PostgreSQL verbindet nicht“

✅ Prüfe, ob das Passwort in beiden Dateien identisch ist: sogo.conf und docker-compose.yml

SOGo startet, aber kein Login möglich

✅ Prüfe die ISPConfig-DB-Erreichbarkeit. Der SOGo-Container muss die MariaDB erreichen können. Teste mit: docker-compose exec sogo nc -zv HOST_IP 3306

„AH00558: Could not reliably determine“ Apache-Warnung

✅ Normal – Apache läuft hinter Nginx. Diese Warnung kann ignoriert werden.

sogod crasht direkt nach Start

✅ Häufigste Ursache: PostgreSQL-URL enthält einen Tabellennamen (z.B. /sogo/sogo_user_profile). Korrekt ist nur der Datenbankname: /sogo

ActiveSync funktioniert nicht

✅ Teste: curl -I https://webmail.DEINE-DOMAIN.de/Microsoft-Server-ActiveSync – sollte HTTP 200 liefern

CalDAV/CardDAV funktioniert nicht

✅ Teste: curl -I https://webmail.DEINE-DOMAIN.de/.well-known/caldav – sollte HTTP 301 Redirect liefern

11. Deployment-Checkliste

  1. sogo.conf mit echten Werten befüllen (Passwörter, Domains, ISPConfig-Host)
  2. docker-compose.yml: POSTGRES_PASSWORD mit sogo.conf abgleichen
  3. SOGoEncryptionKey generieren: openssl rand -hex 16
  4. ISPConfig-View sogo_users in MariaDB anlegen
  5. MySQL-User sogoread mit SELECT-Rechten anlegen
  6. Nginx-Serverblock für SSL + Reverse-Proxy erstellen
  7. docker-compose up -d
  8. docker-compose ps – alle Container healthy?
  9. curl -f https://webmail.DEINE-DOMAIN.de/SOGo/ – HTTP 200?
  10. 🎉 Login mit ISPConfig-Mailadresse testen!

12. Wartung & Monitoring

Täglich prüfen:

docker-compose ps
docker-compose logs sogo --tail 20 | grep ERROR

Wöchentlich:

docker system df                # Speicher-Check
docker-compose logs --tail 200

Monatlich:

docker image prune -a           # Alte Images entfernen
docker volume prune             # Ungenutzte Volumes

Backup:

# PostgreSQL-Dump
docker-compose exec postgresql pg_dump -U sogo sogo > backup.sql

# Volumes sichern
tar -czf volumes-backup.tar.gz /var/lib/docker/volumes/sogo_*

Fazit

Du hast jetzt einen vollständigen Groupware-Server mit Webmail, Kalender, Kontakten, Aufgaben und ActiveSync – komplett unter eigener Kontrolle, auf ARM64, mit ISPConfig-Integration und Docker Compose.

Das Setup funktioniert produktiv mit: Ubuntu 24.04 LTS, SOGo 5.12.9 (Source Build), PostgreSQL 15, Memcached, Apache und Nginx als Reverse-Proxy.

🔗 Weitere Projekte auf GitHub

X

Basti

Entwickler und Smart-Home-Enthusiast aus Deutschland. Ich entwickle Open-Source-Integrationen für Home Assistant (IDM Wärmepumpe, Violet Pool Controller), Modbus-Tools (ModBridge) und betreibe verschiedene Server-Dienste (Matrix, Seafile, SOGo).

GitHub →

Schreibe einen Kommentar