HashiCorp Vault mit Docker installieren: Industrie-Standard für Secrets-Management
HashiCorp Vault ist der De-facto-Standard für zentrales Secrets-Management: API-Keys, Zertifikate und Passwörter sicher speichern, rotieren und per Audit-Log nachweisen, passend zu NIS2 und DSGVO. Diese Anleitung zeigt den Einstieg per Docker Compose in unter 30 Minuten.
Werbung Mit * 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

Passwörter in .env-Dateien, API-Keys fest im Code, Datenbankzugänge per E-Mail weitergegeben, das sogenannte „Secrets Sprawl" ist in vielen Teams Alltag und gleichzeitig eines der größten Sicherheitsrisiken. HashiCorp Vault löst dieses Problem mit einem einzigen, abgesicherten Speicherpunkt für alle sensiblen Zugangsdaten: feingranulare Zugriffssteuerung, automatische Rotation, dynamisch generierte Credentials und ein lückenloser Audit-Trail, der jeden Zugriff protokolliert. Mit 35.800+ GitHub-Stars und aktiver Weiterentwicklung (aktuelle stabile Version: 2.2.0) ist Vault de-facto-Standard in professionellen DevOps-Umgebungen, und für KMU im DACH-Raum besonders relevant, weil NIS2 und DSGVO ein nachweisbares, auditfähiges Credential-Management vorschreiben. Diese Anleitung zeigt, wie Sie Vault per Docker Compose auf jedem Linux-Host in Betrieb nehmen.
Voraussetzungen
- Linux-Host, VM oder NAS mit Docker Engine 24+ und Docker Compose v2 (
docker compose, ohne Bindestrich). Falls noch nicht installiert, hilft die Anleitung Docker und Docker Compose auf Linux installieren. - Mindestens 512 MB freier RAM (1 GB empfohlen), mindestens 1 GB freier Speicherplatz für Vault-Daten und Logs.
- Port 8200 lokal erreichbar; für den Produktivbetrieb ist ein Reverse Proxy mit TLS-Terminierung (z. B. Traefik als Docker-Reverse-Proxy).
- Texteditor für die
config.hcl(VS Code, nano, vim). - Passwortmanager oder sicheres Offline-Dokument für die Unseal-Keys und den Root-Token, das ist kein optionales Nice-to-have, sondern Pflicht.
- TLS-Zertifikate für den Produktivbetrieb (self-signed oder per Let's Encrypt).
Eckdaten auf einen Blick
| Eigenschaft | Wert |
|---|---|
| Image | hashicorp/vault:2.2.0 (Verified Publisher) |
| Veraltetes Image | vault (ohne Namespace), eingefroren bei 1.13.3, nicht mehr verwenden! |
| Port API/UI | 8200/tcp |
| Port Cluster (HA) | 8201/tcp (nur intern, nicht exponieren) |
| Architektur | linux/amd64, linux/arm64, linux/386 |
| Image-Größe | ca. 180 bis 190 MB (komprimiert) |
| Vault-User im Container | UID 100 |
| Lizenz | BUSL (Community Edition, kostenlos für die meisten Anwendungsfälle) |
| Volume / Pfad | Zweck |
|---|---|
./vault/config:/vault/config:ro | Konfigurationsverzeichnis mit config.hcl, read-only gemountet |
vault-data:/vault/file | Persistente verschlüsselte Vault-Daten (Raft-Backend), niemals löschen |
vault-logs:/vault/logs | Audit-Logs (wenn File-Audit-Device aktiviert ist) |
Schritt 1: Projektordner und Konfigurationsdatei anlegen
Erstellen Sie zunächst die notwendige Verzeichnisstruktur und die Vault-Konfigurationsdatei. Vault benötigt die config.hcl zwingend vor dem ersten Start, fehlt sie, startet Vault im Dev-Mode (flüchtig, kein TLS, kein persistentes Storage).
$ mkdir -p /opt/vault/vault/configLegen Sie jetzt die Konfigurationsdatei an. Das Integrated-Storage-Backend (Raft) ist die offizielle Empfehlung von HashiCorp: Es benötigt keine externe Datenbank und unterstützt bei Bedarf HA-Clustering.
cat > /opt/vault/vault/config/config.hcl <<'EOF'
ui = true
disable_mlock = true
storage "raft" {
path = "/vault/file"
node_id = "vault-node-1"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = true
}
api_addr = "http://127.0.0.1:8200"
cluster_addr = "http://127.0.0.1:8201"
EOFHinweis zu disable_mlock = true: In vielen Docker-Umgebungen kann das Container-Capability IPC_LOCK nicht gesetzt werden (z. B. Rootless Docker, bestimmte Hosting-Anbieter). disable_mlock = true deaktiviert das Memory-Locking, das ist ein Sicherheitskompromiss, den HashiCorp explizit benennt. Für Produktivumgebungen gilt: entweder Swap deaktivieren bzw. verschlüsseln, oder das Capability IPC_LOCK explizit im Compose setzen (was wir in Schritt 2 tun) und disable_mlock dann weglassen.
Hinweis zu TLS: tls_disable = true ist für lokale Entwicklung akzeptabel. Im Produktivbetrieb mit externem Zugriff zwingend TLS aktivieren oder einen Reverse Proxy vorschalten.
Die Datei muss lesbar sein, bevor Sie weitermachen.
$ cat /opt/vault/vault/config/config.hclErwartetes Ergebnis: Der Inhalt der config.hcl wird vollständig ausgegeben, kein „No such file or directory".
Schritt 2: compose.yaml erstellen
Wechseln Sie ins Projektverzeichnis und legen Sie die compose.yaml an:
# ============================================================
# HashiCorp Vault – Docker Compose (Single-Node, Raft Storage)
# Plattformneutral | Getestet mit Vault 2.2.0
# ============================================================
services:
vault:
image: hashicorp/vault:2.2.0
container_name: vault
restart: unless-stopped
ports:
- "8200:8200"
cap_add:
- IPC_LOCK
volumes:
- ./vault/config:/vault/config:ro
- vault-data:/vault/file
- vault-logs:/vault/logs
command: server
environment:
- VAULT_ADDR=http://127.0.0.1:8200
healthcheck:
test: ["CMD", "vault", "status", "-address=http://127.0.0.1:8200"]
interval: 30s
timeout: 10s
retries: 5
start_period: 30s
volumes:
vault-data:
driver: local
vault-logs:
driver: localWichtige Details zu dieser Konfiguration:
command: serverist Pflicht, ohne diesen Befehl startet Vault im Dev-Mode (alles im RAM, keine Persistenz).cap_add: IPC_LOCKerlaubt Vault, sensible Speicherbereiche zu sperren, damit sie nicht in den Swap ausgelagert werden.- Die Volumes
vault-dataundvault-logswerden als benannte Docker-Volumes angelegt, das vereinfacht Backups und verhindert Berechtigungsprobleme (Vault läuft als UID 100). configwird read-only (:ro) gemountet, Vault hat keinen Schreibzugriff auf seine eigene Konfiguration.- Das
version:-Feld wurde bewusst weggelassen, Docker Compose v2 ignoriert es und gibt sonst eine Warnung aus.
$ docker compose config --quiet && echo "compose.yaml OK"Erwartetes Ergebnis: compose.yaml OK, keine Syntaxfehler.
Schritt 3: Container starten
$ cd /opt/vault
$ docker compose up -dDocker lädt das Image hashicorp/vault:2.2.0 (ca. 190 MB) herunter und startet den Container.
$ docker compose psErwartetes Ergebnis (Vault ist gestartet, aber noch sealed, das ist korrekt in diesem Stadium):
NAME IMAGE COMMAND SERVICE STATUS PORTS
vault hashicorp/vault:2.2.0 "docker…" vault running 0.0.0.0:8200->8200/tcpLogs auf Fehler prüfen:
$ docker compose logs vaultSie sollten Zeilen wie => Vault server started! Log data will stream in below: sehen. Kein Error bezüglich fehlender Konfigurationsdatei oder Berechtigungsprobleme.
API-Endpunkt direkt abfragen:
$ curl -s http://localhost:8200/v1/sys/health | python3 -m json.toolErwartetes Ergebnis: HTTP-Status 501 (Not Initialized), das bedeutet, Vault läuft korrekt, wurde aber noch nicht initialisiert. Das ist der erwartete Zustand vor der Ersteinrichtung.
Schritt 4: Vault initialisieren und entsperren
Dieser Schritt ist einmalig und kritisch: vault operator init generiert die Unseal-Keys und den initialen Root-Token. Diese Ausgabe wird nur ein einziges Mal angezeigt, wer sie verliert, verliert dauerhaft den Zugriff auf alle Vault-Daten.
docker exec -it vault vault operator init \
-key-shares=5 \
-key-threshold=3Die Parameter bedeuten: Vault generiert 5 Unseal-Keys (-key-shares=5), von denen mindestens 3 benötigt werden, um Vault zu entsperren (-key-threshold=3). Das ist das Shamir-Secret-Sharing-Verfahren: Kein einzelner Mitarbeiter besitzt alle Keys allein.
Die Ausgabe sieht so aus:
Unseal Key 1: AAAA...
Unseal Key 2: BBBB...
Unseal Key 3: CCCC...
Unseal Key 4: DDDD...
Unseal Key 5: EEEE...
Initial Root Token: hvs.XXXXXXXXXXXXXXXXXXSpeichern Sie alle 5 Unseal-Keys und den Root-Token jetzt sofort in einem Passwortmanager, niemals in einer .env-Datei, niemals in einem Git-Repository. Verteilen Sie die Keys idealerweise auf verschiedene Personen oder Systeme.
Jetzt Vault mit 3 der 5 Keys entsperren (jeden Befehl einzeln ausführen, jeweils einen anderen Key verwenden):
$ docker exec -it vault vault operator unseal UNSEAL_KEY_1
$ docker exec -it vault vault operator unseal UNSEAL_KEY_2
$ docker exec -it vault vault operator unseal UNSEAL_KEY_3$ docker exec -it vault vault statusErwartetes Ergebnis:
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed false
Total Shares 5
Threshold 3
Version 2.2.0
...Der entscheidende Wert: Sealed: false. Zusätzlich per API prüfen:
$ curl -s -o /dev/null -w "%{http_code}" http://localhost:8200/v1/sys/healthErwartetes Ergebnis: 200: Vault ist initialisiert und entsperrt.
Schritt 5: Web-UI aufrufen und ersten Login durchführen
Öffnen Sie im Browser http://localhost:8200/ui (oder die IP-Adresse Ihres Hosts). Sie sehen die Vault-Login-Seite.
- Methode: Token
- Token: der
Initial Root Tokenaus Schritt 4
Nach dem Login sehen Sie das Vault-Dashboard mit den verfügbaren Secrets Engines. Im Server-Mode sind zunächst nur cubbyhole/ und die Systempfade aktiv; die KV-Engine unter secret/ aktivieren Sie in Schritt 6.
Wichtiger Sicherheitshinweis: Der Root-Token hat uneingeschränkte Rechte. Nach der initialen Einrichtung sollten Sie feingranulare Policies und Auth-Methoden anlegen (z. B. AppRole für Dienste, Username/Password für Personen) und den Root-Token anschließend widerrufen (vault token revoke). Das ist Best Practice und wird von HashiCorp ausdrücklich empfohlen.
Das Vault-Dashboard lädt vollständig, kein 503-Fehler. Die Secrets-Engine-Liste zeigt mindestens cubbyhole/.
Schritt 6: Erstes Secret speichern und abrufen
Testen Sie die Grundfunktion direkt per CLI im Container:
# KV-Engine Version 2 unter secret/ aktivieren (einmalig)
docker exec -e VAULT_TOKEN=hvs.IHR_ROOT_TOKEN -it vault \
vault secrets enable -path=secret kv-v2
# Secret schreiben
docker exec -e VAULT_TOKEN=hvs.IHR_ROOT_TOKEN -it vault \
vault kv put secret/test/app api_key="mein-geheimer-schluessel" db_pass="sicheres-passwort"
# Secret wieder auslesen
docker exec -e VAULT_TOKEN=hvs.IHR_ROOT_TOKEN -it vault \
vault kv get secret/test/appErwartetes Ergebnis:
====== Secret Path ======
secret/data/test/app
======= Metadata =======
Key Value
--- -----
created_time 2026-06-11T...
version 1
====== Data ======
Key Value
--- -----
api_key mein-geheimer-schluessel
db_pass sicheres-passwortDas Secret wird vollständig zurückgegeben, Versionsnummer ist 1. Vault KV v2 speichert automatisch eine Versionshistorie, ältere Versionen bleiben abrufbar.
Schritt 7: Updates und Backup
Vault-Updates sind für die Konfiguration unkritisch, die HCL-Syntax ist rückwärtskompatibel. Vor einem Update immer ein Backup des Volumes erstellen:
# Backup des Vault-Data-Volumes
docker run --rm \
-v vault_vault-data:/data \
-v /opt/vault/backup:/backup \
alpine tar czf /backup/vault-backup-$(date +%Y%m%d-%H%M).tar.gz -C /data .
# Image auf neue Version aktualisieren
cd /opt/vault
docker compose pull
docker compose up -dHinweis zu Vault 2.2: Die Release Notes zu 2.2.0 führen bei den Container-Images Änderungen an der Capability cap_ipc_lock als Breaking Change und empfehlen für Container ausdrücklich disable_mlock = true in der Konfiguration, dazu abgeschalteten Swap auf dem Host. Die config.hcl aus Schritt 1 setzt diesen Wert bereits. Prüfen Sie bei eigenen Konfigurationen ohne diese Zeile vor dem Update, ob sie gesetzt ist. Außerdem lehnt die PKI-Engine bei ACME mit der Standardrichtlinie sign-verbatim seit 2.1.2 CSRs mit URI-, E-Mail- oder sonstigen SANs ab. Im Test lief das Update von 2.1.1 auf 2.2.0 mit dieser Anleitung: Nach dem Neustart war Vault versiegelt, nach drei Unseal-Keys meldete vault status die Version 2.2.0, und ein vorher geschriebenes KV-Secret war unverändert lesbar. Mit disable_mlock = true startete 2.2.0 auch ohne cap_add: IPC_LOCK und gab das Secret zurück.
Nach einem Update (Container-Neustart) ist Vault wieder sealed und muss erneut mit 3 Keys entsperrt werden, das ist normal und gewollt. Wer diesen Schritt automatisieren möchte, kann Auto-Unseal per AWS KMS, Azure Key Vault oder HashiCorp Cloud Platform einrichten. Hinweis für Bestandsinstallationen: Frühere Fassungen dieser Anleitung banden das Datenvolume unter /vault/data ein. Läuft Ihre Instanz damit, ändern Sie den Pfad nicht nachträglich, sonst findet Vault seine Daten nicht mehr. Für Neuinstallationen gilt /vault/file. Eine vollständige Backup-Strategie beschreibt die Anleitung 3-2-1-Backup-Strategie umsetzen.
$ docker compose ps
$ docker exec -it vault vault status | grep "Version"Erwartetes Ergebnis: Container läuft, Version entspricht dem neuen Tag. Nach Update-Neustart: Vault mit 3 Keys unseal, dann Sealed: false.
Troubleshooting / Typische Fehler
- Vault antwortet mit 503 oder „connection refused" nach Neustart
Nach jedem Container-Neustart ist Vault automatisch sealed. Status prüfen:
docker exec -it vault vault status. WennSealed: true, mit mindestens 3 Unseal-Keys entsperren.- „Error initializing storage of type raft: failed to create fsm: failed to open bolt file: open /vault/data/vault.db: permission denied"
Das Datenverzeichnis ist für Vault (UID 100) nicht beschreibbar. Das passiert, wenn das Volume unter
/vault/dataeingebunden ist: Diesen Pfad legt der Entrypoint des offiziellen Images nicht mit passenden Rechten an, der Container startet dann in einer Neustartschleife. Nutzen Sie wie in dieser Anleitung/vault/file(Volume undpathin derconfig.hcl); diesen Ordner übergibt der Entrypoint beim Start an den Benutzervault. Bei Bind-Mounts setzen Sie die Rechte zusätzlich mitchown -R 100:1000 ./vault/file.- „No configuration file found" oder Vault startet im Dev-Mode
Die
config.hclfehlt oder das Volume-Mapping ist falsch. Prüfen mit:docker exec -it vault cat /vault/config/config.hcl. Das Verzeichnis./vault/config/muss auf dem Host existieren und die Datei enthalten, bevordocker compose upausgeführt wird.- „Failed to lock memory" oder IPC_LOCK-Warning
In Rootless-Docker-Umgebungen kann
cap_add: IPC_LOCKnicht gesetzt werden. Alternative:disable_mlock = truein dieconfig.hcleintragen (Sicherheitskompromiss, nur wenn Swap deaktiviert oder verschlüsselt ist).- Healthcheck schlägt dauerhaft fehl (Status: „unhealthy")
Vault ist sealed, der Healthcheck-Befehl
vault statusgibt Exit-Code ungleich 0 zurück, solange Vault nicht entsperrt ist. Nach dem Unseal normalisiert sich der Status automatisch.- Image
vault(ohne Namespace) wird verwendet: Dieses Image steckt bei Version 1.13.3 fest und erhält keine Sicherheits-Updates mehr. Ausschließlichhashicorp/vault:2.2.0(mit Namespace) verwenden.- Init-Ausgabe verloren
Wenn Unseal-Keys und Root-Token nicht gesichert wurden, gibt es keinen Recovery-Weg. Das Volume enthält nur verschlüsselte Daten, die ohne Keys wertlos sind. Vault müsste neu initialisiert werden, gleichbedeutend mit Datenverlust.
Häufige Fragen
Brauche ich PostgreSQL oder Redis als Begleit-Container?
Nein. Vault bringt mit dem Integrated-Storage-Backend (Raft) sein eigenes eingebettetes Key-Value-Backend mit, keine externe Datenbank notwendig. Externe Backends (PostgreSQL, Consul, MySQL) sind technisch möglich, aber für KMU-Einsatz unnötige Komplexität.
Was ist der Unterschied zwischen Dev-Mode und Server-Mode?
Der Dev-Mode (docker run hashicorp/vault ohne server-Befehl) speichert alles im RAM, startet mit einem bekannten Root-Token, hat kein TLS und verliert alle Daten beim Neustart. Er eignet sich ausschließlich zum Ausprobieren der API. Der Server-Mode (command: server + config.hcl) ist persistent, erfordert manuelle Initialisierung und Unseal, und ist der einzige Modus für echten Betrieb.
Was tue ich, wenn Vault nach einem Neustart nicht erreichbar ist?
Vault ist nach jedem Neustart automatisch sealed, das ist ein gewolltes Sicherheitsfeature. Status prüfen: docker exec -it vault vault status. Wenn Sealed: true, mit mindestens 3 Unseal-Keys entsperren. Wer diesen manuellen Schritt vermeiden möchte, kann Auto-Unseal über einen externen Key-Management-Service einrichten.
Wie sichere ich Vault-Daten?
Das Docker-Volume vault-data enthält alle verschlüsselten Vault-Daten. Regelmäßige Backups erstellen:
docker run --rm \
-v vault_vault-data:/data \
-v /opt/vault/backup:/backup \
alpine tar czf /backup/vault-backup-$(date +%Y%m%d).tar.gz -C /data .Wichtig: Die Backup-Datei ist ohne die Unseal-Keys wertlos, Keys und Backup unbedingt getrennt aufbewahren.
Welche Vault-Version soll ich verwenden, 2.0.x oder 1.21.x?
Für Neuinstallationen empfiehlt sich die aktuelle stabile Version 2.2.0. Für 1.21.x ist seit März 2026 (1.21.4) kein neues Community-Image mehr auf Docker Hub erschienen; wer noch 1.x betreibt, sollte daher auf 2.2 wechseln. Vault 2.x ist in der API und der config.hcl-Syntax rückwärtskompatibel. Seit 2.0.4 schlagen HCL-Dateien mit doppelten Attributen (z. B. zweimal ui) beim Parsen fehl; prüfen Sie Konfiguration und Policies vor dem Update darauf.
Ist HashiCorp Vault kostenlos?
Die Community-Edition steht seit Vault 1.14 unter der BUSL-Lizenz (Business Source License) und ist für die meisten Anwendungsfälle kostenlos. Enterprise-Features wie Namespaces, Performance-Replikation und HSM-Support erfordern eine kostenpflichtige Enterprise-Lizenz.
Ist Vault NIS2- und DSGVO-konform einsetzbar?
Vault selbst ist ein Werkzeug, die Compliance hängt davon ab, wie Sie es betreiben. Das eingebaute Audit-Logging (jeden API-Aufruf protokollieren) ist ein zentraler Baustein für NIS2- und DSGVO-konforme Credential-Verwaltung. Das File-Audit-Device aktivieren Sie nach dem Login mit: vault audit enable file file_path=/vault/logs/audit.log.
Fazit
HashiCorp Vault ist kein leichtgewichtiges Tool, der initiale Setup-Aufwand (Konfigurationsdatei, Initialisierung, Unseal-Prozess) ist bewusst so gestaltet, dass Sicherheit nicht aus Versehen umgangen werden kann. Wer einmal verstanden hat, wie Sealed/Unsealed-Zustand und Shamir-Secret-Sharing funktionieren, bekommt dafür eine der robustesten Secrets-Management-Lösungen am Markt: zentrales Credential-Management, feingranulare Zugriffssteuerung, vollständiges Audit-Log und die Möglichkeit, dynamische Credentials zu generieren, die nach TTL-Ablauf automatisch erlöschen. Für KMU im DACH-Raum, die NIS2- und DSGVO-Anforderungen an auditfähiges Credential-Management nachweisen müssen, ist Vault die überzeugendste Open-Source-Option.
Wer parallel dazu einen zentralen Identity-Provider für SSO sucht, findet in der Geschwister-Anleitung Zitadel mit Docker installieren eine hervorragende Ergänzung zu Vault. Für den Einstieg in sichere Docker-Compose-Konfigurationen generell lohnt sich außerdem Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only.
Weiterführende Anleitungen und Quellen
- Docker und Docker Compose auf Linux installieren, die Self-Hosting-Grundlage
- Traefik als Docker-Reverse-Proxy mit automatischem HTTPS einrichten
- Zitadel mit Docker installieren: Cloud-nativer Identity-Server
- Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only
- 3-2-1-Backup-Strategie umsetzen: Anleitung mit Restic, USB-Disk und S3-Cloud
Offizielle Quellen: HashiCorp Vault Dokumentation | hashicorp/vault auf Docker Hub | HashiCorp Vault GitHub Repository


