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
| Aspekt | Offizieller Stack | Typische Produktionslücke |
|---|---|---|
| Installation | Bewährte Compose-Snippets, .env-Samples | Mehrere Override-Dateien in COMPOSE_FILE — schwer zu überblicken |
| TLS | Integrierter nginx-Override | Security-Header, Rate-Limits und Asset-Caching oft minimal |
| Netzwerk | Ein gemeinsames Docker-Netz | DB, Redis und Elasticsearch theoretisch vom Proxy erreichbar |
| Container-Härtung | Funktional ausgelegt | Root-UIDs, offene Volume-Modi (777), breite Capabilities |
| Performance | Defaults | MariaDB/Redis/ES nicht auf Ticket-Workload getunt |
| Betrieb | scripts/update.sh | Kein 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(nurdocker ps/logs,sudoeditauf 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:
| Prinzip | Umsetzung |
|---|---|
| Reproduzierbarkeit | Image-Tags in .env gepinnt; Upgrade = Tag bump + scripts/upgrade.sh |
| Defense in Depth | cap_drop: ALL, no-new-privileges, Non-Root wo möglich |
| Netzwerk-Segmentierung | frontend (nginx ↔ web) und backend (Datenstores) — DB/Redis/ES nie am Proxy |
| Performance | MariaDB innodb_buffer_pool_size, Redis maxmemory, ES ES_JAVA_OPTS abgestimmt |
| Observability | Healthchecks mit depends_on: condition: service_healthy |
| Ressourcen-Governance | CPU/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ötigecap_addsecurity_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-Limitsinnodb_log_file_size512M (weniger Checkpoint-Churn als 256M-Minimum)max_allowed_packet128M für große Ticket-Anhängeutf8mb4+dynamicRow Format (OTOBO-Pflicht)
Redis
- Reiner Cache:
maxmemory 512mbmitallkeys-lru - Kein Host-Port — nur internes Backend-Netz
Elasticsearch
bootstrap.memory_lock: true+ passendeulimits- 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)
| Service | CPU | RAM | Hinweis |
|---|---|---|---|
| MariaDB | 2 | 2 GB | Buffer Pool synchron halten |
| Elasticsearch | 2 | 2 GB | Heap ≤ 1 GB |
| Web (PSGI) | 2 | 2 GB | OTOBO_WEB_OPTION=deployment in Prod |
| Daemon | 1 | 1 GB | GenericAgent, Eskalationen |
| Redis | 1 | 768 MB | maxmemory < Limit |
| nginx | 1 | 256 MB | nur 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:
- Wiederverwendbarkeit: Andere OTOBO-Admins suchen genau diese Patterns (Hardening, nginx, Tuning).
- Transparenz: Security-relevante Infra gehört in versionierte, reviewbare Dateien — nicht nur in Kundenprojekte.
- 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 forken | Stattdessen |
|---|---|
RotherOSS/otobo-docker | Override-Dateien referenzieren, README verlinkt Upstream |
RotherOSS/otobo Images | Tags 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.
Weiterführende Links
- OTOBO im Open ITSM Hub
- Offizieller otobo-docker Stack
- OTOBO Docker Installationsguide (softoft Community Docs)
- OTOBO 11.1 Kurzüberblick
- Open Ticket AI — Automation für OTOBO & Co.
Geplanter Code-Stand: github.com/Softoft-Orga/otobo-docker-production — Repo wird aus dem IT-Unlimited-Projekt extrahiert.
