OTOBO Docker: Sicherer und performanter mit gehärtetem Docker Compose

2026-07-11

Praxisleitfaden zu gehärtetem OTOBO-Docker-Compose — Netzwerk-Segmentierung, Non-Root-Container, nginx-TLS-Proxy, Ressourcenlimits und ein Hardening-Overlay für den offiziellen RotherOSS-Stack.

OTOBO Docker: Sicherer und performanter mit gehärtetem Docker Compose

Der offizielle RotherOSS/otobo-docker-Stack bringt OTOBO schnell ans Laufen — Web, MariaDB, Elasticsearch, Redis und optional Nginx in wenigen Minuten. Für Produktionsbetrieb reicht „läuft“ oft nicht: Volume-Berechtigungen, fehlende Netzwerk-Trennung, Root-Container und ungepinnte Images sind typische Schwachstellen, die Admins erst unter Last oder im Security-Audit entdecken.

Dieser Artikel fasst zusammen, wie sich OTOBO Docker absichern und tunen lässt — ohne am offiziellen Image-Release-Zyklus vorbeizubauen.


Ausgangslage: Was der Standard-Stack gut macht — und wo es hakt

AspektOffizieller StackTypische Produktionslücke
InstallationBewährte Compose-Snippets, .env-SamplesMehrere Override-Dateien in COMPOSE_FILE — schwer zu überblicken
TLSIntegrierter nginx-OverrideSecurity-Header, Rate-Limits und Asset-Caching oft minimal
NetzwerkEin gemeinsames Docker-NetzDB, Redis und Elasticsearch theoretisch vom Proxy erreichbar
Container-HärtungFunktional ausgelegtRoot-UIDs, offene Volume-Modi (777), breite Capabilities
PerformanceDefaultsMariaDB/Redis/ES nicht auf Ticket-Workload getunt
Betriebscripts/update.shKein Least-Privilege-Modell für technische Admins

Ab OTOBO 11.1 haben OTOBO Core und OTOBO Docker unabhängige Release-Zyklen — ein guter Zeitpunkt, die Infrastruktur-Schicht bewusst zu ownen, statt nur Images zu pullen.


Zwei sinnvolle Ansätze

1. Hardening-Overlay (für bestehende otobo-docker-Installationen)

Wer bereits den offiziellen Stack nutzt, kann ein Compose-Override plus Host-Skript nachrüsten — ohne den Upstream-Workflow zu verlieren:

  • Non-Root-UIDs für Web, Daemon, DB, Redis und Elasticsearch
  • Config-Bind-Mount nach /opt/otobo-config/ (read-only im Container)
  • Volume-Berechtigungen von 777 auf service-spezifische Owner (z. B. 1000:1000, 999:999)
  • Least-Privilege-Sudo für die Gruppe otobo-admin (nur docker ps/logs, sudoedit auf Config, kein Root-Shell)

Das Overlay wird in COMPOSE_FILE angehängt und per Skript idempotent angewendet — inklusive Backup der Docker-Volumes vor dem Neustart.

2. Project-owned Compose-Stack (Greenfield / kontrollierte Upgrades)

Für neue Deployments lohnt sich ein eigener, schlanker Compose-Stack unter docker/:

docker-compose.yml          # Basis-Topologie (db, redis, elastic, web, daemon)
docker-compose.dev.yml      # HTTP auf :8080, DB nur localhost
docker-compose.prod.yml     # nginx TLS-Proxy, keine direkten Host-Ports
config/mariadb/otobo.cnf    # InnoDB-Tuning (utf8mb4, buffer pool)
config/redis/redis.conf     # maxmemory + LRU-Eviction
config/nginx/               # TLS, Security-Header, Static-Cache, Rate-Limits

Designprinzipien:

PrinzipUmsetzung
ReproduzierbarkeitImage-Tags in .env gepinnt; Upgrade = Tag bump + scripts/upgrade.sh
Defense in Depthcap_drop: ALL, no-new-privileges, Non-Root wo möglich
Netzwerk-Segmentierungfrontend (nginx ↔ web) und backend (Datenstores) — DB/Redis/ES nie am Proxy
PerformanceMariaDB innodb_buffer_pool_size, Redis maxmemory, ES ES_JAVA_OPTS abgestimmt
ObservabilityHealthchecks mit depends_on: condition: service_healthy
Ressourcen-GovernanceCPU/Memory-Limits pro Service

In Produktion terminiert nur nginx TLS; der OTOBO-Web-Container bleibt intern auf Port 5000.


Sicherheit im Detail

Netzwerk: Frontend vs. Backend

networks:
  frontend:   # nginx ↔ web
  backend:    # web/daemon ↔ db/redis/elastic

Datenbank und Cache sind nicht im gleichen Netz wie der Reverse Proxy. Selbst bei einem kompromittierten nginx-Container bleibt ein direkter Zugriff auf MariaDB ausgeschlossen.

Container-Härtung

Jeder Service startet mit:

  • cap_drop: [ALL] plus minimal nötige cap_add
  • security_opt: [no-new-privileges:true]
  • dedizierte Linux-User (mysql:mysql, redis:redis, UID-Mapping für OTOBO)

nginx als einziger Einstiegspunkt

Der Produktions-Override setzt:

  • HTTP → HTTPS Redirect
  • TLS 1.2/1.3 (Mozilla Intermediate Profile)
  • HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy
  • Rate-Limiting und Connection-Limits auf dynamische Requests
  • Proxy-Cache für /otobo-web/-Assets (Skins, JS, CSS) — entlastet Perl/PSGI

