Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Server & Netzwerk 13.09.2026 · 10 min Lesezeit

Zammad 7.2.0 mit Docker Compose installieren und betreiben

Zammad 7.2.0 mit der offiziellen Compose-Datei installieren: Elasticsearch auf kleinen Servern weglassen, Healthcheck-Abbruch des Rails-Servers lösen, Passwörter trennen, Backup, Update von 7.1.3 und Deinstallation. Mit Messwerten aus einem eigenen Testlauf.

Geprüft am 03.10.2026 · für zammad 7.2.0, zammad-docker-compose 17.5.0

WerbelinksMit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Mehr dazu

Schreibtisch mit Headset, zugeklapptem Laptop, Stapeln leerer weißer Karten und Stiftehalter vor einem Bürostuhl

Zammad ist ein quelloffenes Ticketsystem für Support und Service-Desk, hier 7.2.0 mit Docker Compose. Getestet am 13.09.2026 mit 7.1.3 (zwei vCPU, 3 GB freier RAM, Docker 29.1.3) und am 03.10.2026 (Docker 29.8.2, Compose 5.5.1): Update auf 7.2.0, Neuinstallation.

Was Zammad ist und für wen es sich lohnt

Zammad bündelt Anfragen aus E-Mail, Webformular, Telefon, Chat und Social Media als Tickets.

Zwei Nummernkreise: Zammad (7.2.0, ghcr.io/zammad/zammad) und das Repository zammad/zammad-docker-compose (v17.5.0 vom 29.09.2026 mit Tag 7.2.0-0011; 7.2.0 seit v17.4.0 vom 23.09.2026).

  • Passend für Teams ab etwa drei Personen mit gemeinsamem Posteingang und Gruppen je Abteilung.

Grenzen und wann Zammad nicht passt

Mindestens neun Container, darunter PostgreSQL, Redis, Memcached und Elasticsearch.

  • Nicht passend für Hosts unter 4 GB RAM.
  • Nicht passend für reine Inventarverwaltung oder ein einzelnes Kontaktformular.
  • Nicht passend ohne Wartungsfenster für Migrationen; ein Downgrade ist nicht vorgesehen.

Voraussetzungen und realistischer Ressourcenbedarf

Elasticsearch (-Xms1g -Xmx1g) plus Stack (im Test 1,5 GB) passen nicht in 3 GB; im Test lief Zammad ohne Volltextsuche.

RAM laut docker stats --no-stream: scheduler 388, init 382, websocket 277, railsserver 273, PostgreSQL 108 MiB, Rest je unter 30.

  • RAM: mindestens 4 GB ohne Elasticsearch, 6 bis 8 GB mit Elasticsearch.
  • Zwei CPU-Kerne, x86-64 (Rails-Boot rund 170 Sekunden).
  • Mindestens 10 GB freier Speicher (Pull im Test 4,4 GB, Zammad-Image 1,47 GB).
  • Für Elasticsearch: vm.max_map_count mindestens 262144 (sysctl vm.max_map_count).
  • Docker Compose 2.23.1 oder neuer (configs.content), getestet mit 5.5.1.

Unterstützte Plattformen und getestete Versionen

Versionen aus Release v17.5.0, getestet am 03.10.2026 auf Debian 12:

KomponenteImage und TagRolle im Stack
Zammadghcr.io/zammad/zammad:7.2.0-0011init, railsserver, scheduler, websocket, nginx, backup
PostgreSQLpostgres:17.11-alpineDatenhaltung
Redisredis:8.10.2-alpineHintergrundjobs
Memcachedmemcached:1.6.45-alpineCache, 256 MB
Elasticsearchelasticsearch:9.5.3Volltextsuche

Compose-Datei und die wichtigen Blöcke

Laden Sie die docker-compose.yml aus dem Release-Tag v17.5.0, nicht aus master: Compose-Datei und Image-Tag passen dann zusammen.

