OpenBao mit Docker installieren: Linux – Zentraler Secrets-Store unter MPL-2.0
OpenBao – der Linux-Foundation-Fork von HashiCorp Vault unter MPL-2.0 – läuft per Docker Compose in 25 Minuten. Diese Anleitung zeigt den vollständigen Weg: compose.yaml, PostgreSQL-Backend, Unseal-Prozess, CLI und Troubleshooting.

Wer Credentials, TLS-Zertifikate und dynamische Datenbankzugänge zentral verwalten möchte, stand bisher vor einer klaren Wahl: HashiCorp Vault – oder nichts Vergleichbares. Seit HashiCorp 2023 die Lizenz auf BSL gewechselt hat, ist diese Wahl für viele Teams rechtlich heikel geworden. OpenBao löst dieses Problem: Der Fork wird von der Linux Foundation betreut, steht unter der MPL-2.0 und ist vollständig API-kompatibel zu Vault. Mit 6.300+ GitHub-Stars und regelmäßigen Releases (aktuell 2.5.4) ist er kein Experiment mehr, sondern produktionstaugliche Software für DevOps-Teams, Entwickler und KMU-Admins, die einen lizenzrechtlich sauberen Secrets-Store brauchen.
Voraussetzungen
- Linux-Host oder VM (Ubuntu 22.04/24.04, Debian 12 oder vergleichbar) mit Docker Engine 24+ und Compose Plugin v2 – wie du Docker und Compose installierst, zeigt die Docker- und Docker-Compose-Grundlage
- Mindestens 512 MB RAM (empfohlen: 1 GB+), mindestens 1 GB freier Speicherplatz
- Netzwerkzugriff auf Port 8200/TCP (API); für Cluster-Replikation zusätzlich 8201/TCP
- Texteditor für
config.hclund.env - Passwortmanager oder sicherer Speicher für Unseal-Schlüssel und Root-Token (z. B. Vaultwarden)
- Optional: Reverse Proxy (Traefik, Nginx, Caddy) für HTTPS – in Produktion Pflicht
Eckdaten: Image, Ports, Volumes und Umgebungsvariablen
| Parameter | Wert | Hinweis |
|---|---|---|
| Image | openbao/openbao:2.5.4 | Stable-Tag pinnen; Multi-Arch: amd64, arm64, armv7, s390x, riscv64, ppc64le |
| Alternatives Image | ghcr.io/openbao/openbao:2.5.4 | GitHub Container Registry als Fallback |
| Port | 8200:8200 | API + (ehem.) UI; 8201 nur für Multi-Node-HA |
| Volume config | ./config:/openbao/config | HCL/JSON-Konfiguration; vor dem ersten Start anlegen |
| Volume data | bao_data:/openbao/file | Persistenter Datenspeicher (File-Backend) |
| Volume logs | bao_logs:/openbao/logs | Audit-Logs; optional, aber empfohlen |
| Env: BAO_LOG_LEVEL | info | trace/debug/info/warn/error |
| Capability | IPC_LOCK | Verhindert Swap-Auslagerung von Secrets – Pflicht |
| User | openbao (non-root) | Volumes müssen schreibbar sein |
Schritt 1: Projektordner anlegen und vorbereiten
Lege einen dedizierten Ordner für OpenBao an. /opt/openbao/ ist für Server-Dienste die übliche Wahl; auf einem NAS oder als normaler Nutzer geht auch ~/openbao/.
mkdir -p /opt/openbao/config
cd /opt/openbaoDas Unterverzeichnis config/ nimmt gleich die config.hcl auf. Docker legt die Named Volumes (postgres_data, bao_data, bao_logs) automatisch an – dafür sind keine weiteren Verzeichnisse nötig.
Verifizieren: ls -la /opt/openbao/ – du solltest config/ als leeres Verzeichnis sehen.
Schritt 2: .env-Datei anlegen
Alle Passwörter und variablen Parameter kommen in die .env-Datei. Diese Datei darf niemals ins Git-Repository.
# /opt/openbao/.env – NICHT in Git einchecken!
POSTGRES_DB=openbao
POSTGRES_USER=openbao
POSTGRES_PASSWORD=SICHER_AENDERN
BAO_LOG_LEVEL=infoErsetze SICHER_AENDERN durch ein starkes, zufälliges Passwort. Enthält das Passwort Sonderzeichen wie @, / oder ?, müssen diese in der connection_url in der config.hcl URL-kodiert werden (z. B. @ → %40), sonst schlägt der PostgreSQL-Verbindungsaufbau mit „invalid dsn" fehl.
chmod 600 /opt/openbao/.envVerifizieren: cat /opt/openbao/.env – alle vier Variablen sichtbar, keine Leerzeilen davor.
Schritt 3: Konfigurationsdatei config.hcl anlegen
OpenBao liest beim Start alle .hcl- und .json-Dateien aus dem gemounteten Konfigurationsverzeichnis. Hier richtest du das PostgreSQL-Storage-Backend ein und deaktivierst TLS für den lokalen Betrieb hinter einem Reverse Proxy.
# /opt/openbao/config/config.hcl
storage "postgresql" {
connection_url = "postgres://openbao:SICHER_AENDERN@postgres:5432/openbao?sslmode=disable"
ha_enabled = "false"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = "true"
}
api_addr = "http://0.0.0.0:8200"
ui = falsePasse SICHER_AENDERN an das Passwort aus deiner .env an. Der Hostname postgres entspricht dem Service-Namen im Compose-Stack – Docker löst ihn intern auf. ha_enabled = "false" ist korrekt für Einzelknoten-Betrieb. tls_disable = "true" ist hinter einem Reverse Proxy akzeptabel; ohne vorgelagerten Proxy unbedingt TLS aktivieren, da sonst Root-Token und Secrets im Klartext übertragen werden.
Verifizieren: cat /opt/openbao/config/config.hcl – Storage-Block, Listener und api_addr vollständig und ohne Tippfehler.
Schritt 4: compose.yaml erstellen und Stack starten
Der Stack besteht aus zwei Services: PostgreSQL als Storage-Backend und OpenBao selbst. Der depends_on-Healthcheck stellt sicher, dass PostgreSQL Verbindungen akzeptiert, bevor OpenBao startet.
# /opt/openbao/compose.yaml
services:
postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: ${POSTGRES_DB:-openbao}
POSTGRES_USER: ${POSTGRES_USER:-openbao}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD muss in .env gesetzt sein}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-openbao} -d ${POSTGRES_DB:-openbao}"]
interval: 10s
timeout: 5s
retries: 5
openbao:
image: openbao/openbao:2.5.4
restart: unless-stopped
cap_add:
- IPC_LOCK
ports:
- "8200:8200"
volumes:
- ./config:/openbao/config
- bao_data:/openbao/file
- bao_logs:/openbao/logs
environment:
BAO_LOG_LEVEL: ${BAO_LOG_LEVEL:-info}
command: ["server", "-config=/openbao/config/config.hcl"]
depends_on:
postgres:
condition: service_healthy
volumes:
postgres_data:
bao_data:
bao_logs:Wichtige Details: cap_add: IPC_LOCK ist Pflicht, damit OpenBao Secrets im RAM sperren und eine Swap-Auslagerung verhindern kann. Ohne diese Capability gibt OpenBao eine Warnung aus und Secrets könnten unverschlüsselt im Swap-Speicher landen. command: ["server", "-config=..."] überschreibt den Standard-Dev-Modus des offiziellen Images – ohne diesen Eintrag würde OpenBao im Dev-Modus starten, bei dem alle Daten nur im RAM liegen und nach einem Neustart verloren sind.
cd /opt/openbao
docker compose up -dVerifizieren:
docker compose psErwartete Ausgabe: beide Services zeigen Status: Up, postgres zusätzlich (healthy).
docker compose logs openbao --tail=20Erwartetes Ergebnis: Zeilen wie core: vault is sealed oder core: security barrier not initialized – das ist korrekt. Keine Fehler zu Port, Volume oder Datenbankverbindung. HTTP 503 von der API in diesem Stadium ist ebenfalls normal und erwartet.
Schritt 5: OpenBao initialisieren und entsiegeln (Unseal)
Nach dem ersten Start befindet sich OpenBao im Sealed-Zustand: Die Barrier ist verschlüsselt und antwortet auf alle API-Anfragen mit HTTP 503. Die Initialisierung erzeugt die fünf Unseal-Schlüssel und den Root-Token.
docker compose exec openbao bao operator initDie Ausgabe enthält fünf Unseal Keys und einen Initial Root Token. Speichere diese Werte sofort in einem sicheren Passwortmanager – sie können nicht wiederhergestellt werden. Bei Verlust aller Unseal-Schlüssel ist der gesamte Datenspeicher dauerhaft verschlüsselt.
Nun entsiegele OpenBao mit mindestens drei der fünf Schlüssel (Shamir-Verfahren). Führe den Befehl dreimal aus und gib jedes Mal einen anderen Schlüssel ein:
docker compose exec openbao bao operator unseal
# Erster Schlüssel eingeben – Unseal Progress: 1/3
docker compose exec openbao bao operator unseal
# Zweiter Schlüssel – Unseal Progress: 2/3
docker compose exec openbao bao operator unseal
# Dritter Schlüssel – Sealed: falseNach jedem Container-Neustart muss das Unseal wiederholt werden. Für automatisierte Umgebungen lässt sich Auto-Unseal per AWS KMS, Azure Key Vault oder einem HSM konfigurieren.
Verifizieren:
curl -s http://localhost:8200/v1/sys/health | python3 -m json.toolErwartete Ausgabe bei erfolgreichem Unseal: HTTP 200 mit "sealed": false und "initialized": true. HTTP 503 bedeutet, OpenBao ist noch versiegelt. Alternativ direkt per CLI:
docker compose exec openbao bao statusDie Spalte Sealed muss false zeigen.
Schritt 6: Ersten Login und Secret anlegen
Mit dem Root-Token meldest du dich an und kannst sofort Secrets verwalten. In der Praxis solltest du schnellstmöglich weitere Policies und Auth-Methoden einrichten, um den Root-Token danach sicher wegzusperren.
# Root-Token setzen (ersetze tttt... durch deinen echten Token)
export BAO_TOKEN=tttt...
export BAO_ADDR=http://localhost:8200
# KV-Secrets-Engine aktivieren
docker compose exec -e BAO_TOKEN=$BAO_TOKEN -e BAO_ADDR=$BAO_ADDR openbao \
bao secrets enable -path=secret kv-v2
# Erstes Secret schreiben
docker compose exec -e BAO_TOKEN=$BAO_TOKEN -e BAO_ADDR=$BAO_ADDR openbao \
bao kv put secret/meine-app db_password="supersicher" api_key="abc123"
# Secret lesen
docker compose exec -e BAO_TOKEN=$BAO_TOKEN -e BAO_ADDR=$BAO_ADDR openbao \
bao kv get secret/meine-appWer lieber mit der REST-API arbeitet, kann denselben Weg per curl gehen – alle Vault-API-Endpunkte sind vollständig kompatibel.
curl -s -H "X-Vault-Token: $BAO_TOKEN" \
http://localhost:8200/v1/secret/data/meine-app | python3 -m json.toolVerifizieren: Die Ausgabe zeigt "db_password": "supersicher" und "api_key": "abc123" unter dem Schlüssel data.data. HTTP 403 deutet auf einen ungültigen Token hin; HTTP 404 bedeutet, der Pfad existiert noch nicht.
Schritt 7: Container aktualisieren
OpenBao erscheint alle ein bis zwei Monate mit einem neuen Release. Beim Update das Image-Tag in der compose.yaml anpassen, dann:
cd /opt/openbao
docker compose pull
docker compose up -dNach dem Neustart ist OpenBao wieder versiegelt – führe das Unseal-Prozedere (drei Schlüssel) erneut durch. Automatisches Container-Monitoring für neue Releases richtest du z. B. mit Diun oder WUD ein.
Verifizieren:
docker compose ps
docker compose exec openbao bao versionDie neue Versionsnummer muss dem Tag in der compose.yaml entsprechen.
Troubleshooting / Typische Fehler
- HTTP 503 nach dem Start: OpenBao ist versiegelt. Normal nach jedem (Neu-)Start. Lösung:
docker compose exec openbao bao operator unsealdreimal mit je einem anderen Unseal-Schlüssel aufrufen. - HTTP 501 – not initialized: Die Initialisierung wurde noch nicht durchgeführt. Lösung:
docker compose exec openbao bao operator initausführen und die Ausgabe sofort sicher speichern. - „failed to lock memory" / IPC_LOCK-Warnung:
cap_add: IPC_LOCKfehlt in dercompose.yaml. Eintrag ergänzen und den Stack neu starten. Ohne diesen Eintrag können Secrets in den Swap-Speicher gelangen. - „invalid dsn" beim Datenbankstart: Das PostgreSQL-Passwort enthält Sonderzeichen (
@,/,?,#), die in derconnection_urlURL-kodiert werden müssen. Beispiel:@→%40. - „error creating core: failed to create storage": PostgreSQL war noch nicht bereit, als OpenBao startete. Der
depends_on-Healthcheck in dercompose.yamlverhindert das – prüfe, ob der Healthcheck korrekt konfiguriert ist. Notfallsdocker compose restart openbao. - „permission denied" beim Datei-Backend: Das Volume-Verzeichnis gehört nicht dem Container-User
openbao. Lösung: UID/GID des Containers prüfen mitdocker compose exec openbao idund Volume-Rechte entsprechend anpassen. - Alle Secrets weg nach Neustart: Du betreibst OpenBao im Dev-Modus. Erkennbar daran, dass kein Unseal nötig war. Lösung:
command: ["server", "-config=/openbao/config/config.hcl"]in dercompose.yamlsetzen und den Stack neu aufsetzen. - Unseal-Schlüssel verloren: Bei Verlust aller Schlüssel ist der Datenspeicher unwiederbringlich verschlüsselt – keine Hintertür, keine Recovery. Einzige Option: Neustart mit leerem Volume. Prävention: Schlüssel per Shamir-Verfahren auf mehrere Personen verteilen oder Auto-Unseal einrichten.
Häufige Fragen
Wie unterscheidet sich OpenBao von HashiCorp Vault?
OpenBao ist ein direkter Fork von Vault, der nach dem BSL-Lizenzwechsel von HashiCorp im Jahr 2023 unter MPL-2.0 weiterentwickelt wird. API, CLI-Syntax und Konfigurationsformat sind weitgehend identisch. Die wesentlichen Unterschiede: Der CLI-Befehl heißt bao statt vault, Umgebungsvariablen beginnen mit BAO_ statt VAULT_, und die Web-UI wurde in OpenBao ab Version 2.1.0 entfernt. Für Teams, die bereits Vault nutzen, ist eine Migration deshalb vergleichsweise reibungsarm.
Muss ich OpenBao nach jedem Neustart manuell entsiegeln?
Im Standardbetrieb mit Shamir-Seal ja – nach jedem Neustart müssen mindestens drei der fünf Unseal-Schlüssel eingegeben werden. Für automatisierten Betrieb lässt sich Auto-Unseal per AWS KMS, Azure Key Vault, GCP KMS oder einem Hardware-Security-Modul (PKCS#11) konfigurieren. Damit öffnet sich OpenBao beim Start automatisch, ohne manuellen Eingriff.
Kann ich OpenBao ohne PostgreSQL betreiben?
Ja – mit dem File-Storage-Backend (storage "file" { path = "/openbao/file" }) ist keine externe Datenbank erforderlich. Das File-Backend ist einfacher einzurichten, unterstützt aber kein High Availability. Für Produktion mit Ausfallsicherheit empfehlen sich das integrierte Raft-Backend oder PostgreSQL.
Gibt es eine Web-Oberfläche für OpenBao?
Nein – ab Version 2.1.0 wurde die Web-UI entfernt. Verwaltung erfolgt ausschließlich per CLI (bao) oder REST-API. Als Alternative können inoffizielle Community-Tools oder direkte API-Abfragen per curl genutzt werden. Die CLI deckt alle Funktionen vollständig ab.
Welche Ports müssen in der Firewall freigegeben werden?
Für Einzelknoten-Betrieb genügt Port 8200/TCP (API). Port 8201/TCP wird nur für Cluster-Kommunikation zwischen mehreren OpenBao-Knoten benötigt und muss nicht nach außen freigegeben werden. Hinter einem Reverse Proxy (Traefik, Nginx, Caddy) reicht es, nur den Proxy-Port (443) öffentlich zu machen.
Wie sichere ich die OpenBao-Daten?
Die Daten liegen im Docker Volume bao_data (File-Backend) bzw. in der PostgreSQL-Datenbank (Volume postgres_data). Für ein zuverlässiges Backup bietet sich eine Kombination aus pg_dump und offsite-Synchronisierung an – wie das funktioniert, zeigt die Anleitung zu PostgreSQL-Backup mit cron und rclone. Bewahre die Unseal-Schlüssel und den Root-Token getrennt von den Datensicherungen auf.
Ist OpenBao für den produktiven Einsatz geeignet?
Ja – das PostgreSQL-Backend gilt als „production ready", der Codebasis liegt der bewährte HashiCorp-Vault-Kern zugrunde, und die Linux Foundation gewährleistet langfristige Pflege unter klarer Open-Source-Lizenz. Für Produktion solltest du TLS (oder einen vorgelagerten Reverse Proxy mit HTTPS), Auto-Unseal und regelmäßige Backups einrichten. Wie du einen Reverse Proxy mit automatischem HTTPS bereitstellst, zeigt Traefik als Docker-Reverse-Proxy.
Fazit
OpenBao ist die konsequente Antwort auf den HashiCorp-Lizenzwechsel: API-kompatibler Vault-Fork, MPL-2.0, Linux Foundation – kein Lizenzrisiko, keine proprietären Abhängigkeiten. Der Betrieb per Docker Compose ist in 25 Minuten eingerichtet; das PostgreSQL-Backend macht den Stack produktionstauglich. Der entscheidende operative Unterschied zu vielen anderen Self-Hosting-Projekten ist der Unseal-Prozess: Unseal-Schlüssel und Root-Token sind nicht wiederherstellbar und müssen von Anfang an sicher aufbewahrt werden. Wer das verinnerlicht und Auto-Unseal für automatisierten Betrieb einplant, bekommt mit OpenBao einen vollständig selbst kontrollierten, lizenzrechtlich sauberen Secrets-Store – ohne Abstriche beim Funktionsumfang.
Weiterführende Anleitungen und Quellen
- Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only für den Produktivbetrieb
- Vaultwarden produktiv betreiben: Argon2-Admin-Token, Fail2Ban und sicheres Backup
- Traefik als Docker-Reverse-Proxy mit automatischem HTTPS
- PostgreSQL-Backup automatisieren mit cron und rclone
- Single Sign-On für den Self-Hosted-Stack: Authentik vs. Authelia mit Traefik Forward-Auth
Offizielle Quellen: OpenBao Installationsdokumentation · GitHub-Repository · Docker Hub Image