Config außerhalb des Containers

Config.pm und Kernel/Config/Files/ liegen auf dem Host unter /opt/otobo-config/ und werden read-only gemountet. Änderungen laufen über sudoedit — nicht über docker exec als Root im laufenden Container.


Performance im Detail

MariaDB

  • innodb_buffer_pool_size ≈ 70–80 % des DB-Container-Limits
  • innodb_log_file_size 512M (weniger Checkpoint-Churn als 256M-Minimum)
  • max_allowed_packet 128M für große Ticket-Anhänge
  • utf8mb4 + dynamic Row Format (OTOBO-Pflicht)

Redis

  • Reiner Cache: maxmemory 512mb mit allkeys-lru
  • Kein Host-Port — nur internes Backend-Netz

Elasticsearch

  • bootstrap.memory_lock: true + passende ulimits
  • JVM-Heap ≤ 50 % des Container-Memory-Limits
  • Host-Kernel: vm.max_map_count=262144

nginx Static Cache

Statische Assets werden sieben Tage am Proxy gecacht (X-Cache-Status-Header zur Diagnose). Dynamische Ticket-Requests bleiben ungecacht, aber rate-limited.


Ressourcen-Budget (Richtwerte)

ServiceCPURAMHinweis
MariaDB22 GBBuffer Pool synchron halten
Elasticsearch22 GBHeap ≤ 1 GB
Web (PSGI)22 GBOTOBO_WEB_OPTION=deployment in Prod
Daemon11 GBGenericAgent, Eskalationen
Redis1768 MBmaxmemory < Limit
nginx1256 MBnur Prod

Minimum-Host: 8 GB RAM, 2 vCPU, 50 GB SSD. Für produktive Teams eher 16 GB.


GitHub-Repo: Ja — und wo?

Ja, ein öffentliches Repo macht Sinn — aus drei Gründen:

  1. Wiederverwendbarkeit: Andere OTOBO-Admins suchen genau diese Patterns (Hardening, nginx, Tuning).
  2. Transparenz: Security-relevante Infra gehört in versionierte, reviewbare Dateien — nicht nur in Kundenprojekte.
  3. SEO & Community: Verlinkung aus Open ITSM Hub, softoft.de und otobo-docs stärkt das OTOBO-Ökosystem.

Empfohlene Heimat: Softoft-Orga

Unter github.com/Softoft-Orga passt es neben open-ticket-ai und otobo-znuny-python-client — als Community-Infrastruktur, nicht als Fork von RotherOSS.

Vorgeschlagener Repo-Name: otobo-docker-production

Struktur:

otobo-docker-production/
├── overlay/                 # Für Nutzer des offiziellen RotherOSS-Stacks
│   ├── otobo-override-hardening.yml
│   ├── harden-docker.sh
│   └── otobo-admin.sudoers
├── compose/                 # Vollständiger project-owned Stack
│   ├── docker-compose.yml
│   ├── docker-compose.dev.yml
│   ├── docker-compose.prod.yml
│   ├── config/
│   └── scripts/
└── README.md                # Entscheidungshilfe: Overlay vs. Compose

Was nicht ins Repo gehört

Nicht upstream forkenStattdessen
RotherOSS/otobo-dockerOverride-Dateien referenzieren, README verlinkt Upstream
RotherOSS/otobo ImagesTags pinnen, Images pullen
Kundenspezifische .env-Secrets.env.example mit Platzhaltern
TLS-Private-Keys.gitignore + Cert-Generation-Skript

Upstream-Beiträge

Generische Verbesserungen (z. B. Default-Volume-Permissions, dokumentierte Non-Root-UIDs) können als Issues oder PRs an RotherOSS/otobo-docker — der Overlay-Ansatz bleibt unabhängig vom Merge-Tempo.


Quick Start (Compose-Stack)

git clone https://github.com/Softoft-Orga/otobo-docker-production.git
cd otobo-docker-production/compose
cp .env.example .env
# OTOBO_DB_ROOT_PASSWORD setzen

# Entwicklung (HTTP)
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d

# Produktion (TLS)
./scripts/gen-selfsigned-cert.sh helpdesk.example.com   # oder echtes Zertifikat
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

Web-Installer: https://<fqdn>/otobo/installer.pl — DB-Host = db.


Quick Start (Hardening-Overlay)

Für bestehende /opt/otobo-docker-Installationen:

# Nach dem Klonen des overlay/-Ordners
bash harden-docker.sh              # Volume-Fix, Override, Sudoers, Neustart
bash harden-docker.sh --dry-run    # Nur anzeigen
bash harden-docker.sh --add-admin max.mustermann

Fazit

Der offizielle OTOBO-Docker-Stack ist der richtige Einstieg. Für Produktion lohnt sich eine bewusste Schicht darüber:

  • Overlay — schnell, upstream-kompatibel, für Bestandsinstallationen
  • Eigener Compose-Stack — maximale Kontrolle, klare Dev/Prod-Trennung, reproduzierbare Upgrades

Beides ist Open Source wert — und gehört in ein dediziertes GitHub-Repo unter Softoft-Orga, nicht in open-itsm-hub (Verzeichnis/Content) und nicht als Fork von RotherOSS.


Geplanter Code-Stand: github.com/Softoft-Orga/otobo-docker-production — Repo wird aus dem IT-Unlimited-Projekt extrahiert.