# Arbeitsverzeichnis anlegen und wechseln
mkdir -p /opt/zammad && cd /opt/zammad
# Compose-Datei des Releases v17.5.0 (Zammad 7.2.0) herunterladen
curl -fsSLO https://raw.githubusercontent.com/zammad/zammad-docker-compose/v17.5.0/docker-compose.yml
# Kontrolle: Standard-Tag muss 7.2.0-0011 sein
grep -n 'VERSION:-' docker-compose.yml

Alle Zammad-Container teilen per YAML-Anker x-shared Image und Umgebung. Wichtig ist der Rails-Healthcheck:

  zammad-railsserver:
    <<: *zammad-service
    command: ["zammad-railsserver"]
    healthcheck:
      test: ["CMD", "curl", "-sf", "http://127.0.0.1:${ZAMMAD_RAILSSERVER_PORT:-3000}"]
      interval: 30s
      timeout: 5s
      start_period: 120s
      retries: 3

Die PostgreSQL-Bootstrap-Rolle ist Superuser; Zammad erhält per initdb eine unprivilegierte Rolle.

  zammad-postgresql:
    environment:
      POSTGRES_USER: ${POSTGRES_SUPERUSER:-postgres}
      POSTGRES_PASSWORD: ${POSTGRES_SUPERUSER_PASS:-${POSTGRES_PASS:-zammad}}
      ZAMMAD_DB: ${POSTGRES_DB:-zammad_production}
      ZAMMAD_DB_USER: ${POSTGRES_USER:-zammad}
      ZAMMAD_DB_PASS: ${POSTGRES_PASS:-zammad}

Härtung: POSTGRES_SUPERUSER_PASS fällt sonst auf POSTGRES_PASS zurück; setzen Sie beide unterschiedlich. initdb läuft nur bei leerem Datenverzeichnis.

Seit v17.1.0 stimmen POSTGRES_SHARED_BUFFERS, POSTGRES_WORK_MEM und POSTGRES_SHM_SIZE PostgreSQL ab; Standardwerte genügen klein.

Verifizieren: grep -n 'VERSION:-' docker-compose.yml zeigt ghcr.io/zammad/zammad}:${VERSION:-7.2.0-0011}.

Umgebungsvariablen in der env-Datei

Anpassungen gehören in eine .env neben der Compose-Datei. Ersetzen Sie die Platzhalter.

NGINX_EXPOSE_PORT=18081
ELASTICSEARCH_ENABLED=false
ELASTICSEARCH_JAVA_OPTS=-Xms256m -Xmx256m
VERSION=7.2.0-0011
POSTGRES_PASS=bitte-ersetzen-app
POSTGRES_SUPERUSER_PASS=bitte-ersetzen-admin
RESTART=on-failure

Weitere relevante Variablen für den Produktivbetrieb:

VariableStandardBedeutung und Hinweis
NGINX_EXPOSE_PORT8080Hostport der Weboberfläche, optional mit 127.0.0.1: davor.
VERSION7.2.0-0011Image-Tag, festschreiben.
POSTGRES_PASSzammadPasswort der Anwendungsrolle, ändern.
POSTGRES_SUPERUSER_PASSWert von POSTGRES_PASSSuperuser-Passwort, separat setzen.
POSTGRES_SUPERUSERpostgresBootstrap-Rolle, muss sich von POSTGRES_USER unterscheiden.
ELASTICSEARCH_ENABLEDleerSchaltet nur die Anbindung ab, nicht den Container.
ELASTICSEARCH_JAVA_OPTS-Xms1g -Xmx1gHeap der Suchmaschine.
ZAMMAD_FQDNleerÖffentlicher Hostname für Links und Mails.
ZAMMAD_HTTP_TYPEhttphttps hinter einem TLS-Proxy.
NGINX_SERVER_SCHEMESchema der Anfragehttps, wenn ein vorgelagerter Proxy TLS beendet (seit 7.2 maßgeblich).
NGINX_SERVER_NAMEleerserver_name des internen nginx.
RAILS_TRUSTED_PROXIESleerNetze des vorgelagerten Proxys.
TZEurope/BerlinZeitzone.
BACKUP_TIME03:00Uhrzeit des integrierten Backups.
HOLD_DAYS10Aufbewahrung in Tagen.
RESTARTalwaysTest on-failure, produktiv always.

