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 – NIS2- und DSGVO-konform. Diese Anleitung zeigt den Einstieg per Docker Compose in unter 30 Minuten.

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.0.2, Stand Juni 2026) 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 du Vault per Docker Compose auf jedem Linux-Host in Betrieb nimmst.
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 Produktivbetrieb empfehle ich einen 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.0.2 (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. 171–182 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/data | 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
Erstelle 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/configLege 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/data"
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.
Verifizieren: Die Datei muss lesbar sein, bevor du weitermachst.
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
Wechsle ins Projektverzeichnis und lege die compose.yaml an:
# ============================================================
# HashiCorp Vault – Docker Compose (Single-Node, Raft Storage)
# Plattformneutral | Getestet mit Vault 2.0.2
# ============================================================
services:
vault:
image: hashicorp/vault:2.0.2
container_name: vault
restart: unless-stopped
ports:
- "8200:8200"
cap_add:
- IPC_LOCK
volumes:
- ./vault/config:/vault/config:ro
- vault-data:/vault/data
- 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.
Verifizieren:
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.0.2 (ca. 171 MB) herunter und startet den Container.
Verifizieren:
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.0.2 "docker…" vault running 0.0.0.0:8200->8200/tcpLogs auf Fehler prüfen:
docker compose logs vaultDu solltest 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.XXXXXXXXXXXXXXXXXXSpeichere alle 5 Unseal-Keys und den Root-Token jetzt sofort in einem Passwortmanager – niemals in einer .env-Datei, niemals in einem Git-Repository. Verteile 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_3Verifizieren:
docker exec -it vault vault statusErwartetes Ergebnis:
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed false
Total Shares 5
Threshold 3
Version 2.0.2
...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
Öffne im Browser http://localhost:8200/ui (oder die IP-Adresse deines Hosts). Du siehst die Vault-Login-Seite.
- Methode: Token
- Token: der
Initial Root Tokenaus Schritt 4
Nach dem Login siehst du das Vault-Dashboard mit den verfügbaren Secrets Engines. Standardmäßig ist secret/ (KV v2) aktiviert.
Wichtiger Sicherheitshinweis: Der Root-Token hat uneingeschränkte Rechte. Nach der initialen Einrichtung solltest du 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.
Verifizieren: Das Vault-Dashboard lädt vollständig, kein 503-Fehler. Die Secrets-Engine-Liste zeigt mindestens cubbyhole/ und secret/.
Schritt 6: Erstes Secret speichern und abrufen
Teste die Grundfunktion direkt per CLI im Container:
# Mit Root-Token einloggen und Secret schreiben
docker exec -e VAULT_TOKEN=hvs.DEIN_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.DEIN_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-passwortVerifizieren: Das 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 -dNach 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. Eine vollständige Backup-Strategie beschreibt die Anleitung 3-2-1-Backup-Strategie umsetzen.
Verifizieren:
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 obtain lock on data directory": Das Verzeichnis
/vault/dataist nicht beschreibbar für Vault (UID 100). Lösung: Bei Bind-Mountschown -R 100:100 ./vault/dataauf dem Host ausführen. Bei benannten Docker-Volumes (wie in dieser Anleitung) passiert das normalerweise nicht. - „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.0.2(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.0.2 (Stand Juni 2026). Wer bereits 1.x betreibt, kann auf dem 1.21.x-Sicherheitspatch-Track bleiben. Vault 2.0 ist rückwärtskompatibel in der API und der config.hcl-Syntax.
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 Auto-Unseal, Namespaces 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 du es betreibst. Das eingebaute Audit-Logging (jeden API-Aufruf protokollieren) ist ein zentraler Baustein für NIS2- und DSGVO-konforme Credential-Verwaltung. Das File-Audit-Device aktivierst du 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