Installation Schritt für Schritt

# In das Verzeichnis mit compose-Datei und .env wechseln
cd /opt/zammad
# Syntax und Variablenaufloesung pruefen, ohne etwas zu starten
docker compose config -q
# Stack starten, Elasticsearch bewusst weglassen
docker compose up -d --scale zammad-elasticsearch=0

--scale zammad-elasticsearch=0 verhindert den Start; ELASTICSEARCH_ENABLED=false trennt nur die Anbindung, der Container startet trotzdem. Dauerhaft: replicas: 0 per Override-Datei.

Verifizieren: docker compose config -q endet ohne Ausgabe, docker compose ps listet keinen Elasticsearch-Container.

Start und was dabei wirklich passiert

Test mit 7.1.3: Pull sechs Minuten, Migration zwei, Rails healthy nach 170 Sekunden (vorher dreimal ExitCode 7), HTTP 200 erst nach Nachstart von zammad-nginx; gesamt elf Minuten. Nachtest 7.2.0 mit vorhandenen Images und Override-Datei: zwei Minuten bis HTTP 200.

Ob der Assistent noch aussteht, prüfen Sie ohne Browser:

# Setup-Status der Instanz abfragen
curl -s http://127.0.0.1:18081/api/v1/getting_started

Antwort im Test: {"setup_done":false,"import_mode":false,"import_backend":"","system_online_service":false}.

Der Healthcheck-Abbruch und seine Lösung

Auf kleiner Hardware bricht docker compose up -d ab:

Container test-zammad-zammad-railsserver-1  Error
dependency failed to start: container test-zammad-zammad-railsserver-1 is unhealthy

Health-Log: {"Status":"unhealthy","FailingStreak":3,"Log":[{"ExitCode":7,"Output":""},{"ExitCode":7,"Output":""},{"ExitCode":7,"Output":""}]}. ExitCode 7 heißt connection refused: Rails war noch nicht bereit.

start_period: 120s plus dreimal interval: 30s ergibt rund 210 Sekunden; zammad-nginx hängt per depends_on: service_healthy an Rails und bleibt Created.

Sofortlösung (im Test verifiziert): nach healthy nginx nachstarten; Containername beginnt mit dem Verzeichnisnamen.

# Gesundheitsstatus des Rails-Containers abfragen
docker inspect --format '{{.State.Health.Status}}' zammad-zammad-railsserver-1
# Sobald healthy: nginx nachstarten
docker compose up -d zammad-nginx

Dauerhaft hilft eine docker-compose.override.yml neben der Originaldatei:

services:
  zammad-railsserver:
    healthcheck:
      start_period: 300s
      retries: 10

Verifizieren: curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:18081/ liefert 200, curl -s http://127.0.0.1:18081/api/v1/getting_started zeigt "setup_done":false.

Erstkonfiguration im Browser

Oberfläche: http://SERVER-IP:18081/.

  • Das erste Konto erhält Administratorrechte: persönliches Konto, kein Sammelkonto.
  • Die Basis-URL muss zum öffentlichen Namen passen.
  • E-Mail-Eingang per IMAP oder POP3, Versand getrennt über SMTP.
  • Ohne Elasticsearch finden Sie Tickets über Filter und Übersichten.
  • Erst nach dem Assistenten öffentlich freigeben, sonst kann ein Fremder das Administratorkonto anlegen.

Funktions- und Healthchecks im Betrieb

Der Statuscode-Aufruf eignet sich auch fürs Monitoring.

# Status aller Container des Stacks
docker compose ps
# Erreichbarkeit der Oberflaeche als reiner Statuscode
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:18081/
# Speicherverbrauch aller laufenden Container, einmalige Momentaufnahme
docker stats --no-stream
# Logs des Init-Containers, hier laufen die Migrationen
docker compose logs -f zammad-init

Im Test lastete zammad-init auch nach den Migrationen zeitweise einen Kern aus.

Verifizieren: docker compose ps zeigt alle Dienste außer Elasticsearch als running bzw. healthy.

Persistente Daten und Volumes

Fünf benannte Volumes mit Projektnamen als Präfix (docker volume ls):

  • postgresql-data nach /var/lib/postgresql/data: Datenbank, wichtigstes Volume.
  • zammad-storage nach /opt/zammad/storage: Anhänge und abgelegte Dateien.
  • zammad-backup nach /var/tmp/zammad: integrierte Backups.
  • redis-data nach /data: Hintergrundjobs.
  • elasticsearch-data: Suchindex, neu aufbaubar.

Host-Pfad: /var/lib/docker/volumes/NAME/_data; nur bei gestopptem Container kopieren.

Sichere Netzwerkfreigabe und Reverse Proxy mit TLS

Der nginx-Container spricht nur HTTP; setzen Sie für den TLS-Proxy:

  • ZAMMAD_FQDN, ZAMMAD_HTTP_TYPE=https, NGINX_SERVER_NAME, RAILS_TRUSTED_PROXIES: siehe Tabelle Umgebungsvariablen.
  • NGINX_SERVER_SCHEME=https: Seit 7.2 verwirft der interne nginx Forwarded und X-Forwarded-Ssl. Ohne die Variable fehlt das sichere Session-Cookie, die Anmeldung scheitert mit „CSRF token verification failed!“.
ZAMMAD_FQDN=support.example.com
ZAMMAD_HTTP_TYPE=https
NGINX_SERVER_SCHEME=https
NGINX_SERVER_NAME=support.example.com
RAILS_TRUSTED_PROXIES=172.16.0.0/12

Proxy auf demselben Host: NGINX_EXPOSE_PORT=127.0.0.1:18081, sonst ist Zammad am Proxy vorbei unverschlüsselt erreichbar.

Backup und Wiederherstellung

Der Backup-Container sichert täglich um BACKUP_TIME nach /var/tmp/zammad, Aufbewahrung HOLD_DAYS. Sofortlauf:

# Integriertes Backup sofort ausloesen
docker compose exec -u 0 zammad-backup zammad-backup

Zusätzlich ein eigener Dump (im Test 17 MB):

# Datenbank als SQL-Dump sichern
docker compose exec -T zammad-postgresql pg_dump -U zammad -d zammad_production > zammad.sql
# Anhaenge und Dateien aus dem storage-Volume als Archiv sichern
docker run --rm -v zammad_zammad-storage:/d -v "$PWD":/b alpine \
  tar czf /b/zammad-storage.tgz -C /d .

Üben Sie den Rückweg auf einem Testsystem.

# Anwendungsdienste stoppen, Datenbank laeuft weiter
docker compose stop zammad-railsserver zammad-scheduler zammad-websocket zammad-nginx
# SQL-Dump zurueckspielen
cat zammad.sql | docker compose exec -T zammad-postgresql psql -U zammad -d zammad_production
# Dateien zurueckspielen
docker run --rm -v zammad_zammad-storage:/d -v "$PWD":/b alpine \
  sh -c 'rm -rf /d/* && tar xzf /b/zammad-storage.tgz -C /d'
# Alles wieder hochfahren
docker compose up -d

Updates und die Grenzen des Rollbacks

Update: VERSION auf den neuen Tag setzen, Compose-Datei des passenden Releases laden; zammad-init migriert beim Start.

# In das Stack-Verzeichnis wechseln
cd /opt/zammad
# Neue Images beziehen
docker compose pull
# Stack mit den neuen Images neu erzeugen
docker compose up -d
# Migrationen mitlesen
docker compose logs -f zammad-init

Vorher Datenbank sichern. Laut Dokumentation kein Downgrade, keine Major-Version überspringen; ohne gepinntes VERSION droht bei pull eine irreversible Migration.

Migration bestehender Installationen von 7.1.3 auf 7.2.0

Am 03.10.2026 getestet: frische 7.1.3 (v17.0.0) ohne Eingriffe auf 7.2.0-0011, Migration zwei Minuten, HTTP 200, rails r "puts Version.get" meldete 7.2.0.

cd /opt/zammad
# 1. Datenbank sichern (siehe Abschnitt Backup)
docker compose exec -T zammad-postgresql pg_dump -U zammad -d zammad_production > vor-7.2.sql
# 2. Compose-Datei des Releases v17.5.0 holen, alte Datei vorher sichern
cp docker-compose.yml docker-compose.yml.v17.0.0
curl -fsSLO https://raw.githubusercontent.com/zammad/zammad-docker-compose/v17.5.0/docker-compose.yml
# 3. In der .env VERSION=7.2.0-0011 setzen, dann pruefen und neu starten
docker compose config -q
docker compose pull
docker compose up -d --scale zammad-elasticsearch=0
# 4. Migrationen verfolgen
docker compose logs -f zammad-init

Aus den Release-Notes von Zammad 7.2:

  • Suchindex neu aufbauen (Audit-Log): einmal ELASTICSEARCH_REINDEX=true oder docker compose exec zammad-railsserver bundle exec rake zammad:searchindex:rebuild. Ohne Elasticsearch entfällt das.
  • Reverse Proxy: NGINX_SERVER_SCHEME=https setzen, siehe Abschnitt Reverse Proxy.
  • Elasticsearch: Minimum 8.15, Version 7 entfällt. Der Stack bringt 9.5.3; externe Cluster vorher prüfen.

Ab Compose-Release v17.2.0 ersetzt COMPOSE_FILE in der .env das include: der Override-Datei; ist sie gesetzt, wird die Override-Datei nur gelesen, wenn gelistet.

Verifizieren: docker compose images zeigt den erwarteten Zammad-Tag, docker compose logs zammad-init endet ohne Fehler.

Typische Fehler mit Diagnose und Lösung

Die ersten drei Zeilen beruhen auf eigener Beobachtung.

SymptomUrsacheAbhilfe
dependency failed to start: container zammad-railsserver-1 is unhealthyRails-Boot länger als rund 210 sNach healthy zammad-nginx starten, Override-Datei
Oberfläche nicht erreichbar, zammad-nginx im Status CreatedFolge des Abbruchsdocker compose up -d zammad-nginx
Host läuft beim Start voll, Container werden beendetElasticsearch-Heap 1 GB plus 1,5 GB Stack--scale zammad-elasticsearch=0 oder ELASTICSEARCH_JAVA_OPTS reduzieren
Suche liefert keine Treffer, Tickets sind aber vorhandenElasticsearch läuft nicht oder ist nicht angebundenElasticsearch starten, Reindex
initdb bricht mit Hinweis auf identische Rollen abPOSTGRES_USER und POSTGRES_SUPERUSER tragen denselben NamenNamen ändern, Volume postgresql-data neu anlegen
Links in Benachrichtigungen zeigen auf http oder die interne IPZAMMAD_FQDN und ZAMMAD_HTTP_TYPE nicht gesetztBeide setzen, docker compose up -d
Elasticsearch startet nicht, Hinweis auf max virtual memory areasvm.max_map_count unter 262144Wert in /etc/sysctl.d anheben

Nach Tests entfernt docker compose down --rmi all nur Stack-Images, docker image prune -a auch fremde.

Saubere Deinstallation

Warnung: Der Ablauf löscht Datenbank und Anhänge unwiderruflich (-v), zurück nur per Backup. Zum Stoppen genügt docker compose stop.

# Stack stoppen, ALLE Volumes und die Images des Stacks loeschen, unwiderruflicher Datenverlust
cd /opt/zammad && docker compose down -v --rmi all
# Arbeitsverzeichnis entfernen
cd .. && rm -rf /opt/zammad
# Kontrolle: es darf nichts mehr uebrig bleiben
docker ps -a | grep zammad
docker volume ls | grep zammad

Im Test lieferten beide Kontrollbefehle anschließend eine leere Ausgabe.

Fazit aus dem Testlauf

Zammad 7.2.0 läuft mit offizieller Compose-Datei und .env; Hürden: Rails-Healthcheck, Elasticsearch-RAM.

Vor dem Livegang: TLS-Proxy, geprüfter Restore, Entscheidung zur Volltextsuche.

Passende Anleitungen auf S-EDV

Quellen

ZammadDocker ComposeHelpdeskTicketsystemSelf-HostingPostgreSQLElasticsearch